Coverage Report

Created: 2026-10-28 06:38

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
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
};