From b210c570fcedb7c943910e5deaec90327228817a Mon Sep 17 00:00:00 2001 From: eelke Date: Mon, 24 Dec 2018 08:10:09 +0100 Subject: [PATCH] ArrayParser doesn't require the string to be null terminated anymore, instead the length of the string can be passed in. This is first step in process to allow Value to work without null terminator. --- pgsql/ArrayParser.cpp | 6 +++--- pgsql/ArrayParser.h | 2 +- pgsql/Pgsql_Value.h | 6 +++--- tests/PgsqlTests/tst_ArrayParser.cpp | 25 +++++++++++++++++++------ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/pgsql/ArrayParser.cpp b/pgsql/ArrayParser.cpp index e629a4e..4d93b6b 100644 --- a/pgsql/ArrayParser.cpp +++ b/pgsql/ArrayParser.cpp @@ -12,9 +12,9 @@ namespace { } -ArrayParser::ArrayParser(const char *array_string) +ArrayParser::ArrayParser(const char *array_string, int length) : data(array_string) - , end(array_string + strlen(array_string)) + , end(length >= 0 ? array_string + length : array_string + strlen(array_string)) , pos(array_string) { initializeParse(); @@ -36,7 +36,7 @@ ArrayParser::NextElemResult ArrayParser::GetNextElem() // parse unquoted value, fast path no escapes const char *start = pos; while (pos < end && *pos != Seperator && *pos != ArrayEnd) ++pos; - if (*pos == 0) // reached end of data shouldn't happen + if (pos == end) // reached end of data shouldn't happen throw std::runtime_error("Invalid input"); result.ok = true; diff --git a/pgsql/ArrayParser.h b/pgsql/ArrayParser.h index f1ca1e0..93ae1cd 100644 --- a/pgsql/ArrayParser.h +++ b/pgsql/ArrayParser.h @@ -18,7 +18,7 @@ namespace Pgsql { /** * \param data The string that needs parsing (warning just the pointer is stored, the string is not copied) */ - explicit ArrayParser(const char *array_string); + ArrayParser(const char *array_string, int length); class NextElemResult { public: diff --git a/pgsql/Pgsql_Value.h b/pgsql/Pgsql_Value.h index 2ce89cb..bc0e80b 100644 --- a/pgsql/Pgsql_Value.h +++ b/pgsql/Pgsql_Value.h @@ -60,7 +60,7 @@ namespace Pgsql { } else { using value_type = E; - ArrayParser parser(m_val); + ArrayParser parser(m_val, -1); for (;;) { auto res = parser.GetNextElem(); if (res.ok) { @@ -88,7 +88,7 @@ namespace Pgsql { if (m_val == nullptr) return; using value_type = E; - ArrayParser parser(m_val); + ArrayParser parser(m_val, -1); for (;;) { auto res = parser.GetNextElem(); if (res.ok) { @@ -111,7 +111,7 @@ namespace Pgsql { if (m_val == nullptr) return; using value_type = E; - ArrayParser parser(m_val); + ArrayParser parser(m_val, -1); for (;;) { auto res = parser.GetNextElem(); if (res.ok) { diff --git a/tests/PgsqlTests/tst_ArrayParser.cpp b/tests/PgsqlTests/tst_ArrayParser.cpp index 3827c04..b6c3355 100644 --- a/tests/PgsqlTests/tst_ArrayParser.cpp +++ b/tests/PgsqlTests/tst_ArrayParser.cpp @@ -9,7 +9,7 @@ using namespace Pgsql; TEST(ArrayParser, emptyInput) { const char * input = ""; - ArrayParser parser(input); + ArrayParser parser(input, -1); auto res = parser.GetNextElem(); ASSERT_FALSE(res.ok); } @@ -17,7 +17,7 @@ TEST(ArrayParser, emptyInput) TEST(ArrayParser, emptyArray) { const char * input = "{}"; - ArrayParser parser(input); + ArrayParser parser(input, -1); auto res = parser.GetNextElem(); ASSERT_FALSE(res.ok); } @@ -25,7 +25,7 @@ TEST(ArrayParser, emptyArray) TEST(ArrayParser, oneInt) { const char * input = "{1}"; - ArrayParser parser(input); + ArrayParser parser(input, -1); auto res = parser.GetNextElem(); ASSERT_TRUE(res.ok); ASSERT_EQ(res.value, "1"); @@ -37,7 +37,7 @@ TEST(ArrayParser, oneInt) TEST(ArrayParser, twoElems) { const char * input = "{1,2.3}"; - ArrayParser parser(input); + ArrayParser parser(input, -1); auto res = parser.GetNextElem(); ASSERT_TRUE(res.ok); @@ -54,7 +54,7 @@ TEST(ArrayParser, twoElems) TEST(ArrayParser, nullElem) { const char * input = "{NULL}"; - ArrayParser parser(input); + ArrayParser parser(input, -1); auto res = parser.GetNextElem(); ASSERT_TRUE(res.ok); ASSERT_EQ(res.value, std::nullopt); @@ -71,7 +71,7 @@ TEST(ArrayParser, nullElem) TEST(ArrayParser, quotedValues) { const char * input = R"_({"ab c","de\"f"})_"; - ArrayParser parser(input); + ArrayParser parser(input, -1); auto res = parser.GetNextElem(); ASSERT_TRUE(res.ok); ASSERT_EQ(res.value, "ab c"); @@ -84,6 +84,19 @@ TEST(ArrayParser, quotedValues) ASSERT_FALSE(res.ok); } +TEST(ArrayParser, unexpectedEndWithNullTerminator) +{ + const char * input = "{abc"; + ArrayParser parser(input, -1); + ASSERT_THROW(parser.GetNextElem(), std::runtime_error); +} + +TEST(ArrayParser, unexpectedEndWithoutNullTerminator) +{ + const char * input = "{abc"; + ArrayParser parser(input, 3); // 3 will put c past the end + ASSERT_THROW(parser.GetNextElem(), std::runtime_error); +} // ARRAY['2017-12-11'::date, NULL] // {2017-12-11,NULL}