aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/JSON/src/ParserImpl.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/poco/JSON/src/ParserImpl.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/poco/JSON/src/ParserImpl.cpp')
-rw-r--r--contrib/libs/poco/JSON/src/ParserImpl.cpp241
1 files changed, 241 insertions, 0 deletions
diff --git a/contrib/libs/poco/JSON/src/ParserImpl.cpp b/contrib/libs/poco/JSON/src/ParserImpl.cpp
new file mode 100644
index 0000000000..ce455ea031
--- /dev/null
+++ b/contrib/libs/poco/JSON/src/ParserImpl.cpp
@@ -0,0 +1,241 @@
+//
+// Parser.cpp
+//
+// Library: JSON
+// Package: JSON
+// Module: Parser
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/JSON/Parser.h"
+#include "Poco/JSON/JSONException.h"
+#include "Poco/Ascii.h"
+#include "Poco/Token.h"
+#include "Poco/UTF8Encoding.h"
+#include "Poco/String.h"
+#include "Poco/StreamCopier.h"
+#undef min
+#undef max
+#include <limits>
+#include <clocale>
+#include <istream>
+#include "pdjson.h"
+
+
+typedef struct json_stream json_stream;
+
+
+namespace Poco {
+namespace JSON {
+
+
+ParserImpl::ParserImpl(const Handler::Ptr& pHandler, std::size_t /*bufSize*/):
+ _pJSON(new json_stream),
+ _pHandler(pHandler),
+ _depth(JSON_UNLIMITED_DEPTH),
+ _decimalPoint('.'),
+ _allowNullByte(true),
+ _allowComments(false)
+{
+}
+
+
+ParserImpl::~ParserImpl()
+{
+ delete _pJSON;
+}
+
+
+void ParserImpl::handle(const std::string& json)
+{
+ if (!_allowNullByte && json.find("\\u0000") != json.npos)
+ throw JSONException("Null bytes in strings not allowed.");
+
+ try
+ {
+ json_open_buffer(_pJSON, json.data(), json.size());
+ checkError();
+ //////////////////////////////////
+ // Underlying parser is capable of parsing multiple consecutive JSONs;
+ // we do not currently support this feature; to force error on
+ // excessive characters past valid JSON end, this MUST be called
+ // AFTER opening the buffer - otherwise it is overwritten by
+ // json_open*() call, which calls internal init()
+ json_set_streaming(_pJSON, false);
+ /////////////////////////////////
+ handle(); checkError();
+ if (JSON_DONE != json_next(_pJSON))
+ throw JSONException("Excess characters found after JSON end.");
+ json_close(_pJSON);
+ }
+ catch (std::exception&)
+ {
+ json_close(_pJSON);
+ throw;
+ }
+}
+
+
+Dynamic::Var ParserImpl::parseImpl(const std::string& json)
+{
+ if (_allowComments)
+ {
+ std::string str = json;
+ stripComments(str);
+ handle(str);
+ }
+ else handle(json);
+
+ return asVarImpl();
+}
+
+
+Dynamic::Var ParserImpl::parseImpl(std::istream& in)
+{
+ std::ostringstream os;
+ StreamCopier::copyStream(in, os);
+ return parseImpl(os.str());
+}
+
+
+void ParserImpl::stripComments(std::string& json)
+{
+ if (_allowComments)
+ {
+ bool inString = false;
+ bool inComment = false;
+ char prevChar = 0;
+ std::string::iterator it = json.begin();
+ for (; it != json.end();)
+ {
+ if (*it == '"' && !inString) inString = true;
+ else inString = false;
+ if (!inString)
+ {
+ if (*it == '/' && it + 1 != json.end() && *(it + 1) == '*')
+ inComment = true;
+ }
+ if (inComment)
+ {
+ char c = *it;
+ it = json.erase(it);
+ if (prevChar == '*' && c == '/')
+ {
+ inComment = false;
+ prevChar = 0;
+ }
+ else prevChar = c;
+ }
+ else ++it;
+ }
+ }
+}
+
+
+void ParserImpl::handleArray()
+{
+ json_type tok = json_peek(_pJSON);
+ while (tok != JSON_ARRAY_END && checkError())
+ {
+ handle();
+ tok = json_peek(_pJSON);
+ }
+
+ if (tok == JSON_ARRAY_END) handle();
+ else throw JSONException("JSON array end not found");
+}
+
+
+void ParserImpl::handleObject()
+{
+ json_type tok = json_peek(_pJSON);
+ while (tok != JSON_OBJECT_END && checkError())
+ {
+ json_next(_pJSON);
+ if (_pHandler) _pHandler->key(std::string(json_get_string(_pJSON, NULL)));
+ handle();
+ tok = json_peek(_pJSON);
+ }
+
+ if (tok == JSON_OBJECT_END) handle();
+ else throw JSONException("JSON object end not found");
+}
+
+
+void ParserImpl::handle()
+{
+ enum json_type type = json_next(_pJSON);
+ switch (type)
+ {
+ case JSON_DONE:
+ return;
+ case JSON_NULL:
+ _pHandler->null();
+ break;
+ case JSON_TRUE:
+ if (_pHandler) _pHandler->value(true);
+ break;
+ case JSON_FALSE:
+ if (_pHandler) _pHandler->value(false);
+ break;
+ case JSON_NUMBER:
+ {
+ if (_pHandler)
+ {
+ std::string str(json_get_string(_pJSON, NULL));
+ if (str.find(_decimalPoint) != str.npos || str.find('e') != str.npos || str.find('E') != str.npos)
+ {
+ _pHandler->value(NumberParser::parseFloat(str));
+ }
+ else
+ {
+ Poco::Int64 val;
+ if (NumberParser::tryParse64(str, val))
+ _pHandler->value(val);
+ else
+ _pHandler->value(NumberParser::parseUnsigned64(str));
+ }
+ }
+ break;
+ }
+ case JSON_STRING:
+ if (_pHandler) _pHandler->value(std::string(json_get_string(_pJSON, NULL)));
+ break;
+ case JSON_OBJECT:
+ if (_pHandler) _pHandler->startObject();
+ handleObject();
+ break;
+ case JSON_OBJECT_END:
+ if (_pHandler) _pHandler->endObject();
+ return;
+ case JSON_ARRAY:
+ if (_pHandler) _pHandler->startArray();
+ handleArray();
+ break;
+ case JSON_ARRAY_END:
+ if (_pHandler) _pHandler->endArray();
+ return;
+ case JSON_ERROR:
+ {
+ const char* pErr = json_get_error(_pJSON);
+ std::string err(pErr ? pErr : "JSON parser error.");
+ throw JSONException(err);
+ }
+ }
+}
+
+
+bool ParserImpl::checkError()
+{
+ const char* err = json_get_error(_pJSON);
+ if (err) throw Poco::JSON::JSONException(err);
+ return true;
+}
+
+
+} } // namespace Poco::JSON