diff --git a/src/JSON.cc b/src/JSON.cc index 4800a1e67..5cf949cd7 100644 --- a/src/JSON.cc +++ b/src/JSON.cc @@ -93,28 +93,70 @@ JSON& JSON::operator=(JSON o) { } #else JSON& JSON::operator=(const JSON& o) { + // check for self-assignment + if (&o == this) { + return *this; + } + + switch (_type) { + case (array): { + delete static_cast*>(_payload); + break; + } + case (object): { + delete static_cast*>(_payload); + break; + } + case (string): { + delete static_cast(_payload); + break; + } + case (boolean): { + delete static_cast(_payload); + break; + } + case (number_int): { + delete static_cast(_payload); + break; + } + case (number_float): { + delete static_cast(_payload); + break; + } + case (null): { + break; + } + } + _type = o._type; switch (_type) { - case (array): + case (array): { _payload = new std::vector(*static_cast*>(o._payload)); break; - case (object): + } + case (object): { _payload = new std::map(*static_cast*>(o._payload)); break; - case (string): + } + case (string): { _payload = new std::string(*static_cast(o._payload)); break; - case (boolean): + } + case (boolean): { _payload = new bool(*static_cast(o._payload)); break; - case (number_int): + } + case (number_int): { _payload = new int(*static_cast(o._payload)); break; - case (number_float): + } + case (number_float): { _payload = new double(*static_cast(o._payload)); break; - case (null): + } + case (null): { break; + } } return *this; @@ -124,26 +166,33 @@ JSON& JSON::operator=(const JSON& o) { /// destructor JSON::~JSON() { switch (_type) { - case (array): + case (array): { delete static_cast*>(_payload); break; - case (object): + } + case (object): { delete static_cast*>(_payload); break; - case (string): + } + case (string): { delete static_cast(_payload); break; - case (boolean): + } + case (boolean): { delete static_cast(_payload); break; - case (number_int): + } + case (number_int): { delete static_cast(_payload); break; - case (number_float): + } + case (number_float): { delete static_cast(_payload); break; - case (null): + } + case (null): { break; + } } } @@ -567,10 +616,6 @@ void JSON::parser::error(std::string msg) { bool JSON::parser::next() { _current = _buffer[_pos++]; - if (_buffer == nullptr) { - return false; - } - // skip trailing whitespace while (std::isspace(_current)) { _current = _buffer[_pos++]; @@ -579,13 +624,21 @@ bool JSON::parser::next() { return true; } -/// \todo: escaped strings std::string JSON::parser::parseString() { - // get position of closing quote - const char* p = strchr(_buffer + _pos, '\"'); + // get position of closing quotes + char* p = strchr(_buffer + _pos, '\"'); - // check if quotes were found - if (!p) { + // if the closing quotes are escaped (viz. *(p-1) is '\\'), + // we continue looking for the "right" quotes + while (p != nullptr and * (p - 1) == '\\') { + // length of the string so far + const size_t length = p - _buffer - _pos; + // continue checking after escaped quote + p = strchr(_buffer + _pos + length + 1, '\"'); + } + + // check if closing quotes were found + if (p == nullptr) { error("expected '\"'"); } @@ -654,8 +707,6 @@ void JSON::parser::parse(JSON& result) { error("unexpected end of file"); } - //JSON result; - switch (_current) { case ('{'): { // explicitly set result to object to cope with {} diff --git a/test/JSON_test.cc b/test/JSON_test.cc index 683a6f5d3..3836ba12d 100644 --- a/test/JSON_test.cc +++ b/test/JSON_test.cc @@ -74,6 +74,14 @@ void test_null() { } } + +void test_bool() { + JSON True = true; + JSON False = false; + + bool x = True; +} + void test_string() { /* a string object */ @@ -135,6 +143,13 @@ void test_string() { } catch (const std::exception& ex) { assert(ex.what() == std::string("cannot cast string to JSON Boolean")); } + + { + // get payload + std::string* s1 = static_cast(a.data()); + std::string s2 = a; + assert(*s1 == s2); + } } void test_array() { @@ -200,6 +215,13 @@ void test_array() { std::cerr << element << '\n'; } #endif + + { + // get payload + std::vector* array = static_cast*>(a.data()); + assert(array->size() == a.size()); + assert(array->empty() == a.empty()); + } } void test_streaming() { @@ -224,10 +246,35 @@ void test_streaming() { o >> k; assert(j.toString() == k.toString()); } + + // check numbers + { + std::stringstream number_stream; + number_stream << "[0, -1, 1, 1.0, -1.0, 1.0e+1, 1.0e-1, 1.0E+1, 1.0E-1, -1.2345678e-12345678]"; + JSON j; + j << number_stream; + } + + // check Unicode + { + std::stringstream unicode_stream; + unicode_stream << "[\"öäüÖÄÜß\", \"ÀÁÂÃĀĂȦ\", \"★☆→➠♥︎♦︎☁︎\"]"; + JSON j; + j << unicode_stream; + } + + // check escaped strings + { + std::stringstream escaped_stream; + escaped_stream << "[\"\\\"Hallo\\\"\", \"\u0123\"]"; + JSON j; + j << escaped_stream; + } } int main() { test_null(); + test_bool(); test_string(); test_array(); test_streaming();