ParserImpl.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. //
  2. // Parser.cpp
  3. //
  4. // Library: JSON
  5. // Package: JSON
  6. // Module: Parser
  7. //
  8. // Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
  9. // and Contributors.
  10. //
  11. // SPDX-License-Identifier: BSL-1.0
  12. //
  13. #include "Poco/JSON/Parser.h"
  14. #include "Poco/JSON/JSONException.h"
  15. #include "Poco/Ascii.h"
  16. #include "Poco/Token.h"
  17. #include "Poco/UTF8Encoding.h"
  18. #include "Poco/String.h"
  19. #include "Poco/StreamCopier.h"
  20. #undef min
  21. #undef max
  22. #include <limits>
  23. #include <clocale>
  24. #include <istream>
  25. #include "pdjson.h"
  26. typedef struct json_stream json_stream;
  27. namespace Poco {
  28. namespace JSON {
  29. ParserImpl::ParserImpl(const Handler::Ptr& pHandler, std::size_t bufSize):
  30. _pJSON(new json_stream),
  31. _pHandler(pHandler),
  32. _depth(JSON_UNLIMITED_DEPTH),
  33. _decimalPoint('.'),
  34. _allowNullByte(true),
  35. _allowComments(false)
  36. {
  37. }
  38. ParserImpl::~ParserImpl()
  39. {
  40. delete _pJSON;
  41. }
  42. void ParserImpl::handle(const std::string& json)
  43. {
  44. if (!_allowNullByte && json.find("\\u0000") != json.npos)
  45. throw JSONException("Null bytes in strings not allowed.");
  46. try
  47. {
  48. json_open_buffer(_pJSON, json.data(), json.size());
  49. checkError();
  50. //////////////////////////////////
  51. // Underlying parser is capable of parsing multiple consecutive JSONs;
  52. // we do not currently support this feature; to force error on
  53. // excessive characters past valid JSON end, this MUST be called
  54. // AFTER opening the buffer - otherwise it is overwritten by
  55. // json_open*() call, which calls internal init()
  56. json_set_streaming(_pJSON, false);
  57. /////////////////////////////////
  58. handle(); checkError();
  59. if (JSON_DONE != json_next(_pJSON))
  60. throw JSONException("Excess characters found after JSON end.");
  61. json_close(_pJSON);
  62. }
  63. catch (std::exception&)
  64. {
  65. json_close(_pJSON);
  66. throw;
  67. }
  68. }
  69. Dynamic::Var ParserImpl::parseImpl(const std::string& json)
  70. {
  71. if (_allowComments)
  72. {
  73. std::string str = json;
  74. stripComments(str);
  75. handle(str);
  76. }
  77. else handle(json);
  78. return asVarImpl();
  79. }
  80. Dynamic::Var ParserImpl::parseImpl(std::istream& in)
  81. {
  82. std::ostringstream os;
  83. StreamCopier::copyStream(in, os);
  84. return parseImpl(os.str());
  85. }
  86. void ParserImpl::stripComments(std::string& json)
  87. {
  88. if (_allowComments)
  89. {
  90. bool inString = false;
  91. bool inComment = false;
  92. char prevChar = 0;
  93. std::string::iterator it = json.begin();
  94. for (; it != json.end();)
  95. {
  96. if (*it == '"' && !inString) inString = true;
  97. else inString = false;
  98. if (!inString)
  99. {
  100. if (*it == '/' && it + 1 != json.end() && *(it + 1) == '*')
  101. inComment = true;
  102. }
  103. if (inComment)
  104. {
  105. char c = *it;
  106. it = json.erase(it);
  107. if (prevChar == '*' && c == '/')
  108. {
  109. inComment = false;
  110. prevChar = 0;
  111. }
  112. else prevChar = c;
  113. }
  114. else ++it;
  115. }
  116. }
  117. }
  118. void ParserImpl::handleArray()
  119. {
  120. json_type tok = json_peek(_pJSON);
  121. while (tok != JSON_ARRAY_END && checkError())
  122. {
  123. handle();
  124. tok = json_peek(_pJSON);
  125. }
  126. if (tok == JSON_ARRAY_END) handle();
  127. else throw JSONException("JSON array end not found");
  128. }
  129. void ParserImpl::handleObject()
  130. {
  131. json_type tok = json_peek(_pJSON);
  132. while (tok != JSON_OBJECT_END && checkError())
  133. {
  134. json_next(_pJSON);
  135. if (_pHandler) _pHandler->key(std::string(json_get_string(_pJSON, NULL)));
  136. handle();
  137. tok = json_peek(_pJSON);
  138. }
  139. if (tok == JSON_OBJECT_END) handle();
  140. else throw JSONException("JSON object end not found");
  141. }
  142. void ParserImpl::handle()
  143. {
  144. enum json_type type = json_next(_pJSON);
  145. switch (type)
  146. {
  147. case JSON_DONE:
  148. return;
  149. case JSON_NULL:
  150. _pHandler->null();
  151. break;
  152. case JSON_TRUE:
  153. if (_pHandler) _pHandler->value(true);
  154. break;
  155. case JSON_FALSE:
  156. if (_pHandler) _pHandler->value(false);
  157. break;
  158. case JSON_NUMBER:
  159. {
  160. if (_pHandler)
  161. {
  162. std::string str(json_get_string(_pJSON, NULL));
  163. if (str.find(_decimalPoint) != str.npos || str.find('e') != str.npos || str.find('E') != str.npos)
  164. {
  165. _pHandler->value(NumberParser::parseFloat(str));
  166. }
  167. else
  168. {
  169. Poco::Int64 val;
  170. if (NumberParser::tryParse64(str, val))
  171. _pHandler->value(val);
  172. else
  173. _pHandler->value(NumberParser::parseUnsigned64(str));
  174. }
  175. }
  176. break;
  177. }
  178. case JSON_STRING:
  179. if (_pHandler) _pHandler->value(std::string(json_get_string(_pJSON, NULL)));
  180. break;
  181. case JSON_OBJECT:
  182. if (_pHandler) _pHandler->startObject();
  183. handleObject();
  184. break;
  185. case JSON_OBJECT_END:
  186. if (_pHandler) _pHandler->endObject();
  187. return;
  188. case JSON_ARRAY:
  189. if (_pHandler) _pHandler->startArray();
  190. handleArray();
  191. break;
  192. case JSON_ARRAY_END:
  193. if (_pHandler) _pHandler->endArray();
  194. return;
  195. case JSON_ERROR:
  196. {
  197. const char* pErr = json_get_error(_pJSON);
  198. std::string err(pErr ? pErr : "JSON parser error.");
  199. throw JSONException(err);
  200. }
  201. }
  202. }
  203. bool ParserImpl::checkError()
  204. {
  205. const char* err = json_get_error(_pJSON);
  206. if (err) throw Poco::JSON::JSONException(err);
  207. return true;
  208. }
  209. } } // namespace Poco::JSON