diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2020-02-07 11:24:35 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-07 11:24:35 -0800 |
| commit | 8db6db5dac70c25b04cd4dd84392484dee822fbe (patch) | |
| tree | 4734de271f966ff4b9a913b15c1b7b537ecd1a8d /toolsrc/include | |
| parent | 2873f07823df192ba55693d200850669eabe332c (diff) | |
| download | vcpkg-8db6db5dac70c25b04cd4dd84392484dee822fbe.tar.gz vcpkg-8db6db5dac70c25b04cd4dd84392484dee822fbe.zip | |
[vcpkg] Further parser improvements (#9895)
* [vcpkg] Consolidate several internal parsers together (packagespecs + logicexpression + control) and enhance error messages
* [vcpkg] Migrate Build-Depends parsing to new framework
* [vcpkg] Fix tests. Re-enable underscores in feature names due to libwebp[vwebp_sdl] -- todo: rename this feature and remove underscores.
Diffstat (limited to 'toolsrc/include')
24 files changed, 405 insertions, 155 deletions
diff --git a/toolsrc/include/vcpkg-test/mockcmakevarprovider.h b/toolsrc/include/vcpkg-test/mockcmakevarprovider.h index 03defdcdd..21207c856 100644 --- a/toolsrc/include/vcpkg-test/mockcmakevarprovider.h +++ b/toolsrc/include/vcpkg-test/mockcmakevarprovider.h @@ -6,7 +6,7 @@ namespace vcpkg::Test {
struct MockCMakeVarProvider : CMakeVars::CMakeVarProvider
{
- void load_generic_triplet_vars(const Triplet& triplet) const override { generic_triplet_vars[triplet] = {}; }
+ void load_generic_triplet_vars(Triplet triplet) const override { generic_triplet_vars[triplet] = {}; }
void load_dep_info_vars(Span<const PackageSpec> specs) const override
{
@@ -23,7 +23,7 @@ namespace vcpkg::Test }
Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars(
- const Triplet& triplet) const override;
+ Triplet triplet) const override;
Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars(
const PackageSpec& spec) const override;
diff --git a/toolsrc/include/vcpkg-test/util.h b/toolsrc/include/vcpkg-test/util.h index 088a39b7d..d8ecc51ea 100644 --- a/toolsrc/include/vcpkg-test/util.h +++ b/toolsrc/include/vcpkg-test/util.h @@ -40,7 +40,7 @@ namespace vcpkg::Test { std::unordered_map<std::string, SourceControlFileLocation> map; Triplet triplet; - PackageSpecMap(const Triplet& t = Triplet::X86_WINDOWS) noexcept : triplet(t) {} + PackageSpecMap(Triplet t = Triplet::X86_WINDOWS) noexcept : triplet(t) {} PackageSpec emplace(const char* name, const char* depends = "", @@ -50,8 +50,6 @@ namespace vcpkg::Test PackageSpec emplace(vcpkg::SourceControlFileLocation&& scfl); }; - vcpkg::PackageSpec unsafe_pspec(std::string name, vcpkg::Triplet t = vcpkg::Triplet::X86_WINDOWS); - template<class T, class S> T&& unwrap(vcpkg::ExpectedT<T, S>&& p) { diff --git a/toolsrc/include/vcpkg/base/expected.h b/toolsrc/include/vcpkg/base/expected.h index c273d71e6..2b19bad2a 100644 --- a/toolsrc/include/vcpkg/base/expected.h +++ b/toolsrc/include/vcpkg/base/expected.h @@ -75,6 +75,30 @@ namespace vcpkg constexpr ExpectedLeftTag expected_left_tag; constexpr ExpectedRightTag expected_right_tag; + template<class T> + struct ExpectedHolder + { + ExpectedHolder() = default; + ExpectedHolder(const T& t) : t(t) {} + ExpectedHolder(T&& t) : t(std::move(t)) {} + using pointer = T*; + using const_pointer = const T*; + T* get() { return &t; } + const T* get() const { return &t; } + T t; + }; + template<class T> + struct ExpectedHolder<T&> + { + ExpectedHolder(T& t) : t(&t) {} + ExpectedHolder() : t(nullptr) {} + using pointer = T*; + using const_pointer = T*; + T* get() { return t; } + T* get() const { return t; } + T* t; + }; + template<class T, class S> class ExpectedT { @@ -87,7 +111,10 @@ namespace vcpkg ExpectedT(S&& s, ExpectedRightTag = {}) : m_s(std::move(s)) {} ExpectedT(const T& t, ExpectedLeftTag = {}) : m_t(t) {} - ExpectedT(T&& t, ExpectedLeftTag = {}) : m_t(std::move(t)) {} + template<class = std::enable_if<!std::is_reference_v<T>>> + ExpectedT(T&& t, ExpectedLeftTag = {}) : m_t(std::move(t)) + { + } ExpectedT(const ExpectedT&) = default; ExpectedT(ExpectedT&&) = default; @@ -100,35 +127,94 @@ namespace vcpkg T&& value_or_exit(const LineInfo& line_info) && { exit_if_error(line_info); - return std::move(this->m_t); + return std::move(*this->m_t.get()); } const T& value_or_exit(const LineInfo& line_info) const& { exit_if_error(line_info); - return this->m_t; + return *this->m_t.get(); } const S& error() const& { return this->m_s.error(); } S&& error() && { return std::move(this->m_s.error()); } - const T* get() const + typename ExpectedHolder<T>::const_pointer get() const { if (!this->has_value()) { return nullptr; } - return &this->m_t; + return this->m_t.get(); } - T* get() + typename ExpectedHolder<T>::pointer get() { if (!this->has_value()) { return nullptr; } - return &this->m_t; + return this->m_t.get(); + } + + template<class F> + using map_t = decltype(std::declval<F&>()(*std::declval<typename ExpectedHolder<T>::const_pointer>())); + + template<class F, class U = map_t<F>> + ExpectedT<U, S> map(F f) const& + { + if (has_value()) + { + return {f(*m_t.get()), expected_left_tag}; + } + else + { + return {error(), expected_right_tag}; + } + } + + template<class F> + using move_map_t = + decltype(std::declval<F&>()(std::move(*std::declval<typename ExpectedHolder<T>::pointer>()))); + + template<class F, class U = move_map_t<F>> + ExpectedT<U, S> map(F f) && + { + if (has_value()) + { + return {f(std::move(*m_t.get())), expected_left_tag}; + } + else + { + return {std::move(error()), expected_right_tag}; + } + } + + template<class F, class U = map_t<F>> + U then(F f) const& + { + if (has_value()) + { + return f(*m_t.get()); + } + else + { + return U{error(), expected_right_tag}; + } + } + + template<class F, class U = move_map_t<F>> + U then(F f) && + { + if (has_value()) + { + return f(std::move(*m_t.get())); + } + else + { + return U{std::move(error()), expected_right_tag}; + } } private: @@ -143,9 +229,12 @@ namespace vcpkg } ErrorHolder<S> m_s; - T m_t; + ExpectedHolder<T> m_t; }; template<class T> using Expected = ExpectedT<T, std::error_code>; + + template<class T> + using ExpectedS = ExpectedT<T, std::string>; } diff --git a/toolsrc/include/vcpkg/base/optional.h b/toolsrc/include/vcpkg/base/optional.h index 2d8c126c6..fc3733ead 100644 --- a/toolsrc/include/vcpkg/base/optional.h +++ b/toolsrc/include/vcpkg/base/optional.h @@ -228,12 +228,21 @@ namespace vcpkg return this->m_base.has_value() ? this->m_base.value() : static_cast<T>(std::forward<U>(default_value)); } + T value_or(T&& default_value) const& + { + return this->m_base.has_value() ? this->m_base.value() : static_cast<T&&>(default_value); + } + template<class U> T value_or(U&& default_value) && { return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast<T>(std::forward<U>(default_value)); } + T value_or(T&& default_value) && + { + return this->m_base.has_value() ? std::move(this->m_base.value()) : static_cast<T&&>(default_value); + } typename std::add_pointer<const T>::type get() const { @@ -242,6 +251,38 @@ namespace vcpkg typename std::add_pointer<T>::type get() { return this->m_base.has_value() ? &this->m_base.value() : nullptr; } + template<class F> + using map_t = decltype(std::declval<F&>()(std::declval<const T&>())); + + template<class F, class U = map_t<F>> + U then(F f) const& + { + if (has_value()) + { + return f(this->m_base.value()); + } + else + { + return nullopt; + } + } + + template<class F> + using move_map_t = decltype(std::declval<F&>()(std::declval<T&&>())); + + template<class F, class U = move_map_t<F>> + U then(F f) && + { + if (has_value()) + { + return f(std::move(this->m_base.value())); + } + else + { + return nullopt; + } + } + private: details::OptionalStorage<T> m_base; }; diff --git a/toolsrc/include/vcpkg/binaryparagraph.h b/toolsrc/include/vcpkg/binaryparagraph.h index 223a1fb86..05c42dee4 100644 --- a/toolsrc/include/vcpkg/binaryparagraph.h +++ b/toolsrc/include/vcpkg/binaryparagraph.h @@ -1,7 +1,7 @@ #pragma once #include <vcpkg/packagespec.h> -#include <vcpkg/parse.h> +#include <vcpkg/paragraphparser.h> #include <vcpkg/sourceparagraph.h> namespace vcpkg @@ -14,12 +14,12 @@ namespace vcpkg BinaryParagraph(); explicit BinaryParagraph(Parse::RawParagraph fields); BinaryParagraph(const SourceParagraph& spgh, - const Triplet& triplet, + Triplet triplet, const std::string& abi_tag, const std::vector<FeatureSpec>& deps); BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, - const Triplet& triplet, + Triplet triplet, const std::vector<FeatureSpec>& deps); std::string displayname() const; diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index b7b7475ef..9d555ae25 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -26,7 +26,7 @@ namespace vcpkg::Build const ParsedArguments& options, const VcpkgPaths& paths); - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } enum class UseHeadVersion @@ -140,7 +140,7 @@ namespace vcpkg::Build struct PreBuildInfo { PreBuildInfo(const VcpkgPaths& paths, - const Triplet& triplet, + Triplet triplet, const std::unordered_map<std::string, std::string>& cmakevars); std::string triplet_abi_tag; @@ -197,7 +197,7 @@ namespace vcpkg::Build struct BuildPackageConfig { BuildPackageConfig(const SourceControlFileLocation& scfl, - const Triplet& triplet, + Triplet triplet, const BuildPackageOptions& build_package_options, const CMakeVars::CMakeVarProvider& var_provider, const std::unordered_map<std::string, std::vector<FeatureSpec>>& feature_dependencies, @@ -217,7 +217,7 @@ namespace vcpkg::Build const SourceControlFileLocation& scfl; const SourceControlFile& scf; - const Triplet& triplet; + Triplet triplet; const fs::path& port_dir; const BuildPackageOptions& build_package_options; const CMakeVars::CMakeVarProvider& var_provider; diff --git a/toolsrc/include/vcpkg/cmakevars.h b/toolsrc/include/vcpkg/cmakevars.h index c634866d0..8d131d45e 100644 --- a/toolsrc/include/vcpkg/cmakevars.h +++ b/toolsrc/include/vcpkg/cmakevars.h @@ -11,7 +11,7 @@ namespace vcpkg::CMakeVars struct CMakeVarProvider { virtual Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars( - const Triplet& triplet) const = 0; + Triplet triplet) const = 0; virtual Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars( const PackageSpec& spec) const = 0; @@ -19,7 +19,7 @@ namespace vcpkg::CMakeVars virtual Optional<const std::unordered_map<std::string, std::string>&> get_tag_vars( const PackageSpec& spec) const = 0; - virtual void load_generic_triplet_vars(const Triplet& triplet) const = 0; + virtual void load_generic_triplet_vars(Triplet triplet) const = 0; virtual void load_dep_info_vars(Span<const PackageSpec> specs) const = 0; @@ -41,7 +41,7 @@ namespace vcpkg::CMakeVars public: explicit TripletCMakeVarProvider(const vcpkg::VcpkgPaths& paths) : paths(paths) {} - void load_generic_triplet_vars(const Triplet& triplet) const override; + void load_generic_triplet_vars(Triplet triplet) const override; void load_dep_info_vars(Span<const PackageSpec> specs) const override; @@ -49,7 +49,7 @@ namespace vcpkg::CMakeVars const PortFileProvider::PortFileProvider& port_provider) const override; Optional<const std::unordered_map<std::string, std::string>&> get_generic_triplet_vars( - const Triplet& triplet) const override; + Triplet triplet) const override; Optional<const std::unordered_map<std::string, std::string>&> get_dep_info_vars( const PackageSpec& spec) const override; diff --git a/toolsrc/include/vcpkg/commands.h b/toolsrc/include/vcpkg/commands.h index e73077e1d..9d2d0b6c6 100644 --- a/toolsrc/include/vcpkg/commands.h +++ b/toolsrc/include/vcpkg/commands.h @@ -12,27 +12,25 @@ namespace vcpkg::Commands { - using CommandTypeA = void (*)(const VcpkgCmdArguments& args, - const VcpkgPaths& paths, - const Triplet& default_triplet); + using CommandTypeA = void (*)(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); using CommandTypeB = void (*)(const VcpkgCmdArguments& args, const VcpkgPaths& paths); using CommandTypeC = void (*)(const VcpkgCmdArguments& args); namespace BuildExternal { - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace CI { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Env { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Create @@ -44,7 +42,7 @@ namespace vcpkg::Commands namespace Upgrade { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Edit @@ -56,7 +54,7 @@ namespace vcpkg::Commands namespace DependInfo { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } namespace Search diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index eb9d42b6d..1f92ee63c 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -121,7 +121,7 @@ namespace vcpkg::Dependencies RequestType request_type; Optional<const BinaryParagraph&> core_paragraph() const; - std::vector<PackageSpec> dependencies(const Triplet& triplet) const; + std::vector<PackageSpec> dependencies(Triplet triplet) const; private: Optional<InstalledPackageView> m_installed_package; diff --git a/toolsrc/include/vcpkg/export.h b/toolsrc/include/vcpkg/export.h index eb99b4fb1..3605081e3 100644 --- a/toolsrc/include/vcpkg/export.h +++ b/toolsrc/include/vcpkg/export.h @@ -6,7 +6,7 @@ namespace vcpkg::Export { extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths); } diff --git a/toolsrc/include/vcpkg/input.h b/toolsrc/include/vcpkg/input.h index ef481bf52..917b5af10 100644 --- a/toolsrc/include/vcpkg/input.h +++ b/toolsrc/include/vcpkg/input.h @@ -5,11 +5,11 @@ namespace vcpkg::Input { PackageSpec check_and_get_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text); FullPackageSpec check_and_get_full_package_spec(std::string&& spec_string, - const Triplet& default_triplet, + Triplet default_triplet, CStringView example_text); - void check_triplet(const Triplet& t, const VcpkgPaths& paths); + void check_triplet(Triplet t, const VcpkgPaths& paths); } diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h index e020c8653..1c42cc102 100644 --- a/toolsrc/include/vcpkg/install.h +++ b/toolsrc/include/vcpkg/install.h @@ -83,5 +83,5 @@ namespace vcpkg::Install extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); } diff --git a/toolsrc/include/vcpkg/packagespec.h b/toolsrc/include/vcpkg/packagespec.h index 628352cdb..a37dc99b3 100644 --- a/toolsrc/include/vcpkg/packagespec.h +++ b/toolsrc/include/vcpkg/packagespec.h @@ -1,20 +1,16 @@ #pragma once #include <vcpkg/base/expected.h> -#include <vcpkg/packagespecparseresult.h> +#include <vcpkg/base/optional.h> #include <vcpkg/triplet.h> -namespace vcpkg +namespace vcpkg::Parse { - struct ParsedSpecifier - { - std::string name; - std::vector<std::string> features; - std::string triplet; - - static ExpectedT<ParsedSpecifier, PackageSpecParseResult> from_string(const std::string& input); - }; + struct ParserBase; +} +namespace vcpkg +{ /// /// <summary> /// Full specification of a package. Contains all information to reference @@ -26,14 +22,11 @@ namespace vcpkg PackageSpec() noexcept = default; PackageSpec(std::string name, Triplet triplet) : m_name(std::move(name)), m_triplet(triplet) {} - static ExpectedT<PackageSpec, PackageSpecParseResult> from_name_and_triplet(const std::string& name, - const Triplet& triplet); - - static std::vector<PackageSpec> to_package_specs(const std::vector<std::string>& ports, const Triplet& triplet); + static std::vector<PackageSpec> to_package_specs(const std::vector<std::string>& ports, Triplet triplet); const std::string& name() const; - const Triplet& triplet() const; + Triplet triplet() const; std::string dir() const; @@ -64,16 +57,13 @@ namespace vcpkg const std::string& name() const { return m_spec.name(); } const std::string& feature() const { return m_feature; } - const Triplet& triplet() const { return m_spec.triplet(); } + Triplet triplet() const { return m_spec.triplet(); } const PackageSpec& spec() const { return m_spec; } std::string to_string() const; void to_string(std::string& out) const; - static std::vector<FeatureSpec> from_strings_and_triplet(const std::vector<std::string>& depends, - const Triplet& t); - bool operator<(const FeatureSpec& other) const { if (name() < other.name()) return true; @@ -115,8 +105,7 @@ namespace vcpkg std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string>& default_features, const std::vector<std::string>& all_features) const; - static ExpectedT<FullPackageSpec, PackageSpecParseResult> from_string(const std::string& spec_as_string, - const Triplet& default_triplet); + static ExpectedS<FullPackageSpec> from_string(const std::string& spec_as_string, Triplet default_triplet); }; /// @@ -129,9 +118,30 @@ namespace vcpkg std::string name; std::vector<std::string> features; - static ExpectedT<Features, PackageSpecParseResult> from_string(const std::string& input); + static ExpectedS<Features> from_string(const std::string& input); + }; + + struct Dependency + { + Features depend; + std::string qualifier; + + static ExpectedS<Dependency> from_string(const std::string& input); }; + struct ParsedQualifiedSpecifier + { + std::string name; + Optional<std::vector<std::string>> features; + Optional<std::string> triplet; + Optional<std::string> qualifier; + }; + + Optional<std::string> parse_feature_name(Parse::ParserBase& parser); + Optional<std::string> parse_package_name(Parse::ParserBase& parser); + ExpectedS<ParsedQualifiedSpecifier> parse_qualified_specifier(CStringView input); + Optional<ParsedQualifiedSpecifier> parse_qualified_specifier(Parse::ParserBase& parser); + bool operator==(const PackageSpec& left, const PackageSpec& right); bool operator!=(const PackageSpec& left, const PackageSpec& right); } diff --git a/toolsrc/include/vcpkg/packagespecparseresult.h b/toolsrc/include/vcpkg/packagespecparseresult.h deleted file mode 100644 index 4c99c84c7..000000000 --- a/toolsrc/include/vcpkg/packagespecparseresult.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <vcpkg/base/cstringview.h> -#include <vcpkg/base/expected.h> - -namespace vcpkg -{ - enum class PackageSpecParseResult - { - SUCCESS = 0, - TOO_MANY_COLONS, - INVALID_CHARACTERS - }; - - void to_string(std::string& out, ::vcpkg::PackageSpecParseResult p); - - CStringView to_string(PackageSpecParseResult ev) noexcept; - - template<> - struct ErrorHolder<PackageSpecParseResult> - { - ErrorHolder() noexcept : m_err(PackageSpecParseResult::SUCCESS) {} - ErrorHolder(PackageSpecParseResult err) : m_err(err) {} - - bool has_error() const { return m_err != PackageSpecParseResult::SUCCESS; } - - const PackageSpecParseResult& error() const { return m_err; } - PackageSpecParseResult& error() { return m_err; } - - CStringView to_string() const { return vcpkg::to_string(m_err); } - - private: - PackageSpecParseResult m_err; - }; -} diff --git a/toolsrc/include/vcpkg/paragraphparser.h b/toolsrc/include/vcpkg/paragraphparser.h new file mode 100644 index 000000000..86c3d0228 --- /dev/null +++ b/toolsrc/include/vcpkg/paragraphparser.h @@ -0,0 +1,45 @@ +#pragma once + +#include <vcpkg/base/expected.h> +#include <vcpkg/packagespec.h> + +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + +namespace vcpkg::Parse +{ + struct ParseControlErrorInfo + { + std::string name; + std::vector<std::string> missing_fields; + std::vector<std::string> extra_fields; + std::string error; + }; + + template<class P> + using ParseExpected = vcpkg::ExpectedT<std::unique_ptr<P>, std::unique_ptr<ParseControlErrorInfo>>; + + using RawParagraph = std::unordered_map<std::string, std::string>; + + struct ParagraphParser + { + ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {} + + void required_field(const std::string& fieldname, std::string& out); + std::string optional_field(const std::string& fieldname) const; + std::unique_ptr<ParseControlErrorInfo> error_info(const std::string& name) const; + + private: + RawParagraph&& fields; + std::vector<std::string> missing_fields; + }; + + ExpectedS<std::vector<std::string>> parse_default_features_list(const std::string& str, + CStringView origin = "<unknown>"); + ExpectedS<std::vector<ParsedQualifiedSpecifier>> parse_qualified_specifier_list(const std::string& str, + CStringView origin = "<unknown>"); + ExpectedS<std::vector<Dependency>> parse_dependencies_list(const std::string& str, + CStringView origin = "<unknown>"); +} diff --git a/toolsrc/include/vcpkg/paragraphs.h b/toolsrc/include/vcpkg/paragraphs.h index 7e2410aef..cffe85af7 100644 --- a/toolsrc/include/vcpkg/paragraphs.h +++ b/toolsrc/include/vcpkg/paragraphs.h @@ -1,7 +1,7 @@ #pragma once #include <vcpkg/binaryparagraph.h> -#include <vcpkg/parse.h> +#include <vcpkg/paragraphparser.h> #include <vcpkg/vcpkgpaths.h> #include <vcpkg/base/expected.h> @@ -10,13 +10,13 @@ namespace vcpkg::Paragraphs { using RawParagraph = Parse::RawParagraph; - Expected<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path); - Expected<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path); - Expected<std::vector<RawParagraph>> parse_paragraphs(const std::string& str); + ExpectedS<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path); + ExpectedS<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path); + ExpectedS<std::vector<RawParagraph>> parse_paragraphs(const std::string& str, const std::string& origin); Parse::ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& control_path); - Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); + ExpectedS<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); struct LoadResults { diff --git a/toolsrc/include/vcpkg/parse.h b/toolsrc/include/vcpkg/parse.h index 4b33e302e..3214305bf 100644 --- a/toolsrc/include/vcpkg/parse.h +++ b/toolsrc/include/vcpkg/parse.h @@ -1,38 +1,147 @@ #pragma once -#include <vcpkg/base/expected.h> +#include <vcpkg/base/cstringview.h> #include <vcpkg/base/optional.h> +#include <vcpkg/base/stringview.h> +#include <vcpkg/textrowcol.h> #include <memory> -#include <unordered_map> +#include <string> namespace vcpkg::Parse { - struct ParseControlErrorInfo + struct IParseError { - std::string name; - std::vector<std::string> missing_fields; - std::vector<std::string> extra_fields; - std::error_code error; + virtual ~IParseError() = default; + virtual std::string format() const = 0; }; - template<class P> - using ParseExpected = ExpectedT<std::unique_ptr<P>, std::unique_ptr<ParseControlErrorInfo>>; + struct ParseError : IParseError + { + ParseError(std::string origin, int row, int column, std::string line, std::string message) + : origin(std::move(origin)), row(row), column(column), line(std::move(line)), message(std::move(message)) + { + } + + const std::string origin; + const int row; + const int column; + const std::string line; + const std::string message; - using RawParagraph = std::unordered_map<std::string, std::string>; + virtual std::string format() const override; + }; - struct ParagraphParser + struct ParserBase { - ParagraphParser(RawParagraph&& fields) : fields(std::move(fields)) {} + struct SourceLoc + { + const char* it; + int row; + int column; + }; + + void init(CStringView text, CStringView origin, TextRowCol init_rowcol = {}) + { + m_text = text; + m_origin = origin; + m_it = text.c_str(); + row = init_rowcol.row ? init_rowcol.row : 1; + column = init_rowcol.column ? init_rowcol.column : 1; + } + + static constexpr bool is_whitespace(char ch) { return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; } + static constexpr bool is_lower_alpha(char ch) { return ch >= 'a' && ch <= 'z'; } + static constexpr bool is_upper_alpha(char ch) { return ch >= 'A' && ch <= 'Z'; } + static constexpr bool is_ascii_digit(char ch) { return ch >= '0' && ch <= '9'; } + static constexpr bool is_lineend(char ch) { return ch == '\r' || ch == '\n' || ch == '\0'; } + static constexpr bool is_alphanum(char ch) + { + return is_upper_alpha(ch) || is_lower_alpha(ch) || is_ascii_digit(ch); + } + static constexpr bool is_alphanumdash(char ch) { return is_alphanum(ch) || ch == '-'; } + + StringView skip_whitespace() { return match_zero_or_more(is_whitespace); } + StringView skip_tabs_spaces() + { + return match_zero_or_more([](char ch) { return ch == ' ' || ch == '\t'; }); + } + void skip_to_eof() + { + while (cur()) + ++m_it; + } + void skip_newline() + { + if (cur() == '\r') next(); + if (cur() == '\n') next(); + } + void skip_line() + { + match_until(is_lineend); + skip_newline(); + } - void required_field(const std::string& fieldname, std::string& out); - std::string optional_field(const std::string& fieldname) const; - std::unique_ptr<ParseControlErrorInfo> error_info(const std::string& name) const; + template<class Pred> + StringView match_zero_or_more(Pred p) + { + const char* start = m_it; + auto ch = cur(); + while (ch != '\0' && p(ch)) + ch = next(); + return {start, m_it}; + } + template<class Pred> + StringView match_until(Pred p) + { + const char* start = m_it; + auto ch = cur(); + while (ch != '\0' && !p(ch)) + ch = next(); + return {start, m_it}; + } + + CStringView text() const { return m_text; } + const char* it() const { return m_it; } + char cur() const { return *m_it; } + SourceLoc cur_loc() const { return {m_it, row, column}; } + char next() + { + char ch = *m_it; + // See https://www.gnu.org/prep/standards/standards.html#Errors + if (ch == '\t') + column = (column + 7) / 8 * 8 + 1; // round to next 8-width tab stop + else if (ch == '\n') + { + row++; + column = 1; + } + else if (ch == '\0') + { + return '\0'; + } + else + { + ++column; + } + return *++m_it; + } + bool at_eof() const { return *m_it == 0; } + + void add_error(std::string message) { add_error(std::move(message), cur_loc()); } + void add_error(std::string message, const SourceLoc& loc); + + const Parse::IParseError* get_error() const { return m_err.get(); } + std::unique_ptr<Parse::IParseError> extract_error() { return std::move(m_err); } private: - RawParagraph&& fields; - std::vector<std::string> missing_fields; - }; + const char* m_it; + int row; + int column; + + CStringView m_text; + CStringView m_origin; - std::vector<std::string> parse_comma_list(const std::string& str); + std::unique_ptr<IParseError> m_err; + }; } diff --git a/toolsrc/include/vcpkg/portfileprovider.h b/toolsrc/include/vcpkg/portfileprovider.h index 79f69d9ae..36cdba589 100644 --- a/toolsrc/include/vcpkg/portfileprovider.h +++ b/toolsrc/include/vcpkg/portfileprovider.h @@ -1,6 +1,6 @@ #pragma once -#include <vcpkg/base/optional.h> +#include <vcpkg/base/expected.h> #include <vcpkg/base/util.h> #include <vcpkg/sourceparagraph.h> #include <vcpkg/vcpkgpaths.h> @@ -9,14 +9,14 @@ namespace vcpkg::PortFileProvider { struct PortFileProvider { - virtual Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const = 0; + virtual ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const = 0; virtual std::vector<const SourceControlFileLocation*> load_all_control_files() const = 0; }; struct MapPortFileProvider : Util::ResourceBase, PortFileProvider { explicit MapPortFileProvider(const std::unordered_map<std::string, SourceControlFileLocation>& map); - Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; + ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; std::vector<const SourceControlFileLocation*> load_all_control_files() const override; private: @@ -27,7 +27,7 @@ namespace vcpkg::PortFileProvider { explicit PathsPortFileProvider(const vcpkg::VcpkgPaths& paths, const std::vector<std::string>* ports_dirs_paths); - Optional<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; + ExpectedS<const SourceControlFileLocation&> get_control_file(const std::string& src_name) const override; std::vector<const SourceControlFileLocation*> load_all_control_files() const override; private: diff --git a/toolsrc/include/vcpkg/remove.h b/toolsrc/include/vcpkg/remove.h index 36aeda2ad..c43bc73c2 100644 --- a/toolsrc/include/vcpkg/remove.h +++ b/toolsrc/include/vcpkg/remove.h @@ -21,6 +21,6 @@ namespace vcpkg::Remove extern const CommandStructure COMMAND_STRUCTURE; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet); void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db); } diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index 0574afe74..bdb75fc58 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -1,37 +1,20 @@ #pragma once -#include <vcpkg/packagespec.h> -#include <vcpkg/parse.h> - +#include <string> #include <vcpkg/base/expected.h> #include <vcpkg/base/span.h> #include <vcpkg/base/system.h> - #include <vcpkg/base/system.print.h> - -#include <string> +#include <vcpkg/packagespec.h> +#include <vcpkg/paragraphparser.h> #include <vector> namespace vcpkg { - struct Dependency - { - Features depend; - std::string qualifier; - - std::string name() const; - static Dependency parse_dependency(std::string name, std::string qualifier); - }; - std::vector<FullPackageSpec> filter_dependencies(const std::vector<Dependency>& deps, - const Triplet& t, + Triplet t, const std::unordered_map<std::string, std::string>& cmake_vars); - // zlib[uwp] becomes Dependency{"zlib", "uwp"} - std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends); - - std::string to_string(const Dependency& dep); - struct Type { enum diff --git a/toolsrc/include/vcpkg/statusparagraphs.h b/toolsrc/include/vcpkg/statusparagraphs.h index fa064de7e..7fcf0e916 100644 --- a/toolsrc/include/vcpkg/statusparagraphs.h +++ b/toolsrc/include/vcpkg/statusparagraphs.h @@ -35,10 +35,10 @@ namespace vcpkg /// <param name="triplet">Triplet</param> /// <param name="feature">Feature name</param> /// <returns>Iterator for found spec</returns> - iterator find(const std::string& name, const Triplet& triplet, const std::string& feature = ""); - const_iterator find(const std::string& name, const Triplet& triplet, const std::string& feature = "") const; + iterator find(const std::string& name, Triplet triplet, const std::string& feature = ""); + const_iterator find(const std::string& name, Triplet triplet, const std::string& feature = "") const; - std::vector<std::unique_ptr<StatusParagraph>*> find_all(const std::string& name, const Triplet& triplet); + std::vector<std::unique_ptr<StatusParagraph>*> find_all(const std::string& name, Triplet triplet); Optional<InstalledPackageView> find_all_installed(const PackageSpec& spec) const; diff --git a/toolsrc/include/vcpkg/textrowcol.h b/toolsrc/include/vcpkg/textrowcol.h new file mode 100644 index 000000000..5bbf6a899 --- /dev/null +++ b/toolsrc/include/vcpkg/textrowcol.h @@ -0,0 +1,12 @@ +#pragma once
+
+namespace vcpkg::Parse
+{
+ struct TextRowCol
+ {
+ /// '0' indicates uninitialized; '1' is the first row.
+ int row = 0;
+ /// '0' indicates uninitialized; '1' is the first column.
+ int column = 0;
+ };
+}
diff --git a/toolsrc/include/vcpkg/triplet.h b/toolsrc/include/vcpkg/triplet.h index f33f40fd5..8d8c3e879 100644 --- a/toolsrc/include/vcpkg/triplet.h +++ b/toolsrc/include/vcpkg/triplet.h @@ -27,8 +27,8 @@ namespace vcpkg void to_string(std::string& out) const; size_t hash_code() const; - bool operator==(const Triplet& other) const; - bool operator<(const Triplet& other) const { return canonical_name() < other.canonical_name(); } + bool operator==(Triplet other) const { return this->m_instance == other.m_instance; } + bool operator<(Triplet other) const { return canonical_name() < other.canonical_name(); } private: static const TripletInstance DEFAULT_INSTANCE; @@ -38,7 +38,7 @@ namespace vcpkg const TripletInstance* m_instance; }; - bool operator!=(const Triplet& left, const Triplet& right); + inline bool operator!=(Triplet left, Triplet right) { return !(left == right); } } namespace std @@ -46,6 +46,6 @@ namespace std template<> struct hash<vcpkg::Triplet> { - size_t operator()(const vcpkg::Triplet& t) const { return t.hash_code(); } + size_t operator()(vcpkg::Triplet t) const { return t.hash_code(); } }; } diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index 52d77d283..63d19af2c 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -52,7 +52,7 @@ namespace vcpkg std::string name; fs::path location; - TripletFile(const std::string& name, const fs::path& location) : name(name), location(location){} + TripletFile(const std::string& name, const fs::path& location) : name(name), location(location) {} }; static Expected<VcpkgPaths> create(const fs::path& vcpkg_root_dir, @@ -64,10 +64,10 @@ namespace vcpkg fs::path build_info_file_path(const PackageSpec& spec) const; fs::path listfile_path(const BinaryParagraph& pgh) const; - bool is_valid_triplet(const Triplet& t) const; + bool is_valid_triplet(Triplet t) const; const std::vector<std::string> get_available_triplets_names() const; const std::vector<TripletFile>& get_available_triplets() const; - const fs::path get_triplet_file_path(const Triplet& triplet) const; + const fs::path get_triplet_file_path(Triplet triplet) const; fs::path root; fs::path packages; |
