Skip to content

Commit 222920f

Browse files
committed
HPCC-33539 Support brackets in the compression options
Signed-off-by: Gavin Halliday <[email protected]>
1 parent ecc5d90 commit 222920f

File tree

2 files changed

+81
-15
lines changed

2 files changed

+81
-15
lines changed

system/jlib/jstring.cpp

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2829,6 +2829,12 @@ bool loadBinaryFile(StringBuffer & contents, const char *filename, bool throwOnE
28292829
return ok;
28302830
}
28312831

2832+
2833+
//Support option1=value1,option2(value2),option3,option4(nested=value,nested(value))
2834+
// option1: value1
2835+
// option2: value2
2836+
// option3: 1
2837+
// option4: nested=value,nested(value)
28322838
void processOptionString(const char * options, optionCallback callback)
28332839
{
28342840
if (!options || !callback)
@@ -2838,33 +2844,61 @@ void processOptionString(const char * options, optionCallback callback)
28382844
StringBuffer value;
28392845
while (true)
28402846
{
2841-
const char * comma = strchr(options, ',');
2842-
const char * eq = strchr(options, '=');
2843-
if (comma && eq)
2847+
const char * start = options;
2848+
const char * endname = nullptr;
2849+
const char * end = nullptr;
2850+
const char * comma = nullptr;
2851+
unsigned nesting = 0;
2852+
for (;;)
28442853
{
2845-
if (comma < eq)
2846-
eq = nullptr;
2847-
else
2854+
byte next = *options;
2855+
if (next == '\0')
2856+
break;
2857+
else if (next == '(')
2858+
{
2859+
if ((nesting++ == 0) && !endname)
2860+
endname = options;
2861+
}
2862+
else if (next == ')')
2863+
{
2864+
if (nesting && --nesting==0 && !end)
2865+
{
2866+
end = options;
2867+
//All text after the closing ) until a comma is ignored.
2868+
}
2869+
}
2870+
else if (next == '=')
2871+
{
2872+
if (!nesting && !endname)
2873+
{
2874+
endname = options;
2875+
}
2876+
}
2877+
else if (next == ',' && nesting == 0)
28482878
{
2849-
//Could optionally see if the value is quoted, and if so scan for the terminator to allow quoted commas
2850-
//but then you may have problems with quoted quotes... so leave as-is for the moment
2879+
if (!end)
2880+
end = options;
2881+
comma = options;
2882+
break;
28512883
}
2884+
options++;
28522885
}
2886+
28532887
option.clear();
28542888
value.clear();
2855-
if (eq)
2889+
if (endname)
28562890
{
2857-
option.append(eq-options, options);
2858-
if (comma)
2859-
value.append(comma-(eq+1), eq+1);
2891+
option.append(endname-start, start);
2892+
if (end)
2893+
value.append(end-(endname+1), endname+1);
28602894
else
2861-
value.append(eq+1);
2895+
value.append(endname+1);
28622896
}
28632897
else
28642898
{
28652899
value.append("1");
2866-
if (comma)
2867-
option.append(comma-options, options);
2900+
if (end)
2901+
option.append(end-start, start);
28682902
else
28692903
option.append(options);
28702904
}

testing/unittests/jlibtests.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4635,6 +4635,7 @@ class JLibStringTest : public CppUnit::TestFixture
46354635
CPPUNIT_TEST_SUITE(JLibStringTest);
46364636
CPPUNIT_TEST(testStristr);
46374637
CPPUNIT_TEST(testMemMem);
4638+
CPPUNIT_TEST(testProcessOptions);
46384639
CPPUNIT_TEST_SUITE_END();
46394640

46404641
void testStristr()
@@ -4667,6 +4668,37 @@ class JLibStringTest : public CppUnit::TestFixture
46674668
CPPUNIT_ASSERT_EQUAL((const void*)(nullptr), jmemmem(9, haystack, 2, "ij"));
46684669
CPPUNIT_ASSERT_EQUAL((const void*)(haystack+8), jmemmem(10, haystack, 2, "ij"));
46694670
}
4671+
4672+
void testOption(const char * text, const std::initializer_list<std::pair<const char *, const char *>> & expected)
4673+
{
4674+
StringArray options;
4675+
StringArray values;
4676+
4677+
auto processOption = [this,&options,&values](const char * option, const char * value)
4678+
{
4679+
options.append(option);
4680+
values.append(value);
4681+
};
4682+
4683+
processOptionString(text, processOption);
4684+
4685+
CPPUNIT_ASSERT_EQUAL(options.ordinality(), (unsigned)expected.size());
4686+
ForEachItemIn(i, options)
4687+
{
4688+
CPPUNIT_ASSERT_EQUAL(std::string(expected.begin()[i].first), std::string(options.item(i)));
4689+
CPPUNIT_ASSERT_EQUAL(std::string(expected.begin()[i].second), std::string(values.item(i)));
4690+
}
4691+
}
4692+
4693+
void testProcessOptions()
4694+
{
4695+
testOption("name=boris", {{"name", "boris"}});
4696+
testOption("name(boris)", {{"name", "boris"}});
4697+
testOption("name=boris,age(99)", {{"name", "boris"}, {"age", "99"}});
4698+
testOption("name=boris", {{"name", "boris"}});
4699+
testOption("option1=value1,option2(value2),option3,option4(nested=value,nested(value))",
4700+
{{"option1", "value1"}, {"option2", "value2"}, {"option3", "1"}, {"option4", "nested=value,nested(value)"}});
4701+
}
46704702
};
46714703

46724704
CPPUNIT_TEST_SUITE_REGISTRATION( JLibStringTest );

0 commit comments

Comments
 (0)