Coverage Report

Created: 2026-07-30 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
};