/src/CMake/Source/cmPkgConfigParser.h
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | |
4 | | #pragma once |
5 | | |
6 | | #include "cmConfigure.h" // IWYU pragma: keep |
7 | | |
8 | | #include <cstddef> |
9 | | #include <set> |
10 | | #include <string> |
11 | | #include <unordered_map> |
12 | | #include <vector> |
13 | | |
14 | | #include <cmllpkgc/llpkgc.h> |
15 | | |
16 | | struct cmPkgConfigValueItem |
17 | | { |
18 | | cmPkgConfigValueItem() = default; |
19 | | cmPkgConfigValueItem(std::string text, bool isSubstitution); |
20 | | |
21 | | std::string Text; |
22 | | bool IsSubstitution = false; |
23 | | }; |
24 | | |
25 | | enum class cmPkgConfigEntryKind |
26 | | { |
27 | | Property, |
28 | | Variable, |
29 | | Barewords, |
30 | | }; |
31 | | |
32 | | struct cmPkgConfigEntry |
33 | | { |
34 | | cmPkgConfigEntry() = default; |
35 | | cmPkgConfigEntry(std::vector<cmPkgConfigValueItem> value, std::string ident, |
36 | | cmPkgConfigEntryKind kind); |
37 | | |
38 | | std::vector<cmPkgConfigValueItem> Value; |
39 | | std::string Ident; |
40 | | cmPkgConfigEntryKind Kind = cmPkgConfigEntryKind::Barewords; |
41 | | }; |
42 | | |
43 | | class cmPkgConfigFileParser : private llpkgc_file_t |
44 | | { |
45 | | friend class cmPkgConfigParser; |
46 | | |
47 | | public: |
48 | | cmPkgConfigFileParser(); |
49 | | cmPkgConfigFileParser(cmPkgConfigFileParser const& other); |
50 | | cmPkgConfigFileParser(cmPkgConfigFileParser&& other) noexcept; |
51 | | cmPkgConfigFileParser& operator=(cmPkgConfigFileParser const& other); |
52 | | cmPkgConfigFileParser& operator=(cmPkgConfigFileParser&& other) noexcept; |
53 | | |
54 | | llpkgc_file_errno_t Parse(char const* input, std::size_t len); |
55 | | llpkgc_file_errno_t Finish(); |
56 | | void Resume(); |
57 | | |
58 | | llpkgc_file_errno_t GetErrno() const; |
59 | | char const* ErrorReason() const; |
60 | | std::ptrdiff_t ErrorOffset(char const* base) const; |
61 | | |
62 | | private: |
63 | | void ResetCallbacks(); |
64 | | |
65 | | int OnIdentNext(char const* at, std::size_t len); |
66 | | static int OnIdentNextTr(llpkgc_file_t* parser, char const* at, |
67 | | std::size_t len); |
68 | | |
69 | | void AppendValue(std::string text, bool isSubstitution); |
70 | | |
71 | | int OnSpanNext(char const*, std::size_t len); |
72 | | static int OnSpanNextTr(llpkgc_file_t* parser, char const* at, |
73 | | std::size_t len); |
74 | | |
75 | | int OnIdent(char const* at, std::size_t len); |
76 | | static int OnIdentTr(llpkgc_file_t* parser, char const* at, std::size_t len); |
77 | | |
78 | | int OnPropertyComplete(); |
79 | | static int OnPropertyCompleteTr(llpkgc_file_t* parser); |
80 | | |
81 | | int OnVariableComplete(); |
82 | | static int OnVariableCompleteTr(llpkgc_file_t* parser); |
83 | | |
84 | | int OnBarewordsComplete(); |
85 | | static int OnBarewordsCompleteTr(llpkgc_file_t* parser); |
86 | | |
87 | | int OnValueLiteral(char const* at, std::size_t len); |
88 | | static int OnValueLiteralTr(llpkgc_file_t* parser, char const* at, |
89 | | std::size_t len); |
90 | | |
91 | | int OnValueLiteralComplete(); |
92 | | static int OnValueLiteralCompleteTr(llpkgc_file_t* parser); |
93 | | |
94 | | int OnValueSubstitution(char const* at, std::size_t len); |
95 | | static int OnValueSubstitutionTr(llpkgc_file_t* parser, char const* at, |
96 | | std::size_t len); |
97 | | |
98 | | int OnValueSubstitutionComplete(); |
99 | | static int OnValueSubstitutionCompleteTr(llpkgc_file_t* parser); |
100 | | |
101 | | int OnValueComplete(); |
102 | | static int OnValueCompleteTr(llpkgc_file_t* parser); |
103 | | |
104 | | llpkgc_file_settings_t Settings_{ |
105 | | OnIdentTr, |
106 | | OnValueLiteralTr, |
107 | | OnValueSubstitutionTr, |
108 | | nullptr, // on_line_begin |
109 | | OnPropertyCompleteTr, |
110 | | OnVariableCompleteTr, |
111 | | OnBarewordsCompleteTr, |
112 | | OnValueLiteralCompleteTr, |
113 | | OnValueSubstitutionCompleteTr, |
114 | | OnValueCompleteTr, |
115 | | nullptr, // on_pkgc_complete |
116 | | }; |
117 | | |
118 | | char const* Ptr_ = nullptr; |
119 | | std::size_t Len_ = 0; |
120 | | std::string Ident_; |
121 | | std::vector<cmPkgConfigEntry> Data_; |
122 | | }; |
123 | | |
124 | | class cmPkgConfigFragmentParser : private llpkgc_frag_t |
125 | | { |
126 | | public: |
127 | | cmPkgConfigFragmentParser(); |
128 | | |
129 | | llpkgc_frag_errno_t Parse(char const* input, std::size_t len); |
130 | | llpkgc_frag_errno_t Finish(); |
131 | | |
132 | | llpkgc_frag_errno_t GetErrno() const; |
133 | | char const* ErrorReason() const; |
134 | | |
135 | 0 | std::vector<std::string> const& Fragments() const { return Fragments_; } |
136 | | |
137 | | private: |
138 | | int OnFragmentText(char const* at, std::size_t len); |
139 | | static int OnFragmentTextTr(llpkgc_frag_t* parser, char const* at, |
140 | | std::size_t len); |
141 | | |
142 | | int OnFragmentComplete(); |
143 | | static int OnFragmentCompleteTr(llpkgc_frag_t* parser); |
144 | | |
145 | | llpkgc_frag_settings_t Settings_{ |
146 | | OnFragmentTextTr, OnFragmentCompleteTr, |
147 | | nullptr, // on_fraglist_complete |
148 | | }; |
149 | | |
150 | | std::string CurrentFragment_; |
151 | | std::vector<std::string> Fragments_; |
152 | | }; |
153 | | |
154 | | enum class cmPkgConfigDependencyOperation |
155 | | { |
156 | | None, |
157 | | LessThan, |
158 | | LessThanEqual, |
159 | | Equal, |
160 | | NotEqual, |
161 | | GreaterThan, |
162 | | GreaterThanEqual, |
163 | | }; |
164 | | |
165 | | struct cmPkgConfigDependencySpec |
166 | | { |
167 | | std::string Name; |
168 | | cmPkgConfigDependencyOperation Operation = |
169 | | cmPkgConfigDependencyOperation::None; |
170 | | std::string Version; |
171 | | }; |
172 | | |
173 | | class cmPkgConfigDependencyParser : private llpkgc_dep_t |
174 | | { |
175 | | public: |
176 | | cmPkgConfigDependencyParser(); |
177 | | |
178 | | llpkgc_dep_errno_t Parse(char const* input, std::size_t len); |
179 | | llpkgc_dep_errno_t Finish(); |
180 | | |
181 | | llpkgc_dep_errno_t GetErrno() const; |
182 | | char const* ErrorReason() const; |
183 | | |
184 | | std::vector<cmPkgConfigDependencySpec> const& Dependencies() const |
185 | 0 | { |
186 | 0 | return Dependencies_; |
187 | 0 | } |
188 | | |
189 | | private: |
190 | | int OnDependencyName(char const* at, std::size_t len); |
191 | | static int OnDependencyNameTr(llpkgc_dep_t* parser, char const* at, |
192 | | std::size_t len); |
193 | | |
194 | | int OnDependencyOperator(char const* at, std::size_t len); |
195 | | static int OnDependencyOperatorTr(llpkgc_dep_t* parser, char const* at, |
196 | | std::size_t len); |
197 | | |
198 | | int OnDependencyVersion(char const* at, std::size_t len); |
199 | | static int OnDependencyVersionTr(llpkgc_dep_t* parser, char const* at, |
200 | | std::size_t len); |
201 | | |
202 | | int OnDependencyComplete(); |
203 | | static int OnDependencyCompleteTr(llpkgc_dep_t* parser); |
204 | | |
205 | | llpkgc_dep_settings_t Settings_{ |
206 | | OnDependencyNameTr, |
207 | | OnDependencyOperatorTr, |
208 | | OnDependencyVersionTr, |
209 | | OnDependencyCompleteTr, |
210 | | nullptr, // on_dep_list_complete |
211 | | }; |
212 | | |
213 | | cmPkgConfigDependencySpec Current_; |
214 | | std::vector<cmPkgConfigDependencySpec> Dependencies_; |
215 | | }; |
216 | | |
217 | | struct cmPkgConfigResolvedValue |
218 | | { |
219 | | std::vector<std::string> Fragments; |
220 | | std::vector<cmPkgConfigDependencySpec> Dependencies; |
221 | | std::string Literal; |
222 | | }; |
223 | | |
224 | | class cmPkgConfigParser |
225 | | { |
226 | | public: |
227 | 1 | cmPkgConfigParser() = default; |
228 | | |
229 | | llpkgc_file_errno_t Parse(char const* input, std::size_t len); |
230 | | llpkgc_file_errno_t Finish(); |
231 | | llpkgc_file_errno_t Finish(char const* data, std::size_t len); |
232 | | |
233 | | llpkgc_file_errno_t GetErrno() const; |
234 | | char const* ErrorReason() const; |
235 | | std::ptrdiff_t ErrorOffset(char const* base) const; |
236 | | |
237 | | void SetVariable(std::string name, std::string value); |
238 | | std::string GetVariable(std::string const& name); |
239 | | bool HasProperty(std::string const& name) const; |
240 | | std::vector<std::string> GetFragments(std::string const& name); |
241 | | std::vector<cmPkgConfigDependencySpec> GetDependencies( |
242 | | std::string const& name); |
243 | | std::string GetLiteral(std::string const& name); |
244 | | |
245 | | void ParseComplete(); |
246 | | |
247 | | private: |
248 | | using ValueItems = std::vector<cmPkgConfigValueItem>; |
249 | | |
250 | | std::string ResolveValue(ValueItems const& items); |
251 | | std::string ResolveValueImpl(ValueItems const& items, |
252 | | std::set<std::string> resolving); |
253 | | |
254 | | bool ResolveAndParse(std::string const& name, |
255 | | cmPkgConfigResolvedValue& cache); |
256 | | |
257 | | static bool IsFragmentProperty(std::string const& lower); |
258 | | static bool IsDependencyProperty(std::string const& lower); |
259 | | |
260 | | cmPkgConfigFileParser File_; |
261 | | std::unordered_map<std::string, ValueItems> StoredVariables_; |
262 | | std::vector<cmPkgConfigEntry> StoredProperties_; |
263 | | std::unordered_map<std::string, cmPkgConfigResolvedValue> Cache_; |
264 | | }; |