/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 | | |
57 | | llpkgc_file_errno_t GetErrno() const; |
58 | | char const* ErrorReason() const; |
59 | | std::ptrdiff_t ErrorOffset(char const* base) const; |
60 | | |
61 | | private: |
62 | | void ResetCallbacks(); |
63 | | |
64 | | int OnIdentNext(char const* at, std::size_t len); |
65 | | static int OnIdentNextTr(llpkgc_file_t* parser, char const* at, |
66 | | std::size_t len); |
67 | | |
68 | | void AppendValue(std::string text, bool isSubstitution); |
69 | | |
70 | | int OnSpanNext(char const* at, std::size_t len); |
71 | | static int OnSpanNextTr(llpkgc_file_t* parser, char const* at, |
72 | | std::size_t len); |
73 | | |
74 | | int OnIdent(char const* at, std::size_t len); |
75 | | static int OnIdentTr(llpkgc_file_t* parser, char const* at, std::size_t len); |
76 | | |
77 | | int OnPropertyComplete(); |
78 | | static int OnPropertyCompleteTr(llpkgc_file_t* parser); |
79 | | |
80 | | int OnVariableComplete(); |
81 | | static int OnVariableCompleteTr(llpkgc_file_t* parser); |
82 | | |
83 | | int OnBarewordsComplete(); |
84 | | static int OnBarewordsCompleteTr(llpkgc_file_t* parser); |
85 | | |
86 | | int OnValueLiteral(char const* at, std::size_t len); |
87 | | static int OnValueLiteralTr(llpkgc_file_t* parser, char const* at, |
88 | | std::size_t len); |
89 | | |
90 | | int OnValueLiteralComplete(); |
91 | | static int OnValueLiteralCompleteTr(llpkgc_file_t* parser); |
92 | | |
93 | | int OnValueSubstitution(char const* at, std::size_t len); |
94 | | static int OnValueSubstitutionTr(llpkgc_file_t* parser, char const* at, |
95 | | std::size_t len); |
96 | | |
97 | | int OnValueSubstitutionComplete(); |
98 | | static int OnValueSubstitutionCompleteTr(llpkgc_file_t* parser); |
99 | | |
100 | | int OnValueComplete(); |
101 | | static int OnValueCompleteTr(llpkgc_file_t* parser); |
102 | | |
103 | | llpkgc_file_settings_t Settings_{ |
104 | | OnIdentTr, |
105 | | OnValueLiteralTr, |
106 | | OnValueSubstitutionTr, |
107 | | OnPropertyCompleteTr, |
108 | | OnVariableCompleteTr, |
109 | | OnBarewordsCompleteTr, |
110 | | OnValueLiteralCompleteTr, |
111 | | OnValueSubstitutionCompleteTr, |
112 | | OnValueCompleteTr, |
113 | | nullptr, // on_pkgc_complete |
114 | | }; |
115 | | |
116 | | std::string CurrentValue_; |
117 | | std::string Ident_; |
118 | | std::vector<cmPkgConfigEntry> Data_; |
119 | | }; |
120 | | |
121 | | class cmPkgConfigFragmentParser : private llpkgc_frag_t |
122 | | { |
123 | | public: |
124 | | cmPkgConfigFragmentParser(); |
125 | | |
126 | | llpkgc_frag_errno_t Parse(char const* input, std::size_t len); |
127 | | llpkgc_frag_errno_t Finish(); |
128 | | |
129 | | llpkgc_frag_errno_t GetErrno() const; |
130 | | char const* ErrorReason() const; |
131 | | |
132 | 3.33k | std::vector<std::string> const& Fragments() const { return Fragments_; } |
133 | | |
134 | | private: |
135 | | int OnFragmentText(char const* at, std::size_t len); |
136 | | static int OnFragmentTextTr(llpkgc_frag_t* parser, char const* at, |
137 | | std::size_t len); |
138 | | |
139 | | int OnFragmentComplete(); |
140 | | static int OnFragmentCompleteTr(llpkgc_frag_t* parser); |
141 | | |
142 | | llpkgc_frag_settings_t Settings_{ |
143 | | OnFragmentTextTr, OnFragmentCompleteTr, |
144 | | nullptr, // on_fraglist_complete |
145 | | }; |
146 | | |
147 | | std::string CurrentFragment_; |
148 | | std::vector<std::string> Fragments_; |
149 | | }; |
150 | | |
151 | | enum class cmPkgConfigDependencyOperation |
152 | | { |
153 | | None = LLPKGC_DEP_ANY, |
154 | | LessThan = LLPKGC_DEP_LESS_THAN, |
155 | | LessThanEqual = LLPKGC_DEP_LESS_THAN_EQUAL, |
156 | | Equal = LLPKGC_DEP_EQUAL, |
157 | | NotEqual = LLPKGC_DEP_NOT_EQUAL, |
158 | | GreaterThan = LLPKGC_DEP_GREATER_THAN, |
159 | | GreaterThanEqual = LLPKGC_DEP_GREATER_THAN_EQUAL, |
160 | | }; |
161 | | |
162 | | struct cmPkgConfigDependencySpec |
163 | | { |
164 | | std::string Name; |
165 | | cmPkgConfigDependencyOperation Operation = |
166 | | cmPkgConfigDependencyOperation::None; |
167 | | std::string Version; |
168 | | }; |
169 | | |
170 | | class cmPkgConfigDependencyParser : private llpkgc_dep_t |
171 | | { |
172 | | public: |
173 | | cmPkgConfigDependencyParser(); |
174 | | |
175 | | llpkgc_dep_errno_t Parse(char const* input, std::size_t len); |
176 | | llpkgc_dep_errno_t Finish(); |
177 | | |
178 | | llpkgc_dep_errno_t GetErrno() const; |
179 | | char const* ErrorReason() const; |
180 | | |
181 | | std::vector<cmPkgConfigDependencySpec> const& Dependencies() const |
182 | 2.94k | { |
183 | 2.94k | return Dependencies_; |
184 | 2.94k | } |
185 | | |
186 | | private: |
187 | | int OnDependencyName(char const* at, std::size_t len); |
188 | | static int OnDependencyNameTr(llpkgc_dep_t* parser, char const* at, |
189 | | std::size_t len); |
190 | | |
191 | | int OnDependencyVersion(char const* at, std::size_t len); |
192 | | static int OnDependencyVersionTr(llpkgc_dep_t* parser, char const* at, |
193 | | std::size_t len); |
194 | | |
195 | | int OnDependencyComplete(); |
196 | | static int OnDependencyCompleteTr(llpkgc_dep_t* parser); |
197 | | |
198 | | llpkgc_dep_settings_t Settings_{ |
199 | | OnDependencyNameTr, OnDependencyVersionTr, OnDependencyCompleteTr, |
200 | | nullptr, // on_dep_list_complete |
201 | | }; |
202 | | |
203 | | cmPkgConfigDependencySpec Current_; |
204 | | std::vector<cmPkgConfigDependencySpec> Dependencies_; |
205 | | }; |
206 | | |
207 | | struct cmPkgConfigResolvedValue |
208 | | { |
209 | | std::vector<std::string> Fragments; |
210 | | std::vector<cmPkgConfigDependencySpec> Dependencies; |
211 | | std::string Literal; |
212 | | }; |
213 | | |
214 | | class cmPkgConfigParser |
215 | | { |
216 | | public: |
217 | 8.10k | cmPkgConfigParser() = default; |
218 | | |
219 | | llpkgc_file_errno_t Parse(char const* input, std::size_t len); |
220 | | llpkgc_file_errno_t Finish(); |
221 | | llpkgc_file_errno_t Finish(char const* data, std::size_t len); |
222 | | |
223 | | llpkgc_file_errno_t GetErrno() const; |
224 | | char const* ErrorReason() const; |
225 | | std::ptrdiff_t ErrorOffset(char const* base) const; |
226 | | |
227 | | void SetVariable(std::string name, std::string value); |
228 | | std::string GetVariable(std::string const& name); |
229 | | bool HasProperty(std::string const& name) const; |
230 | | std::vector<std::string> GetFragments(std::string const& name); |
231 | | std::vector<cmPkgConfigDependencySpec> GetDependencies( |
232 | | std::string const& name); |
233 | | std::string GetLiteral(std::string const& name); |
234 | | |
235 | | void ParseComplete(); |
236 | | |
237 | | private: |
238 | | using ValueItems = std::vector<cmPkgConfigValueItem>; |
239 | | |
240 | | std::string ResolveValue(ValueItems const& items); |
241 | | std::string ResolveValueImpl(ValueItems const& items, |
242 | | std::set<std::string> resolving); |
243 | | |
244 | | bool ResolveAndParse(std::string const& name, |
245 | | cmPkgConfigResolvedValue& cache); |
246 | | |
247 | | cmPkgConfigFileParser File_; |
248 | | std::unordered_map<std::string, ValueItems> StoredVariables_; |
249 | | std::vector<cmPkgConfigEntry> StoredProperties_; |
250 | | std::unordered_map<std::string, cmPkgConfigResolvedValue> Cache_; |
251 | | }; |