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.
This commit is contained in:
parent
93c8b49f61
commit
b210c570fc
4 changed files with 26 additions and 13 deletions
|
|
@ -12,9 +12,9 @@ namespace {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayParser::ArrayParser(const char *array_string)
|
ArrayParser::ArrayParser(const char *array_string, int length)
|
||||||
: data(array_string)
|
: data(array_string)
|
||||||
, end(array_string + strlen(array_string))
|
, end(length >= 0 ? array_string + length : array_string + strlen(array_string))
|
||||||
, pos(array_string)
|
, pos(array_string)
|
||||||
{
|
{
|
||||||
initializeParse();
|
initializeParse();
|
||||||
|
|
@ -36,7 +36,7 @@ ArrayParser::NextElemResult ArrayParser::GetNextElem()
|
||||||
// parse unquoted value, fast path no escapes
|
// parse unquoted value, fast path no escapes
|
||||||
const char *start = pos;
|
const char *start = pos;
|
||||||
while (pos < end && *pos != Seperator && *pos != ArrayEnd) ++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");
|
throw std::runtime_error("Invalid input");
|
||||||
|
|
||||||
result.ok = true;
|
result.ok = true;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Pgsql {
|
||||||
/**
|
/**
|
||||||
* \param data The string that needs parsing (warning just the pointer is stored, the string is not copied)
|
* \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 {
|
class NextElemResult {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ namespace Pgsql {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using value_type = E;
|
using value_type = E;
|
||||||
ArrayParser parser(m_val);
|
ArrayParser parser(m_val, -1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
|
@ -88,7 +88,7 @@ namespace Pgsql {
|
||||||
if (m_val == nullptr) return;
|
if (m_val == nullptr) return;
|
||||||
|
|
||||||
using value_type = E;
|
using value_type = E;
|
||||||
ArrayParser parser(m_val);
|
ArrayParser parser(m_val, -1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
|
@ -111,7 +111,7 @@ namespace Pgsql {
|
||||||
if (m_val == nullptr) return;
|
if (m_val == nullptr) return;
|
||||||
|
|
||||||
using value_type = E;
|
using value_type = E;
|
||||||
ArrayParser parser(m_val);
|
ArrayParser parser(m_val, -1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using namespace Pgsql;
|
||||||
TEST(ArrayParser, emptyInput)
|
TEST(ArrayParser, emptyInput)
|
||||||
{
|
{
|
||||||
const char * input = "";
|
const char * input = "";
|
||||||
ArrayParser parser(input);
|
ArrayParser parser(input, -1);
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
ASSERT_FALSE(res.ok);
|
ASSERT_FALSE(res.ok);
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ TEST(ArrayParser, emptyInput)
|
||||||
TEST(ArrayParser, emptyArray)
|
TEST(ArrayParser, emptyArray)
|
||||||
{
|
{
|
||||||
const char * input = "{}";
|
const char * input = "{}";
|
||||||
ArrayParser parser(input);
|
ArrayParser parser(input, -1);
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
ASSERT_FALSE(res.ok);
|
ASSERT_FALSE(res.ok);
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ TEST(ArrayParser, emptyArray)
|
||||||
TEST(ArrayParser, oneInt)
|
TEST(ArrayParser, oneInt)
|
||||||
{
|
{
|
||||||
const char * input = "{1}";
|
const char * input = "{1}";
|
||||||
ArrayParser parser(input);
|
ArrayParser parser(input, -1);
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
ASSERT_TRUE(res.ok);
|
ASSERT_TRUE(res.ok);
|
||||||
ASSERT_EQ(res.value, "1");
|
ASSERT_EQ(res.value, "1");
|
||||||
|
|
@ -37,7 +37,7 @@ TEST(ArrayParser, oneInt)
|
||||||
TEST(ArrayParser, twoElems)
|
TEST(ArrayParser, twoElems)
|
||||||
{
|
{
|
||||||
const char * input = "{1,2.3}";
|
const char * input = "{1,2.3}";
|
||||||
ArrayParser parser(input);
|
ArrayParser parser(input, -1);
|
||||||
|
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
ASSERT_TRUE(res.ok);
|
ASSERT_TRUE(res.ok);
|
||||||
|
|
@ -54,7 +54,7 @@ TEST(ArrayParser, twoElems)
|
||||||
TEST(ArrayParser, nullElem)
|
TEST(ArrayParser, nullElem)
|
||||||
{
|
{
|
||||||
const char * input = "{NULL}";
|
const char * input = "{NULL}";
|
||||||
ArrayParser parser(input);
|
ArrayParser parser(input, -1);
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
ASSERT_TRUE(res.ok);
|
ASSERT_TRUE(res.ok);
|
||||||
ASSERT_EQ(res.value, std::nullopt);
|
ASSERT_EQ(res.value, std::nullopt);
|
||||||
|
|
@ -71,7 +71,7 @@ TEST(ArrayParser, nullElem)
|
||||||
TEST(ArrayParser, quotedValues)
|
TEST(ArrayParser, quotedValues)
|
||||||
{
|
{
|
||||||
const char * input = R"_({"ab c","de\"f"})_";
|
const char * input = R"_({"ab c","de\"f"})_";
|
||||||
ArrayParser parser(input);
|
ArrayParser parser(input, -1);
|
||||||
auto res = parser.GetNextElem();
|
auto res = parser.GetNextElem();
|
||||||
ASSERT_TRUE(res.ok);
|
ASSERT_TRUE(res.ok);
|
||||||
ASSERT_EQ(res.value, "ab c");
|
ASSERT_EQ(res.value, "ab c");
|
||||||
|
|
@ -84,6 +84,19 @@ TEST(ArrayParser, quotedValues)
|
||||||
ASSERT_FALSE(res.ok);
|
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]
|
// ARRAY['2017-12-11'::date, NULL]
|
||||||
// {2017-12-11,NULL}
|
// {2017-12-11,NULL}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue