diff options
| author | Phil Christensen <philc@microsoft.com> | 2019-08-27 11:00:37 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-27 11:00:37 -0700 |
| commit | 0eb73051028d5ece1dd837171728fd62c82c1202 (patch) | |
| tree | f9e2d3e41cd2a2b3119b9d148fae21bb653865cb /toolsrc/src | |
| parent | 693d05fa965b28fded96d0ded7b1cda84189ff48 (diff) | |
| parent | 8bae937e1725a85cb7829ad3113debbeef43674a (diff) | |
| download | vcpkg-0eb73051028d5ece1dd837171728fd62c82c1202.tar.gz vcpkg-0eb73051028d5ece1dd837171728fd62c82c1202.zip | |
[vcpkg] fix list parsing logic and add error messages
fix list parsing logic and add error messages
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/vcpkg/parse.cpp | 94 |
1 files changed, 82 insertions, 12 deletions
diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index 0509339c5..6015d9927 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -2,6 +2,7 @@ #include <vcpkg/parse.h> +#include <vcpkg/base/system.print.h> #include <vcpkg/base/util.h> namespace vcpkg::Parse @@ -44,6 +45,8 @@ namespace vcpkg::Parse return nullptr; } + static bool is_whitespace(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } + std::vector<std::string> parse_comma_list(const std::string& str) { if (str.empty()) @@ -53,26 +56,93 @@ namespace vcpkg::Parse std::vector<std::string> out; - size_t cur = 0; + auto iter = str.cbegin(); + do { - auto pos = str.find(',', cur); - if (pos == std::string::npos) + // Trim leading whitespace of each element + while (iter != str.cend() && is_whitespace(*iter)) + { + ++iter; + } + + // Allow commas inside of []. + bool bracket_nesting = false; + + auto element_begin = iter; + auto element_end = iter; + while (iter != str.cend() && (*iter != ',' || bracket_nesting)) + { + char value = *iter; + + // do not support nested [] + if (value == '[') + { + if (bracket_nesting) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Lists do not support nested brackets, Did you forget a ']'?\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast<int>(iter - str.cbegin()), ' ')); + } + bracket_nesting = true; + } + else if (value == ']') + { + if (!bracket_nesting) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Found unmatched ']'. Did you forget a '['?\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast<int>(iter - str.cbegin()), ' ')); + } + bracket_nesting = false; + } + + ++iter; + + // Trim ending whitespace + if (!is_whitespace(value)) + { + // Update element_end after iter is incremented so it will be one past. + element_end = iter; + } + } + + if (element_begin == element_end) { - out.push_back(str.substr(cur)); - break; + Checks::exit_with_message(VCPKG_LINE_INFO, + "Empty element in list\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(static_cast<int>(element_begin - str.cbegin()), ' ')); } - out.push_back(str.substr(cur, pos - cur)); + out.push_back({element_begin, element_end}); - // skip comma and space - ++pos; - while (str[pos] == ' ') + if (iter != str.cend()) { - ++pos; + Checks::check_exit(VCPKG_LINE_INFO, *iter == ',', "Internal parsing error - expected comma"); + + // Not at the end, must be at a comma that needs to be stepped over + ++iter; + + if (iter == str.end()) + { + Checks::exit_with_message(VCPKG_LINE_INFO, + "Empty element in list\n" + "> '%s'\n" + "> %s^\n", + str, + std::string(str.length(), ' ')); + } } - cur = pos; - } while (cur != std::string::npos); + } while (iter != str.cend()); return out; } |
