diff options
Diffstat (limited to 'libqpdf/JSON.cc')
-rw-r--r-- | libqpdf/JSON.cc | 708 |
1 files changed, 260 insertions, 448 deletions
diff --git a/libqpdf/JSON.cc b/libqpdf/JSON.cc index 3f96ab5d..4f2a14d9 100644 --- a/libqpdf/JSON.cc +++ b/libqpdf/JSON.cc @@ -1,9 +1,9 @@ #include <qpdf/JSON.hh> -#include <qpdf/QUtil.hh> #include <qpdf/QTC.hh> -#include <stdexcept> +#include <qpdf/QUtil.hh> #include <cstring> +#include <stdexcept> JSON::Members::~Members() { @@ -27,27 +27,23 @@ JSON::JSON_dictionary::~JSON_dictionary() { } -std::string JSON::JSON_dictionary::unparse(size_t depth) const +std::string +JSON::JSON_dictionary::unparse(size_t depth) const { std::string result = "{"; bool first = true; - for (auto const& iter: members) - { - if (first) - { + for (auto const& iter : members) { + if (first) { first = false; - } - else - { + } else { result.append(1, ','); } result.append(1, '\n'); result.append(2 * (1 + depth), ' '); - result += ("\"" + iter.first + "\": " + - iter.second->unparse(1 + depth)); + result += + ("\"" + iter.first + "\": " + iter.second->unparse(1 + depth)); } - if (! first) - { + if (!first) { result.append(1, '\n'); result.append(2 * depth, ' '); } @@ -59,26 +55,22 @@ JSON::JSON_array::~JSON_array() { } -std::string JSON::JSON_array::unparse(size_t depth) const +std::string +JSON::JSON_array::unparse(size_t depth) const { std::string result = "["; bool first = true; - for (auto const& element: elements) - { - if (first) - { + for (auto const& element : elements) { + if (first) { first = false; - } - else - { + } else { result.append(1, ','); } result.append(1, '\n'); result.append(2 * (1 + depth), ' '); result += element->unparse(1 + depth); } - if (! first) - { + if (!first) { result.append(1, '\n'); result.append(2 * depth, ' '); } @@ -96,7 +88,8 @@ JSON::JSON_string::~JSON_string() { } -std::string JSON::JSON_string::unparse(size_t) const +std::string +JSON::JSON_string::unparse(size_t) const { return "\"" + encoded + "\""; } @@ -120,7 +113,8 @@ JSON::JSON_number::~JSON_number() { } -std::string JSON::JSON_number::unparse(size_t) const +std::string +JSON::JSON_number::unparse(size_t) const { return encoded; } @@ -134,7 +128,8 @@ JSON::JSON_bool::~JSON_bool() { } -std::string JSON::JSON_bool::unparse(size_t) const +std::string +JSON::JSON_bool::unparse(size_t) const { return value ? "true" : "false"; } @@ -143,7 +138,8 @@ JSON::JSON_null::~JSON_null() { } -std::string JSON::JSON_null::unparse(size_t) const +std::string +JSON::JSON_null::unparse(size_t) const { return "null"; } @@ -151,12 +147,9 @@ std::string JSON::JSON_null::unparse(size_t) const std::string JSON::unparse() const { - if (0 == this->m->value.get()) - { + if (0 == this->m->value.get()) { return "null"; - } - else - { + } else { return this->m->value->unparse(0); } } @@ -166,39 +159,34 @@ JSON::encode_string(std::string const& str) { std::string result; size_t len = str.length(); - for (size_t i = 0; i < len; ++i) - { + for (size_t i = 0; i < len; ++i) { unsigned char ch = static_cast<unsigned char>(str.at(i)); - switch (ch) - { - case '\\': + switch (ch) { + case '\\': result += "\\\\"; break; - case '\"': + case '\"': result += "\\\""; break; - case '\b': + case '\b': result += "\\b"; break; - case '\f': + case '\f': result += "\\f"; break; - case '\n': + case '\n': result += "\\n"; break; - case '\r': + case '\r': result += "\\r"; break; - case '\t': + case '\t': result += "\\t"; break; - default: - if (ch < 32) - { + default: + if (ch < 32) { result += "\\u" + QUtil::int_to_string_base(ch, 16, 4); - } - else - { + } else { result.append(1, static_cast<char>(ch)); } } @@ -215,19 +203,14 @@ JSON::makeDictionary() JSON JSON::addDictionaryMember(std::string const& key, JSON const& val) { - JSON_dictionary* obj = dynamic_cast<JSON_dictionary*>( - this->m->value.get()); - if (0 == obj) - { + JSON_dictionary* obj = dynamic_cast<JSON_dictionary*>(this->m->value.get()); + if (0 == obj) { throw std::runtime_error( "JSON::addDictionaryMember called on non-dictionary"); } - if (val.m->value.get()) - { + if (val.m->value.get()) { obj->members[encode_string(key)] = val.m->value; - } - else - { + } else { obj->members[encode_string(key)] = std::make_shared<JSON_null>(); } return obj->members[encode_string(key)]; @@ -242,18 +225,13 @@ JSON::makeArray() JSON JSON::addArrayElement(JSON const& val) { - JSON_array* arr = dynamic_cast<JSON_array*>( - this->m->value.get()); - if (0 == arr) - { + JSON_array* arr = dynamic_cast<JSON_array*>(this->m->value.get()); + if (0 == arr) { throw std::runtime_error("JSON::addArrayElement called on non-array"); } - if (val.m->value.get()) - { + if (val.m->value.get()) { arr->elements.push_back(val.m->value); - } - else - { + } else { arr->elements.push_back(std::make_shared<JSON_null>()); } return arr->elements.back(); @@ -298,23 +276,21 @@ JSON::makeNull() bool JSON::isArray() const { - return nullptr != dynamic_cast<JSON_array const*>( - this->m->value.get()); + return nullptr != dynamic_cast<JSON_array const*>(this->m->value.get()); } bool JSON::isDictionary() const { - return nullptr != dynamic_cast<JSON_dictionary const*>( - this->m->value.get()); + return nullptr != + dynamic_cast<JSON_dictionary const*>(this->m->value.get()); } bool JSON::getString(std::string& utf8) const { auto v = dynamic_cast<JSON_string const*>(this->m->value.get()); - if (v == nullptr) - { + if (v == nullptr) { return false; } utf8 = v->utf8; @@ -325,8 +301,7 @@ bool JSON::getNumber(std::string& value) const { auto v = dynamic_cast<JSON_number const*>(this->m->value.get()); - if (v == nullptr) - { + if (v == nullptr) { return false; } value = v->encoded; @@ -337,8 +312,7 @@ bool JSON::getBool(bool& value) const { auto v = dynamic_cast<JSON_bool const*>(this->m->value.get()); - if (v == nullptr) - { + if (v == nullptr) { return false; } value = v->value; @@ -348,8 +322,7 @@ JSON::getBool(bool& value) const bool JSON::isNull() const { - if (dynamic_cast<JSON_null const*>(this->m->value.get())) - { + if (dynamic_cast<JSON_null const*>(this->m->value.get())) { return true; } return false; @@ -360,12 +333,10 @@ JSON::forEachDictItem( std::function<void(std::string const& key, JSON value)> fn) const { auto v = dynamic_cast<JSON_dictionary const*>(this->m->value.get()); - if (v == nullptr) - { + if (v == nullptr) { return false; } - for (auto const& k: v->members) - { + for (auto const& k : v->members) { fn(k.first, JSON(k.second)); } return true; @@ -375,12 +346,10 @@ bool JSON::forEachArrayItem(std::function<void(JSON value)> fn) const { auto v = dynamic_cast<JSON_array const*>(this->m->value.get()); - if (v == nullptr) - { + if (v == nullptr) { return false; } - for (auto const& i: v->elements) - { + for (auto const& i : v->elements) { fn(JSON(i)); } return true; @@ -389,25 +358,25 @@ JSON::forEachArrayItem(std::function<void(JSON value)> fn) const bool JSON::checkSchema(JSON schema, std::list<std::string>& errors) { - return checkSchemaInternal(this->m->value.get(), - schema.m->value.get(), - 0, errors, ""); + return checkSchemaInternal( + this->m->value.get(), schema.m->value.get(), 0, errors, ""); } bool -JSON::checkSchema(JSON schema, unsigned long flags, - std::list<std::string>& errors) +JSON::checkSchema( + JSON schema, unsigned long flags, std::list<std::string>& errors) { - return checkSchemaInternal(this->m->value.get(), - schema.m->value.get(), - flags, errors, ""); + return checkSchemaInternal( + this->m->value.get(), schema.m->value.get(), flags, errors, ""); } bool -JSON::checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v, - unsigned long flags, - std::list<std::string>& errors, - std::string prefix) +JSON::checkSchemaInternal( + JSON_value* this_v, + JSON_value* sch_v, + unsigned long flags, + std::list<std::string>& errors, + std::string prefix) { JSON_array* this_arr = dynamic_cast<JSON_array*>(this_v); JSON_dictionary* this_dict = dynamic_cast<JSON_dictionary*>(this_v); @@ -418,20 +387,15 @@ JSON::checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v, JSON_string* sch_str = dynamic_cast<JSON_string*>(sch_v); std::string err_prefix; - if (prefix.empty()) - { + if (prefix.empty()) { err_prefix = "top-level object"; - } - else - { + } else { err_prefix = "json key \"" + prefix + "\""; } std::string pattern_key; - if (sch_dict) - { - if (! this_dict) - { + if (sch_dict) { + if (!this_dict) { QTC::TC("libtests", "JSON wanted dictionary"); errors.push_back(err_prefix + " is supposed to be a dictionary"); return false; @@ -440,44 +404,36 @@ JSON::checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v, std::string key; if ((members.size() == 1) && ((key = members.begin()->first, key.length() > 2) && - (key.at(0) == '<') && - (key.at(key.length() - 1) == '>'))) - { + (key.at(0) == '<') && (key.at(key.length() - 1) == '>'))) { pattern_key = key; } } - if (sch_dict && (! pattern_key.empty())) - { + if (sch_dict && (!pattern_key.empty())) { auto pattern_schema = sch_dict->members[pattern_key].get(); - for (auto const& iter: this_dict->members) - { + for (auto const& iter : this_dict->members) { std::string const& key = iter.first; checkSchemaInternal( - this_dict->members[key].get(), pattern_schema, - flags, errors, prefix + "." + key); + this_dict->members[key].get(), + pattern_schema, + flags, + errors, + prefix + "." + key); } - } - else if (sch_dict) - { - for (auto& iter: sch_dict->members) - { + } else if (sch_dict) { + for (auto& iter : sch_dict->members) { std::string const& key = iter.first; - if (this_dict->members.count(key)) - { + if (this_dict->members.count(key)) { checkSchemaInternal( this_dict->members[key].get(), iter.second.get(), - flags, errors, prefix + "." + key); - } - else - { - if (flags & f_optional) - { + flags, + errors, + prefix + "." + key); + } else { + if (flags & f_optional) { QTC::TC("libtests", "JSON optional key"); - } - else - { + } else { QTC::TC("libtests", "JSON key missing in object"); errors.push_back( err_prefix + ": key \"" + key + @@ -485,55 +441,49 @@ JSON::checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v, } } } - for (auto const& iter: this_dict->members) - { + for (auto const& iter : this_dict->members) { std::string const& key = iter.first; - if (sch_dict->members.count(key) == 0) - { + if (sch_dict->members.count(key) == 0) { QTC::TC("libtests", "JSON key extra in object"); errors.push_back( err_prefix + ": key \"" + key + "\" is not present in schema but appears in object"); } } - } - else if (sch_arr) - { - if (! this_arr) - { + } else if (sch_arr) { + if (!this_arr) { QTC::TC("libtests", "JSON wanted array"); errors.push_back(err_prefix + " is supposed to be an array"); return false; } - if (sch_arr->elements.size() != 1) - { + if (sch_arr->elements.size() != 1) { QTC::TC("libtests", "JSON schema array error"); - errors.push_back(err_prefix + - " schema array contains other than one item"); + errors.push_back( + err_prefix + " schema array contains other than one item"); return false; } int i = 0; - for (auto const& element: this_arr->elements) - { + for (auto const& element : this_arr->elements) { checkSchemaInternal( element.get(), sch_arr->elements.at(0).get(), - flags, errors, prefix + "." + QUtil::int_to_string(i)); + flags, + errors, + prefix + "." + QUtil::int_to_string(i)); ++i; } - } - else if (! sch_str) - { + } else if (!sch_str) { QTC::TC("libtests", "JSON schema other type"); - errors.push_back(err_prefix + - " schema value is not dictionary, array, or string"); + errors.push_back( + err_prefix + " schema value is not dictionary, array, or string"); return false; } return errors.empty(); } -namespace { +namespace +{ class JSONParser { public: @@ -597,7 +547,7 @@ namespace { std::vector<parser_state_e> ps_stack; std::string dict_key; }; -} +} // namespace std::string JSONParser::decode_string(std::string const& str) @@ -606,8 +556,7 @@ JSONParser::decode_string(std::string const& str) // is called, so errors are logic errors instead of runtime // errors. size_t len = str.length(); - if ((len < 2) || (str.at(0) != '"') || (str.at(len-1) != '"')) - { + if ((len < 2) || (str.at(0) != '"') || (str.at(len - 1) != '"')) { throw std::logic_error( "JSON Parse: decode_string called with other than \"...\""); } @@ -616,48 +565,43 @@ JSONParser::decode_string(std::string const& str) ++s; len -= 2; std::string result; - for (size_t i = 0; i < len; ++i) - { - if (s[i] == '\\') - { - if (i + 1 >= len) - { + for (size_t i = 0; i < len; ++i) { + if (s[i] == '\\') { + if (i + 1 >= len) { throw std::logic_error("JSON parse: nothing after \\"); } char ch = s[++i]; - switch (ch) - { - case '\\': - case '\"': - case '/': + switch (ch) { + case '\\': + case '\"': + case '/': // \/ is allowed in json input, but so is /, so we // don't map / to \/ in output. result.append(1, ch); break; - case 'b': + case 'b': result.append(1, '\b'); break; - case 'f': + case 'f': result.append(1, '\f'); break; - case 'n': + case 'n': result.append(1, '\n'); break; - case 'r': + case 'r': result.append(1, '\r'); break; - case 't': + case 't': result.append(1, '\t'); break; - case 'u': - if (i + 4 >= len) - { + case 'u': + if (i + 4 >= len) { throw std::logic_error( "JSON parse: not enough characters after \\u"); } { std::string hex = - QUtil::hex_decode(std::string(s+i+1, s+i+5)); + QUtil::hex_decode(std::string(s + i + 1, s + i + 5)); i += 4; unsigned char high = static_cast<unsigned char>(hex.at(0)); unsigned char low = static_cast<unsigned char>(hex.at(1)); @@ -667,52 +611,40 @@ JSONParser::decode_string(std::string const& str) result += QUtil::toUTF8(codepoint); } break; - default: - throw std::logic_error( - "JSON parse: bad character after \\"); + default: + throw std::logic_error("JSON parse: bad character after \\"); break; } - } - else - { + } else { result.append(1, s[i]); } } return result; } -void JSONParser::getToken() +void +JSONParser::getToken() { - while (p < end) - { - if (*p == 0) - { + while (p < end) { + if (*p == 0) { QTC::TC("libtests", "JSON parse null character"); throw std::runtime_error( "JSON: null character at offset " + QUtil::int_to_string(p - cstr)); } - switch (lex_state) - { - case ls_top: - if (*p == '"') - { + switch (lex_state) { + case ls_top: + if (*p == '"') { tok_start = p; tok_end = nullptr; lex_state = ls_string; - } - else if (QUtil::is_space(*p)) - { + } else if (QUtil::is_space(*p)) { // ignore - } - else if ((*p >= 'a') && (*p <= 'z')) - { + } else if ((*p >= 'a') && (*p <= 'z')) { tok_start = p; tok_end = nullptr; lex_state = ls_alpha; - } - else if (*p == '-') - { + } else if (*p == '-') { tok_start = p; tok_end = nullptr; lex_state = ls_number; @@ -721,9 +653,7 @@ void JSONParser::getToken() number_after_e = 0; number_saw_point = false; number_saw_e = false; - } - else if ((*p >= '0') && (*p <= '9')) - { + } else if ((*p >= '0') && (*p <= '9')) { tok_start = p; tok_end = nullptr; lex_state = ls_number; @@ -732,9 +662,7 @@ void JSONParser::getToken() number_after_e = 0; number_saw_point = false; number_saw_e = false; - } - else if (*p == '.') - { + } else if (*p == '.') { tok_start = p; tok_end = nullptr; lex_state = ls_number; @@ -743,14 +671,10 @@ void JSONParser::getToken() number_after_e = 0; number_saw_point = true; number_saw_e = false; - } - else if (strchr("{}[]:,", *p)) - { + } else if (strchr("{}[]:,", *p)) { tok_start = p; tok_end = p + 1; - } - else - { + } else { QTC::TC("libtests", "JSON parse bad character"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -758,82 +682,53 @@ void JSONParser::getToken() } break; - case ls_number: - if ((*p >= '0') && (*p <= '9')) - { - if (number_saw_e) - { + case ls_number: + if ((*p >= '0') && (*p <= '9')) { + if (number_saw_e) { ++number_after_e; - } - else if (number_saw_point) - { + } else if (number_saw_point) { ++number_after_point; - } - else - { + } else { ++number_before_point; } - } - else if (*p == '.') - { - if (number_saw_e) - { + } else if (*p == '.') { + if (number_saw_e) { QTC::TC("libtests", "JSON parse point after e"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": numeric literal: decimal point after e"); - } - else if (number_saw_point) - { + } else if (number_saw_point) { QTC::TC("libtests", "JSON parse duplicate point"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": numeric literal: decimal point already seen"); - } - else - { + } else { number_saw_point = true; } - } - else if (*p == 'e') - { - if (number_saw_e) - { + } else if (*p == 'e') { + if (number_saw_e) { QTC::TC("libtests", "JSON parse duplicate e"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": numeric literal: e already seen"); - } - else - { + } else { number_saw_e = true; } - } - else if ((*p == '+') || (*p == '-')) - { - if (number_saw_e && (number_after_e == 0)) - { + } else if ((*p == '+') || (*p == '-')) { + if (number_saw_e && (number_after_e == 0)) { // okay - } - else - { + } else { QTC::TC("libtests", "JSON parse unexpected sign"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": numeric literal: unexpected sign"); } - } - else if (QUtil::is_space(*p)) - { + } else if (QUtil::is_space(*p)) { tok_end = p; - } - else if (strchr("{}[]:,", *p)) - { + } else if (strchr("{}[]:,", *p)) { tok_end = p; --p; - } - else - { + } else { QTC::TC("libtests", "JSON parse numeric bad character"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -842,22 +737,15 @@ void JSONParser::getToken() } break; - case ls_alpha: - if ((*p >= 'a') && (*p <= 'z')) - { + case ls_alpha: + if ((*p >= 'a') && (*p <= 'z')) { // okay - } - else if (QUtil::is_space(*p)) - { + } else if (QUtil::is_space(*p)) { tok_end = p; - } - else if (strchr("{}[]:,", *p)) - { + } else if (strchr("{}[]:,", *p)) { tok_end = p; --p; - } - else - { + } else { QTC::TC("libtests", "JSON parse keyword bad character"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -865,36 +753,27 @@ void JSONParser::getToken() } break; - case ls_string: - if (*p == '"') - { + case ls_string: + if (*p == '"') { tok_end = p + 1; - } - else if (*p == '\\') - { + } else if (*p == '\\') { lex_state = ls_backslash; } break; - case ls_backslash: + case ls_backslash: /* cSpell: ignore bfnrt */ - if (strchr("\\\"/bfnrt", *p)) - { + if (strchr("\\\"/bfnrt", *p)) { lex_state = ls_string; - } - else if (*p == 'u') - { - if (p + 4 >= end) - { + } else if (*p == 'u') { + if (p + 4 >= end) { QTC::TC("libtests", "JSON parse premature end of u"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": \\u must be followed by four characters"); } - for (size_t i = 1; i <= 4; ++i) - { - if (! QUtil::is_hex_digit(p[i])) - { + for (size_t i = 1; i <= 4; ++i) { + if (!QUtil::is_hex_digit(p[i])) { QTC::TC("libtests", "JSON parse bad hex after u"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -903,9 +782,7 @@ void JSONParser::getToken() } p += 4; lex_state = ls_string; - } - else - { + } else { QTC::TC("libtests", "JSON parse backslash bad character"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -915,31 +792,27 @@ void JSONParser::getToken() break; } ++p; - if (tok_start && tok_end) - { + if (tok_start && tok_end) { break; } } - if (p == end) - { - if (tok_start && (! tok_end)) - { - switch (lex_state) - { - case ls_top: + if (p == end) { + if (tok_start && (!tok_end)) { + switch (lex_state) { + case ls_top: // Can't happen throw std::logic_error( "tok_start set in ls_top while parsing " + std::string(cstr)); break; - case ls_number: - case ls_alpha: + case ls_number: + case ls_alpha: tok_end = p; break; - case ls_string: - case ls_backslash: + case ls_string: + case ls_backslash: QTC::TC("libtests", "JSON parse unterminated string"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -953,16 +826,14 @@ void JSONParser::getToken() void JSONParser::handleToken() { - if (! (tok_start && tok_end)) - { + if (!(tok_start && tok_end)) { return; } // Get token value. std::string value(tok_start, tok_end); - if (parser_state == ps_done) - { + if (parser_state == ps_done) { QTC::TC("libtests", "JSON parse junk after object"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -971,11 +842,9 @@ JSONParser::handleToken() // Git string value std::string s_value; - if (lex_state == ls_string) - { + if (lex_state == ls_string) { // Token includes the quotation marks - if (tok_end - tok_start < 2) - { + if (tok_end - tok_start < 2) { throw std::logic_error("JSON string length < 2"); } s_value = decode_string(value); @@ -986,28 +855,25 @@ JSONParser::handleToken() std::shared_ptr<JSON> item; char delimiter = '\0'; - switch (lex_state) - { - case ls_top: - switch (*tok_start) - { - case '{': + switch (lex_state) { + case ls_top: + switch (*tok_start) { + case '{': item = std::make_shared<JSON>(JSON::makeDictionary()); break; - case '[': + case '[': item = std::make_shared<JSON>(JSON::makeArray()); break; - default: + default: delimiter = *tok_start; break; } break; - case ls_number: - if (number_saw_point && (number_after_point == 0)) - { + case ls_number: + if (number_saw_point && (number_after_point == 0)) { QTC::TC("libtests", "JSON parse decimal with no digits"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -1015,15 +881,13 @@ JSONParser::handleToken() } if ((number_before_point > 1) && ((tok_start[0] == '0') || - ((tok_start[0] == '-') && (tok_start[1] == '0')))) - { + ((tok_start[0] == '-') && (tok_start[1] == '0')))) { QTC::TC("libtests", "JSON parse leading zero"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": number with leading zero"); } - if ((number_before_point == 0) && (number_after_point == 0)) - { + if ((number_before_point == 0) && (number_after_point == 0)) { QTC::TC("libtests", "JSON parse number no digits"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -1032,21 +896,14 @@ JSONParser::handleToken() item = std::make_shared<JSON>(JSON::makeNumber(value)); break; - case ls_alpha: - if (value == "true") - { + case ls_alpha: + if (value == "true") { item = std::make_shared<JSON>(JSON::makeBool(true)); - } - else if (value == "false") - { + } else if (value == "false") { item = std::make_shared<JSON>(JSON::makeBool(false)); - } - else if (value == "null") - { + } else if (value == "null") { item = std::make_shared<JSON>(JSON::makeNull()); - } - else - { + } else { QTC::TC("libtests", "JSON parse invalid keyword"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -1054,18 +911,16 @@ JSONParser::handleToken() } break; - case ls_string: + case ls_string: item = std::make_shared<JSON>(JSON::makeString(s_value)); break; - case ls_backslash: - throw std::logic_error( - "tok_end is set while state = ls_backslash"); + case ls_backslash: + throw std::logic_error("tok_end is set while state = ls_backslash"); break; } - if ((item.get() == nullptr) == (delimiter == '\0')) - { + if ((item.get() == nullptr) == (delimiter == '\0')) { throw std::logic_error( "JSONParser::handleToken: logic error: exactly one of item" " or delimiter must be set"); @@ -1073,39 +928,36 @@ JSONParser::handleToken() // See whether what we have is allowed at this point. - if (item.get()) - { - switch (parser_state) - { - case ps_done: + if (item.get()) { + switch (parser_state) { + case ps_done: throw std::logic_error("can't happen; ps_done already handled"); break; - case ps_dict_after_key: + case ps_dict_after_key: QTC::TC("libtests", "JSON parse expected colon"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": expected ':'"); break; - case ps_dict_after_item: + case ps_dict_after_item: QTC::TC("libtests", "JSON parse expected , or }"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": expected ',' or '}'"); break; - case ps_array_after_item: + case ps_array_after_item: QTC::TC("libtests", "JSON parse expected, or ]"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": expected ',' or ']'"); break; - case ps_dict_begin: - case ps_dict_after_comma: - if (lex_state != ls_string) - { + case ps_dict_begin: + case ps_dict_after_comma: + if (lex_state != ls_string) { QTC::TC("libtests", "JSON parse string as dict key"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + @@ -1113,18 +965,16 @@ JSONParser::handleToken() } break; - case ps_top: - case ps_dict_after_colon: - case ps_array_begin: - case ps_array_after_comma: + case ps_top: + case ps_dict_after_colon: + case ps_array_begin: + case ps_array_after_comma: break; // okay } - } - else if (delimiter == '}') - { - if (! ((parser_state == ps_dict_begin) || - (parser_state == ps_dict_after_item))) + } else if (delimiter == '}') { + if (!((parser_state == ps_dict_begin) || + (parser_state == ps_dict_after_item))) { QTC::TC("libtests", "JSON parse unexpected }"); @@ -1132,11 +982,9 @@ JSONParser::handleToken() "JSON: offset " + QUtil::int_to_string(p - cstr) + ": unexpected dictionary end delimiter"); } - } - else if (delimiter == ']') - { - if (! ((parser_state == ps_array_begin) || - (parser_state == ps_array_after_item))) + } else if (delimiter == ']') { + if (!((parser_state == ps_array_begin) || + (parser_state == ps_array_after_item))) { QTC::TC("libtests", "JSON parse unexpected ]"); @@ -1144,30 +992,22 @@ JSONParser::handleToken() "JSON: offset " + QUtil::int_to_string(p - cstr) + ": unexpected array end delimiter"); } - } - else if (delimiter == ':') - { - if (parser_state != ps_dict_after_key) - { + } else if (delimiter == ':') { + if (parser_state != ps_dict_after_key) { QTC::TC("libtests", "JSON parse unexpected :"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": unexpected colon"); } - } - else if (delimiter == ',') - { - if (! ((parser_state == ps_dict_after_item) || - (parser_state == ps_array_after_item))) - { + } else if (delimiter == ',') { + if (!((parser_state == ps_dict_after_item) || + (parser_state == ps_array_after_item))) { QTC::TC("libtests", "JSON parse unexpected ,"); throw std::runtime_error( "JSON: offset " + QUtil::int_to_string(p - cstr) + ": unexpected comma"); } - } - else if (delimiter != '\0') - { + } else if (delimiter != '\0') { throw std::logic_error("JSONParser::handleToken: bad delimiter"); } @@ -1175,103 +1015,77 @@ JSONParser::handleToken() // whatever we need to do with it. parser_state_e next_state = ps_top; - if (delimiter == ':') - { + if (delimiter == ':') { next_state = ps_dict_after_colon; - } - else if (delimiter == ',') - { - if (parser_state == ps_dict_after_item) - { + } else if (delimiter == ',') { + if (parser_state == ps_dict_after_item) { next_state = ps_dict_after_comma; - } - else if (parser_state == ps_array_after_item) - { + } else if (parser_state == ps_array_after_item) { next_state = ps_array_after_comma; + } else { + throw std::logic_error("JSONParser::handleToken: unexpected parser" + " state for comma"); } - else - { - throw std::logic_error( - "JSONParser::handleToken: unexpected parser" - " state for comma"); - } - } - else if ((delimiter == '}') || (delimiter == ']')) - { + } else if ((delimiter == '}') || (delimiter == ']')) { next_state = ps_stack.back(); ps_stack.pop_back(); - if (next_state != ps_done) - { + if (next_state != ps_done) { stack.pop_back(); } - } - else if (delimiter != '\0') - { + } else if (delimiter != '\0') { throw std::logic_error( "JSONParser::handleToken: unexpected delimiter in transition"); - } - else if (item.get()) - { + } else if (item.get()) { std::shared_ptr<JSON> tos; - if (! stack.empty()) - { + if (!stack.empty()) { tos = stack.back(); } - switch (parser_state) - { - case ps_dict_begin: - case ps_dict_after_comma: + switch (parser_state) { + case ps_dict_begin: + case ps_dict_after_comma: this->dict_key = s_value; item = nullptr; next_state = ps_dict_after_key; break; - case ps_dict_after_colon: + case ps_dict_after_colon: tos->addDictionaryMember(dict_key, *item); next_state = ps_dict_after_item; break; - case ps_array_begin: - case ps_array_after_comma: + case ps_array_begin: + case ps_array_after_comma: next_state = ps_array_after_item; tos->addArrayElement(*item); break; - case ps_top: + case ps_top: next_state = ps_done; break; - case ps_dict_after_key: - case ps_dict_after_item: - case ps_array_after_item: - case ps_done: + case ps_dict_after_key: + case ps_dict_after_item: + case ps_array_after_item: + case ps_done: throw std::logic_error( "JSONParser::handleToken: unexpected parser state"); } - } - else - { + } else { throw std::logic_error( "JSONParser::handleToken: unexpected null item in transition"); } // Prepare for next token - if (item.get()) - { - if (item->isDictionary()) - { + if (item.get()) { + if (item->isDictionary()) { stack.push_back(item); ps_stack.push_back(next_state); next_state = ps_dict_begin; - } - else if (item->isArray()) - { + } else if (item->isArray()) { stack.push_back(item); ps_stack.push_back(next_state); next_state = ps_array_begin; - } - else if (parser_state == ps_top) - { + } else if (parser_state == ps_top) { stack.push_back(item); } } @@ -1288,13 +1102,11 @@ JSONParser::parse(std::string const& s) end = cstr + s.length(); p = cstr; - while (p < end) - { + while (p < end) { getToken(); handleToken(); } - if (parser_state != ps_done) - { + if (parser_state != ps_done) { QTC::TC("libtests", "JSON parse premature EOF"); throw std::runtime_error("JSON: premature end of input"); } |