aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorPhil Christensen <philc@microsoft.com>2019-08-27 11:00:37 -0700
committerGitHub <noreply@github.com>2019-08-27 11:00:37 -0700
commit0eb73051028d5ece1dd837171728fd62c82c1202 (patch)
treef9e2d3e41cd2a2b3119b9d148fae21bb653865cb /toolsrc/src
parent693d05fa965b28fded96d0ded7b1cda84189ff48 (diff)
parent8bae937e1725a85cb7829ad3113debbeef43674a (diff)
downloadvcpkg-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.cpp94
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;
}