diff options
| author | Alexander Karatarakis <alkarata@microsoft.com> | 2016-11-07 16:06:36 -0800 |
|---|---|---|
| committer | Alexander Karatarakis <alkarata@microsoft.com> | 2016-11-07 16:06:36 -0800 |
| commit | a721db2c1fbfc1b87065b0b43e32249117e53242 (patch) | |
| tree | 1b0a928249499fe6aefd08261ef9b46186d348c6 /toolsrc/src | |
| parent | 8e9338e4a00b44fd7721d8c6866c72d1502c3f97 (diff) | |
| download | vcpkg-a721db2c1fbfc1b87065b0b43e32249117e53242.tar.gz vcpkg-a721db2c1fbfc1b87065b0b43e32249117e53242.zip | |
Refactor: create new Paragraphs.h/cpp
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/Paragraphs.cpp | 163 | ||||
| -rw-r--r-- | toolsrc/src/commands_cache.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/commands_import.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/commands_installation.cpp | 5 | ||||
| -rw-r--r-- | toolsrc/src/commands_portsdiff.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/commands_search.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/commands_update.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/lib.cpp | 9 | ||||
| -rw-r--r-- | toolsrc/src/main.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/tests_paragraph.cpp | 32 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg.cpp | 165 |
11 files changed, 199 insertions, 193 deletions
diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp new file mode 100644 index 000000000..5efa9a7b3 --- /dev/null +++ b/toolsrc/src/Paragraphs.cpp @@ -0,0 +1,163 @@ +#include "Paragraphs.h" +#include "vcpkg_Files.h" + +namespace vcpkg { namespace Paragraphs +{ + struct Parser + { + Parser(const char* c, const char* e) : cur(c), end(e) + { + } + + private: + const char* cur; + const char* const end; + + void peek(char& ch) const + { + if (cur == end) + ch = 0; + else + ch = *cur; + } + + void next(char& ch) + { + if (cur == end) + ch = 0; + else + { + ++cur; + peek(ch); + } + } + + void skip_spaces(char& ch) + { + while (ch == ' ' || ch == '\t') + next(ch); + } + + static bool is_alphanum(char ch) + { + return (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') + || (ch >= '0' && ch <= '9'); + } + + static bool is_lineend(char ch) + { + return ch == '\r' || ch == '\n' || ch == 0; + } + + void get_fieldvalue(char& ch, std::string& fieldvalue) + { + fieldvalue.clear(); + + auto beginning_of_line = cur; + do + { + // scan to end of current line (it is part of the field value) + while (!is_lineend(ch)) + next(ch); + + fieldvalue.append(beginning_of_line, cur); + + if (ch == '\r') + next(ch); + if (ch == '\n') + next(ch); + + if (is_alphanum(ch)) + { + // Line begins a new field. + return; + } + + beginning_of_line = cur; + + // Line may continue the current field with data or terminate the paragraph, + // depending on first nonspace character. + skip_spaces(ch); + + if (is_lineend(ch)) + { + // Line was whitespace or empty. + // This terminates the field and the paragraph. + // We leave the blank line's whitespace consumed, because it doesn't matter. + return; + } + + // First nonspace is not a newline. This continues the current field value. + // We forcibly convert all newlines into single '\n' for ease of text handling later on. + fieldvalue.push_back('\n'); + } + while (true); + } + + void get_fieldname(char& ch, std::string& fieldname) + { + auto begin_fieldname = cur; + while (is_alphanum(ch) || ch == '-') + next(ch); + Checks::check_throw(ch == ':', "Expected ':'"); + fieldname = std::string(begin_fieldname, cur); + + // skip ': ' + next(ch); + skip_spaces(ch); + } + + void get_paragraph(char& ch, std::unordered_map<std::string, std::string>& fields) + { + fields.clear(); + std::string fieldname; + std::string fieldvalue; + do + { + get_fieldname(ch, fieldname); + + auto it = fields.find(fieldname); + Checks::check_throw(it == fields.end(), "Duplicate field"); + + get_fieldvalue(ch, fieldvalue); + + fields.emplace(fieldname, fieldvalue); + } + while (!is_lineend(ch)); + } + + public: + std::vector<std::unordered_map<std::string, std::string>> get_paragraphs() + { + std::vector<std::unordered_map<std::string, std::string>> paragraphs; + + char ch; + peek(ch); + + while (ch != 0) + { + if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') + { + next(ch); + continue; + } + + paragraphs.emplace_back(); + get_paragraph(ch, paragraphs.back()); + } + + return paragraphs; + } + }; + + std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path) + { + return parse_paragraphs(Files::get_contents(control_path).get_or_throw()); + } + + std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str) + { + return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + } +}} diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index 5e20a39af..634a72a64 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -2,6 +2,7 @@ #include "vcpkg_System.h" #include "vcpkg_Files.h" #include "vcpkg.h" +#include "Paragraphs.h" namespace vcpkg { @@ -17,7 +18,7 @@ namespace vcpkg auto file_contents = Files::get_contents(path / "CONTROL"); if (auto text = file_contents.get()) { - auto pghs = parse_paragraphs(*text); + auto pghs = Paragraphs::parse_paragraphs(*text); if (pghs.size() != 1) continue; diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index 9cfc53d6c..7a6139085 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -1,5 +1,6 @@ #include "vcpkg_Commands.h" #include "vcpkg.h" +#include "Paragraphs.h" namespace vcpkg { @@ -12,7 +13,7 @@ namespace vcpkg const fs::path include_directory(args.command_arguments[1]); const fs::path project_directory(args.command_arguments[2]); - auto pghs = get_paragraphs(control_file_path); + auto pghs = Paragraphs::get_paragraphs(control_file_path); Checks::check_throw(pghs.size() == 1, "Invalid control file for package"); StatusParagraph spgh; diff --git a/toolsrc/src/commands_installation.cpp b/toolsrc/src/commands_installation.cpp index f6aeafa02..b5f4e1a5d 100644 --- a/toolsrc/src/commands_installation.cpp +++ b/toolsrc/src/commands_installation.cpp @@ -9,6 +9,7 @@ #include "vcpkg_Dependencies.h" #include "vcpkg_Input.h" #include "vcpkg_Maps.h" +#include "Paragraphs.h" namespace vcpkg { @@ -21,7 +22,7 @@ namespace vcpkg static void build_internal(const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir) { - auto pghs = get_paragraphs(port_dir / "CONTROL"); + auto pghs = Paragraphs::get_paragraphs(port_dir / "CONTROL"); Checks::check_exit(pghs.size() == 1, "Error: invalid control file"); SourceParagraph source_paragraph(pghs[0]); @@ -111,7 +112,7 @@ namespace vcpkg } } - auto pghs = parse_paragraphs(file_contents.get_or_throw()); + auto pghs = Paragraphs::parse_paragraphs(file_contents.get_or_throw()); Checks::check_throw(pghs.size() == 1, "multiple paragraphs in control file"); install_package(paths, BinaryParagraph(pghs[0]), status_db); System::println(System::color::success, "Package %s is installed", spec); diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index e15db3567..fdbaec0ac 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -7,6 +7,7 @@ #include <iostream> #include <iomanip> #include <set> +#include "Paragraphs.h" namespace vcpkg { @@ -52,7 +53,7 @@ namespace vcpkg try { - auto pghs = get_paragraphs(path / "CONTROL"); + auto pghs = Paragraphs::get_paragraphs(path / "CONTROL"); if (pghs.empty()) continue; auto srcpgh = SourceParagraph(pghs[0]); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index d59a338ac..399709cf3 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -1,6 +1,7 @@ #include "vcpkg_Commands.h" #include "vcpkg_System.h" #include "vcpkg.h" +#include "Paragraphs.h" namespace fs = std::tr2::sys; @@ -15,7 +16,7 @@ namespace vcpkg try { - auto pghs = get_paragraphs(path / "CONTROL"); + auto pghs = Paragraphs::get_paragraphs(path / "CONTROL"); if (pghs.empty()) { continue; diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index 5d531ef39..b448091f7 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -2,6 +2,7 @@ #include "vcpkg.h" #include "vcpkg_System.h" #include "vcpkg_Files.h" +#include "Paragraphs.h" namespace vcpkg { @@ -21,7 +22,7 @@ namespace vcpkg const auto& path = begin_it->path(); try { - auto pghs = get_paragraphs(path / "CONTROL"); + auto pghs = Paragraphs::get_paragraphs(path / "CONTROL"); if (pghs.empty()) continue; auto srcpgh = SourceParagraph(pghs[0]); diff --git a/toolsrc/src/lib.cpp b/toolsrc/src/lib.cpp index 3c844ac3f..5de9f9639 100644 --- a/toolsrc/src/lib.cpp +++ b/toolsrc/src/lib.cpp @@ -11,6 +11,7 @@ #include <cassert> #include "vcpkg_Files.h" #include "vcpkg_System.h" +#include "Paragraphs.h" using namespace vcpkg; @@ -51,7 +52,7 @@ static StatusParagraphs load_current_database(const fs::path& vcpkg_dir_status_f } auto text = Files::get_contents(vcpkg_dir_status_file).get_or_throw(); - auto pghs = parse_paragraphs(text); + auto pghs = Paragraphs::parse_paragraphs(text); std::vector<std::unique_ptr<StatusParagraph>> status_pghs; for (auto&& p : pghs) @@ -94,7 +95,7 @@ StatusParagraphs vcpkg::database_load_check(const vcpkg_paths& paths) continue; auto text = Files::get_contents(b->path()).get_or_throw(); - auto pghs = parse_paragraphs(text); + auto pghs = Paragraphs::parse_paragraphs(text); for (auto&& p : pghs) { current_status_db.insert(std::make_unique<StatusParagraph>(p)); @@ -217,7 +218,7 @@ std::vector<std::string> vcpkg::get_unmet_package_dependencies(const vcpkg_paths std::vector<std::unordered_map<std::string, std::string>> pghs; try { - pghs = parse_paragraphs(*control_contents); + pghs = Paragraphs::parse_paragraphs(*control_contents); } catch (std::runtime_error) { @@ -238,7 +239,7 @@ std::vector<std::string> vcpkg::get_unmet_package_build_dependencies(const vcpkg std::vector<std::unordered_map<std::string, std::string>> pghs; try { - pghs = parse_paragraphs(*control_contents); + pghs = Paragraphs::parse_paragraphs(*control_contents); } catch (std::runtime_error) { diff --git a/toolsrc/src/main.cpp b/toolsrc/src/main.cpp index 2200cd105..22c45e5ab 100644 --- a/toolsrc/src/main.cpp +++ b/toolsrc/src/main.cpp @@ -12,6 +12,7 @@ #include "vcpkg_Files.h" #include "vcpkg_System.h" #include "vcpkg_Input.h" +#include "Paragraphs.h" using namespace vcpkg; @@ -115,7 +116,7 @@ static void loadConfig() std::string config_contents = Files::get_contents(localappdata / "vcpkg" / "config").get_or_throw(); std::unordered_map<std::string, std::string> keys; - auto pghs = parse_paragraphs(config_contents); + auto pghs = Paragraphs::parse_paragraphs(config_contents); if (pghs.size() > 0) keys = pghs[0]; diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index b06359b90..28309fd31 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -1,5 +1,6 @@ #include "CppUnitTest.h" #include "vcpkg.h" +#include "Paragraphs.h" #pragma comment(lib,"version") #pragma comment(lib,"winhttp") @@ -81,9 +82,9 @@ namespace UnitTest1 TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) { vcpkg::SourceParagraph pgh({ - { "Source", "zlib" }, - { "Version", "1.2.8" }, - { "Build-Depends", "libA [windows], libB [uwp]" } + {"Source", "zlib"}, + {"Version", "1.2.8"}, + {"Build-Depends", "libA [windows], libB [uwp]"} }); Assert::AreEqual("zlib", pgh.name.c_str()); @@ -97,7 +98,6 @@ namespace UnitTest1 Assert::AreEqual("uwp", pgh.depends[1].qualifier.c_str()); } - TEST_METHOD(BinaryParagraph_Construct_Minimum) { vcpkg::BinaryParagraph pgh({ @@ -153,14 +153,14 @@ namespace UnitTest1 TEST_METHOD(parse_paragraphs_empty) { const char* str = ""; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::IsTrue(pghs.empty()); } TEST_METHOD(parse_paragraphs_one_field) { const char* str = "f1: v1"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(1), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -171,7 +171,7 @@ namespace UnitTest1 const char* str = "f1: v1\n" "f2: v2"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -186,7 +186,7 @@ namespace UnitTest1 "\n" "f3: v3\n" "f4: v4"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(2), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -204,7 +204,7 @@ namespace UnitTest1 "F:\n" "0:\n" "F-2:\n"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(5), pghs[0].size()); } @@ -218,7 +218,7 @@ namespace UnitTest1 "\n" "f3: v3\n" "f4: v4"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(2), pghs.size()); } @@ -227,7 +227,7 @@ namespace UnitTest1 const char* str = "f1:\n" "f2: "; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("", pghs[0]["f1"].c_str()); @@ -243,7 +243,7 @@ namespace UnitTest1 "f2:\r\n" " f2\r\n" " continue\r\n"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("simple\n f1", pghs[0]["f1"].c_str()); Assert::AreEqual("\n f2\n continue", pghs[0]["f2"].c_str()); @@ -257,7 +257,7 @@ namespace UnitTest1 "\r\n" "f3: v3\r\n" "f4: v4"; - auto pghs = vcpkg::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); Assert::AreEqual(size_t(2), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -277,7 +277,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, }); ss << pgh; - auto pghs = vcpkg::parse_paragraphs(ss.str()); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(4), pghs[0].size()); Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); @@ -299,7 +299,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, }); ss << pgh; - auto pghs = vcpkg::parse_paragraphs(ss.str()); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(7), pghs[0].size()); Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); @@ -321,7 +321,7 @@ namespace UnitTest1 {"Depends", "a, b, c"}, }); ss << pgh; - auto pghs = vcpkg::parse_paragraphs(ss.str()); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index f705858cc..a9ef963e7 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -1,160 +1,5 @@ #include "vcpkg.h" #include <regex> -#include "vcpkg_Files.h" -#include "vcpkglib_helpers.h" - -namespace -{ - using namespace vcpkg; - - struct Parser - { - Parser(const char* c, const char* e) : cur(c), end(e) - { - } - - private: - const char* cur; - const char* const end; - - void peek(char& ch) const - { - if (cur == end) - ch = 0; - else - ch = *cur; - } - - void next(char& ch) - { - if (cur == end) - ch = 0; - else - { - ++cur; - peek(ch); - } - } - - void skip_spaces(char& ch) - { - while (ch == ' ' || ch == '\t') - next(ch); - } - - static bool is_alphanum(char ch) - { - return (ch >= 'A' && ch <= 'Z') - || (ch >= 'a' && ch <= 'z') - || (ch >= '0' && ch <= '9'); - } - - static bool is_lineend(char ch) - { - return ch == '\r' || ch == '\n' || ch == 0; - } - - void get_fieldvalue(char& ch, std::string& fieldvalue) - { - fieldvalue.clear(); - - auto beginning_of_line = cur; - do - { - // scan to end of current line (it is part of the field value) - while (!is_lineend(ch)) - next(ch); - - fieldvalue.append(beginning_of_line, cur); - - if (ch == '\r') - next(ch); - if (ch == '\n') - next(ch); - - if (is_alphanum(ch)) - { - // Line begins a new field. - return; - } - - beginning_of_line = cur; - - // Line may continue the current field with data or terminate the paragraph, - // depending on first nonspace character. - skip_spaces(ch); - - if (is_lineend(ch)) - { - // Line was whitespace or empty. - // This terminates the field and the paragraph. - // We leave the blank line's whitespace consumed, because it doesn't matter. - return; - } - - // First nonspace is not a newline. This continues the current field value. - // We forcibly convert all newlines into single '\n' for ease of text handling later on. - fieldvalue.push_back('\n'); - } - while (true); - } - - void get_fieldname(char& ch, std::string& fieldname) - { - auto begin_fieldname = cur; - while (is_alphanum(ch) || ch == '-') - next(ch); - Checks::check_throw(ch == ':', "Expected ':'"); - fieldname = std::string(begin_fieldname, cur); - - // skip ': ' - next(ch); - skip_spaces(ch); - } - - void get_paragraph(char& ch, std::unordered_map<std::string, std::string>& fields) - { - fields.clear(); - std::string fieldname; - std::string fieldvalue; - do - { - get_fieldname(ch, fieldname); - - auto it = fields.find(fieldname); - Checks::check_throw(it == fields.end(), "Duplicate field"); - - get_fieldvalue(ch, fieldvalue); - - fields.emplace(fieldname, fieldvalue); - } - while (!is_lineend(ch)); - } - - public: - std::vector<std::unordered_map<std::string, std::string>> get_paragraphs() - { - std::vector<std::unordered_map<std::string, std::string>> paragraphs; - - char ch; - peek(ch); - - while (ch != 0) - { - if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') - { - next(ch); - continue; - } - - paragraphs.emplace_back(); - get_paragraph(ch, paragraphs.back()); - } - - return paragraphs; - } - }; -} namespace vcpkg { @@ -165,14 +10,4 @@ namespace vcpkg simple_desc.append("..."); return simple_desc; } - - std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path) - { - return parse_paragraphs(Files::get_contents(control_path).get_or_throw()); - } - - std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str) - { - return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); - } } |
