| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file LICENSE.rst or https://cmake.org/licensing for details. */ |
| |
| #pragma once |
| |
| #include "cmConfigure.h" // IWYU pragma: keep |
| |
| #include <cstddef> |
| #include <set> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include <cmllpkgc/llpkgc.h> |
| |
| struct cmPkgConfigValueItem |
| { |
| cmPkgConfigValueItem() = default; |
| cmPkgConfigValueItem(std::string text, bool isSubstitution); |
| |
| std::string Text; |
| bool IsSubstitution = false; |
| }; |
| |
| enum class cmPkgConfigEntryKind |
| { |
| Property, |
| Variable, |
| Barewords, |
| }; |
| |
| struct cmPkgConfigEntry |
| { |
| cmPkgConfigEntry() = default; |
| cmPkgConfigEntry(std::vector<cmPkgConfigValueItem> value, std::string ident, |
| cmPkgConfigEntryKind kind); |
| |
| std::vector<cmPkgConfigValueItem> Value; |
| std::string Ident; |
| cmPkgConfigEntryKind Kind = cmPkgConfigEntryKind::Barewords; |
| }; |
| |
| class cmPkgConfigFileParser : private llpkgc_file_t |
| { |
| friend class cmPkgConfigParser; |
| |
| public: |
| cmPkgConfigFileParser(); |
| cmPkgConfigFileParser(cmPkgConfigFileParser const& other); |
| cmPkgConfigFileParser(cmPkgConfigFileParser&& other) noexcept; |
| cmPkgConfigFileParser& operator=(cmPkgConfigFileParser const& other); |
| cmPkgConfigFileParser& operator=(cmPkgConfigFileParser&& other) noexcept; |
| |
| llpkgc_file_errno_t Parse(char const* input, std::size_t len); |
| llpkgc_file_errno_t Finish(); |
| void Resume(); |
| |
| llpkgc_file_errno_t GetErrno() const; |
| char const* ErrorReason() const; |
| std::ptrdiff_t ErrorOffset(char const* base) const; |
| |
| private: |
| void ResetCallbacks(); |
| |
| int OnIdentNext(char const* at, std::size_t len); |
| static int OnIdentNextTr(llpkgc_file_t* parser, char const* at, |
| std::size_t len); |
| |
| void AppendValue(std::string text, bool isSubstitution); |
| |
| int OnSpanNext(char const*, std::size_t len); |
| static int OnSpanNextTr(llpkgc_file_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnIdent(char const* at, std::size_t len); |
| static int OnIdentTr(llpkgc_file_t* parser, char const* at, std::size_t len); |
| |
| int OnPropertyComplete(); |
| static int OnPropertyCompleteTr(llpkgc_file_t* parser); |
| |
| int OnVariableComplete(); |
| static int OnVariableCompleteTr(llpkgc_file_t* parser); |
| |
| int OnBarewordsComplete(); |
| static int OnBarewordsCompleteTr(llpkgc_file_t* parser); |
| |
| int OnValueLiteral(char const* at, std::size_t len); |
| static int OnValueLiteralTr(llpkgc_file_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnValueLiteralComplete(); |
| static int OnValueLiteralCompleteTr(llpkgc_file_t* parser); |
| |
| int OnValueSubstitution(char const* at, std::size_t len); |
| static int OnValueSubstitutionTr(llpkgc_file_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnValueSubstitutionComplete(); |
| static int OnValueSubstitutionCompleteTr(llpkgc_file_t* parser); |
| |
| int OnValueComplete(); |
| static int OnValueCompleteTr(llpkgc_file_t* parser); |
| |
| llpkgc_file_settings_t Settings_{ |
| OnIdentTr, |
| OnValueLiteralTr, |
| OnValueSubstitutionTr, |
| nullptr, // on_line_begin |
| OnPropertyCompleteTr, |
| OnVariableCompleteTr, |
| OnBarewordsCompleteTr, |
| OnValueLiteralCompleteTr, |
| OnValueSubstitutionCompleteTr, |
| OnValueCompleteTr, |
| nullptr, // on_pkgc_complete |
| }; |
| |
| char const* Ptr_ = nullptr; |
| std::size_t Len_ = 0; |
| std::string Ident_; |
| std::vector<cmPkgConfigEntry> Data_; |
| }; |
| |
| class cmPkgConfigFragmentParser : private llpkgc_frag_t |
| { |
| public: |
| cmPkgConfigFragmentParser(); |
| |
| llpkgc_frag_errno_t Parse(char const* input, std::size_t len); |
| llpkgc_frag_errno_t Finish(); |
| |
| llpkgc_frag_errno_t GetErrno() const; |
| char const* ErrorReason() const; |
| |
| std::vector<std::string> const& Fragments() const { return Fragments_; } |
| |
| private: |
| int OnFragmentText(char const* at, std::size_t len); |
| static int OnFragmentTextTr(llpkgc_frag_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnFragmentComplete(); |
| static int OnFragmentCompleteTr(llpkgc_frag_t* parser); |
| |
| llpkgc_frag_settings_t Settings_{ |
| OnFragmentTextTr, OnFragmentCompleteTr, |
| nullptr, // on_fraglist_complete |
| }; |
| |
| std::string CurrentFragment_; |
| std::vector<std::string> Fragments_; |
| }; |
| |
| enum class cmPkgConfigDependencyOperation |
| { |
| None, |
| LessThan, |
| LessThanEqual, |
| Equal, |
| NotEqual, |
| GreaterThan, |
| GreaterThanEqual, |
| }; |
| |
| struct cmPkgConfigDependencySpec |
| { |
| std::string Name; |
| cmPkgConfigDependencyOperation Operation = |
| cmPkgConfigDependencyOperation::None; |
| std::string Version; |
| }; |
| |
| class cmPkgConfigDependencyParser : private llpkgc_dep_t |
| { |
| public: |
| cmPkgConfigDependencyParser(); |
| |
| llpkgc_dep_errno_t Parse(char const* input, std::size_t len); |
| llpkgc_dep_errno_t Finish(); |
| |
| llpkgc_dep_errno_t GetErrno() const; |
| char const* ErrorReason() const; |
| |
| std::vector<cmPkgConfigDependencySpec> const& Dependencies() const |
| { |
| return Dependencies_; |
| } |
| |
| private: |
| int OnDependencyName(char const* at, std::size_t len); |
| static int OnDependencyNameTr(llpkgc_dep_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnDependencyOperator(char const* at, std::size_t len); |
| static int OnDependencyOperatorTr(llpkgc_dep_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnDependencyVersion(char const* at, std::size_t len); |
| static int OnDependencyVersionTr(llpkgc_dep_t* parser, char const* at, |
| std::size_t len); |
| |
| int OnDependencyComplete(); |
| static int OnDependencyCompleteTr(llpkgc_dep_t* parser); |
| |
| llpkgc_dep_settings_t Settings_{ |
| OnDependencyNameTr, |
| OnDependencyOperatorTr, |
| OnDependencyVersionTr, |
| OnDependencyCompleteTr, |
| nullptr, // on_dep_list_complete |
| }; |
| |
| cmPkgConfigDependencySpec Current_; |
| std::vector<cmPkgConfigDependencySpec> Dependencies_; |
| }; |
| |
| struct cmPkgConfigResolvedValue |
| { |
| std::vector<std::string> Fragments; |
| std::vector<cmPkgConfigDependencySpec> Dependencies; |
| std::string Literal; |
| }; |
| |
| class cmPkgConfigParser |
| { |
| public: |
| cmPkgConfigParser() = default; |
| |
| llpkgc_file_errno_t Parse(char const* input, std::size_t len); |
| llpkgc_file_errno_t Finish(); |
| llpkgc_file_errno_t Finish(char const* data, std::size_t len); |
| |
| llpkgc_file_errno_t GetErrno() const; |
| char const* ErrorReason() const; |
| std::ptrdiff_t ErrorOffset(char const* base) const; |
| |
| void SetVariable(std::string name, std::string value); |
| std::string GetVariable(std::string const& name); |
| bool HasProperty(std::string const& name) const; |
| std::vector<std::string> GetFragments(std::string const& name); |
| std::vector<cmPkgConfigDependencySpec> GetDependencies( |
| std::string const& name); |
| std::string GetLiteral(std::string const& name); |
| |
| void ParseComplete(); |
| |
| private: |
| using ValueItems = std::vector<cmPkgConfigValueItem>; |
| |
| std::string ResolveValue(ValueItems const& items); |
| std::string ResolveValueImpl(ValueItems const& items, |
| std::set<std::string> resolving); |
| |
| bool ResolveAndParse(std::string const& name, |
| cmPkgConfigResolvedValue& cache); |
| |
| static bool IsFragmentProperty(std::string const& lower); |
| static bool IsDependencyProperty(std::string const& lower); |
| |
| cmPkgConfigFileParser File_; |
| std::unordered_map<std::string, ValueItems> StoredVariables_; |
| std::vector<cmPkgConfigEntry> StoredProperties_; |
| std::unordered_map<std::string, cmPkgConfigResolvedValue> Cache_; |
| }; |