return counter;
}
+size_t parseSVCBValueList(const std::string &in, std::vector<std::string> &val) {
+ val.clear();
+ const char *p = in.c_str();
+ const char *pe = p + in.size();
+ int cs = 0;
+ uint8_t escaped_octet = 0;
+ // Keeps track of how many chars we read from the source string
+ size_t counter=0;
+
+ // Here we store the parsed value until we hit a comma or are done
+ std::string tmp;
+
+%%{
+ machine dns_text_to_value_list;
+
+ action doEscapedNumber {
+ escaped_octet *= 10;
+ escaped_octet += fc-'0';
+ counter++;
+ }
+
+ action doneEscapedNumber {
+ tmp += escaped_octet;
+ escaped_octet = 0;
+ }
+
+ action addToVal {
+ tmp += fc;
+ counter++;
+ }
+
+ action handleComma {
+ val.push_back(tmp);
+ tmp.clear();
+ counter++;
+ }
+
+ action incrementCounter {
+ counter++;
+ }
+
+ # generated rules, define required actions
+ DIGIT = 0x30..0x39;
+ DQUOTE = "\"";
+ HTAB = "\t";
+ SP = " ";
+ WSP = (SP | HTAB)@addToVal;
+ non_special = "!" | 0x23..0x27 | 0x2a..0x2b | 0x2d..0x3a | 0x3c..0x5b | 0x5d..0x7e;
+ non_digit = 0x21..0x2f | 0x3a..0x7e;
+ dec_octet = ( ( "0" | "1" ) DIGIT{2} ) | ( "2" ( ( 0x30..0x34 DIGIT ) | ( "5" 0x30..0x35 ) ) );
+ escaped = '\\'@incrementCounter ( non_digit$addToVal | dec_octet$doEscapedNumber@doneEscapedNumber );
+ contiguous = ( non_special$addToVal | escaped )+;
+ comma = ',';
+ quoted_sepped = ( contiguous | ('\\'? WSP) )* (comma@handleComma ( contiguous | ('\\'? WSP) )+ )*;
+ unquoted_sepped = (contiguous (comma@handleComma contiguous)*);
+ quoted = DQUOTE@incrementCounter quoted_sepped DQUOTE@incrementCounter;
+ char_string = (quoted | unquoted_sepped);
+
+ # instantiate machine rules
+ main := char_string;
+ write data;
+ write init;
+}%%
+
+ // silence warnings
+ (void) dns_text_to_value_list_first_final;
+ (void) dns_text_to_value_list_error;
+ (void) dns_text_to_value_list_en_main;
+ %% write exec;
+
+ // Add the last-parsed value to val
+ // ideally, we'd use a transition as well, but too many hours were wasted trying that
+ val.push_back(tmp);
+ return counter;
+}
#if 0
BOOST_CHECK_EQUAL(my_hostname.size(), hostname.size());
}
+BOOST_AUTO_TEST_CASE(test_parseSVCBValueList)
+{
+ vector<string> out;
+
+ parseSVCBValueList("foobar123", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123");
+
+ parseSVCBValueList("h2,h3", out);
+ BOOST_CHECK_EQUAL(out.size(), 2);
+ BOOST_CHECK_EQUAL(out[0], "h2");
+ BOOST_CHECK_EQUAL(out[1], "h3");
+
+ parseSVCBValueList("h2,h3-19,h3-20,h3-22", out);
+ BOOST_CHECK_EQUAL(out.size(), 4);
+ BOOST_CHECK_EQUAL(out[0], "h2");
+ BOOST_CHECK_EQUAL(out[1], "h3-19");
+ BOOST_CHECK_EQUAL(out[2], "h3-20");
+ BOOST_CHECK_EQUAL(out[3], "h3-22");
+
+ parseSVCBValueList("foobar123,bazquux456", out);
+ BOOST_CHECK_EQUAL(out.size(), 2);
+ BOOST_CHECK_EQUAL(out[0], "foobar123");
+ BOOST_CHECK_EQUAL(out[1], "bazquux456");
+
+ parseSVCBValueList("foobar123\\,bazquux456", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123,bazquux456");
+
+ parseSVCBValueList("foobar123\\044bazquux456", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123,bazquux456");
+
+ // Again, but quoted
+ parseSVCBValueList("\"foobar123\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123");
+
+ parseSVCBValueList("\"foobar123,bazquux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 2);
+ BOOST_CHECK_EQUAL(out[0], "foobar123");
+ BOOST_CHECK_EQUAL(out[1], "bazquux456");
+
+ parseSVCBValueList("\"foobar123\\,bazquux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123,bazquux456");
+
+ parseSVCBValueList("\"foobar123\\044bazquux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123,bazquux456");
+
+ // Quoted, with some whitespace
+ parseSVCBValueList("\"foobar123 \"", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123 ");
+
+ parseSVCBValueList("\"foobar123 blabla bla,baz quux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 2);
+ BOOST_CHECK_EQUAL(out[0], "foobar123 blabla bla");
+ BOOST_CHECK_EQUAL(out[1], "baz quux456");
+
+ parseSVCBValueList("\"foobar123,baz quux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 2);
+ BOOST_CHECK_EQUAL(out[0], "foobar123");
+ BOOST_CHECK_EQUAL(out[1], "baz quux456");
+
+ parseSVCBValueList("\"foobar123 blabla bla\\,baz quux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123 blabla bla,baz quux456");
+
+ parseSVCBValueList("\"foobar123 blabla bla\\044baz quux456\"", out);
+ BOOST_CHECK_EQUAL(out.size(), 1);
+ BOOST_CHECK_EQUAL(out[0], "foobar123 blabla bla,baz quux456");
+}
+
BOOST_AUTO_TEST_SUITE_END()