From 7e7da21b107461ad7f97a60aec0db9688cb5b63b Mon Sep 17 00:00:00 2001 From: Avinash Kumar Deepak Date: Mon, 12 Oct 2026 22:10:48 +0530 Subject: [PATCH] handle comma-containing values in parsedict() --- .github/workflows/ci.yml | 3 +- TestConcoreHpp.cpp | 15 +++++++++ concore_base.hpp | 66 ++++++++++++++++++++++++++-------------- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c297b79..0e0290f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,7 +147,8 @@ jobs: - name: Download jeromq run: | - curl -fsSL -o jeromq.jar https://repo1.maven.org/maven2/org/zeromq/jeromq/0.6.0/jeromq-0.6.0.jar + curl -fsSL --retry 5 --retry-connrefused -A "Mozilla/5.0" -o jeromq.jar https://repo1.maven.org/maven2/org/zeromq/jeromq/0.6.0/jeromq-0.6.0.jar || \ + curl -fsSL --retry 5 --retry-connrefused -A "Mozilla/5.0" -o jeromq.jar https://repo.maven.apache.org/maven2/org/zeromq/jeromq/0.6.0/jeromq-0.6.0.jar - name: Compile Java tests run: | diff --git a/TestConcoreHpp.cpp b/TestConcoreHpp.cpp index 90d989e..2a10195 100644 --- a/TestConcoreHpp.cpp +++ b/TestConcoreHpp.cpp @@ -302,6 +302,20 @@ static void test_load_params_semicolon_format() { rm("in/1/concore.params"); } +static void test_tryparam_comma_in_value() { + setup_dirs(); + write_file("in/1/concore.params", "{'channels': [1, 2], 'gain': '0.5'}"); + + Concore c; + c.delay = 0; + c.load_params(); + + check("tryparam preserves list with comma", c.tryparam("channels", "") == "[1, 2]"); + check("tryparam preserves subsequent key", c.tryparam("gain", "") == "0.5"); + + rm("in/1/concore.params"); +} + // ------------- main ------------------------------------------------------- int main() { @@ -337,6 +351,7 @@ int main() { test_tryparam_found(); test_tryparam_missing_key_uses_default(); test_load_params_semicolon_format(); + test_tryparam_comma_in_value(); std::cout << "\n=== Results: " << passed << " passed, " << failed << " failed out of " << (passed + failed) << " tests ===\n"; diff --git a/concore_base.hpp b/concore_base.hpp index f38b6ed..524d5ba 100644 --- a/concore_base.hpp +++ b/concore_base.hpp @@ -41,28 +41,7 @@ inline std::string stripquotes(const std::string& str) { // Parsing Utilities // =================================================================== -/** - * Parses a Python-style dict string into a string→string map. - * Format: {'key1': val1, 'key2': val2} - * Handles both quoted and unquoted keys/values. - */ -inline std::map parsedict(const std::string& str) { - std::map result; - std::string trimmed = stripstr(str); - if (trimmed.size() < 2 || trimmed.front() != '{' || trimmed.back() != '}') - return result; - std::string inner = trimmed.substr(1, trimmed.size() - 2); - std::stringstream ss(inner); - std::string token; - while (std::getline(ss, token, ',')) { - size_t colon = token.find(':'); - if (colon == std::string::npos) continue; - std::string key = stripquotes(stripstr(token.substr(0, colon))); - std::string val = stripquotes(stripstr(token.substr(colon + 1))); - if (!key.empty()) result[key] = val; - } - return result; -} +inline std::map parsedict(const std::string& str); /** * Parses a Python-style list string into a vector of strings. @@ -254,6 +233,49 @@ inline ConcoreValue parse_literal(const std::string& s) { return v; } +/** + * Parses a Python-style dict string into a string→string map. + * Format: {'key1': val1, 'key2': val2} + * Handles both quoted and unquoted keys/values. + */ +inline std::map parsedict(const std::string& str) { + std::map result; + std::string trimmed = stripstr(str); + if (trimmed.size() < 2 || trimmed.front() != '{' || trimmed.back() != '}') + return result; + + size_t pos = 1; + while (pos < trimmed.size()) { + skip_ws(trimmed, pos); + if (pos >= trimmed.size() || trimmed[pos] == '}') break; + + std::string key; + if (trimmed[pos] == '\'' || trimmed[pos] == '"') { + key = parse_literal_string(trimmed, pos).str; + } else { + size_t key_start = pos; + while (pos < trimmed.size() && trimmed[pos] != ':' && !std::isspace(static_cast(trimmed[pos]))) + ++pos; + key = trimmed.substr(key_start, pos - key_start); + } + + skip_ws(trimmed, pos); + if (pos >= trimmed.size() || trimmed[pos] != ':') break; + ++pos; + + skip_ws(trimmed, pos); + size_t val_start = pos; + parse_literal_value(trimmed, pos); + std::string val = stripquotes(stripstr(trimmed.substr(val_start, pos - val_start))); + + if (!key.empty()) result[key] = val; + + skip_ws(trimmed, pos); + if (pos < trimmed.size() && trimmed[pos] == ',') ++pos; + } + return result; +} + inline void flatten_numeric_impl(const ConcoreValue& v, std::vector& out) { switch (v.type) { case ConcoreValueType::NUMBER: