streamConsumer.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /**
  2. * streamConsumer.cpp for jsonstroller
  3. *
  4. * Author: isundil <isundill@gmail.com>
  5. **/
  6. #include <iostream>
  7. #include <sstream>
  8. #include <codecvt>
  9. #include <locale>
  10. #include "jsonElement.hh"
  11. #include "streamConsumer.hh"
  12. #include "unicode.hpp"
  13. StreamConsumer::StreamConsumer(std::istream &s): stream(s), root(nullptr)
  14. { }
  15. StreamConsumer::~StreamConsumer()
  16. {
  17. if (root)
  18. delete root;
  19. }
  20. StreamConsumer *StreamConsumer::withConfig(const AParams *p)
  21. {
  22. params = p;
  23. return this;
  24. }
  25. StreamConsumer *StreamConsumer::read()
  26. {
  27. if (root)
  28. return this;
  29. root = readNext(nullptr);
  30. return this;
  31. }
  32. JSonElement *StreamConsumer::readNext(JSonContainer *parent)
  33. {
  34. std::stringstream sbuf;
  35. JSonElement *root = consumeToken(parent, sbuf);
  36. const std::string buf = sbuf.str();
  37. if (root == nullptr)
  38. {
  39. if (buf == "{")
  40. {
  41. return readObject(parent);
  42. }
  43. else if (buf == "[")
  44. {
  45. return readArray(parent);
  46. }
  47. else
  48. return nullptr;
  49. }
  50. return root;
  51. }
  52. const JSonElement * StreamConsumer::getRoot() const
  53. { return root; }
  54. JSonElement * StreamConsumer::getRoot()
  55. { return root; }
  56. JSonObject *StreamConsumer::readObject(JSonContainer *parent)
  57. {
  58. JSonElement *keyObj;
  59. JSonObject *result = nullptr;
  60. std::stringstream buf;
  61. do
  62. {
  63. keyObj = consumeToken(result, buf);
  64. if (result == nullptr && keyObj == nullptr && buf.str() == "}")
  65. return new JSonObject(parent);
  66. JSonPrimitive<std::string> *key = dynamic_cast<JSonPrimitive<std::string> *>(keyObj);
  67. if (key == nullptr)
  68. throw JSonObject::NotAKeyException(stream.tellg(), history);
  69. if (consumeToken(parent, buf) != nullptr || buf.str() != ":")
  70. throw JsonUnexpectedException(':', stream.tellg(), history);
  71. if (result == nullptr)
  72. result = (!params || params->sortObjects()) ? new JSonSortedObject(parent) : new JSonObject(parent);
  73. else if (result->contains(key->getValue()))
  74. {
  75. if (!params || params->isStrict())
  76. throw JSonObject::DoubleKeyException(stream.tellg(), key->getValue(), history);
  77. else // add Warning, new key erase previous one
  78. {
  79. result->erase(key->getValue());
  80. warnings.push_back(Warning(JSonObject::DoubleKeyException(stream.tellg(), key->getValue(), history)));
  81. }
  82. }
  83. JSonElement *child = readNext(result);
  84. result->push(key->getValue(), child);
  85. delete keyObj;
  86. keyObj = consumeToken(result, buf);
  87. } while (!keyObj && buf.str() != "}");
  88. return result;
  89. }
  90. JSonArray *StreamConsumer::readArray(JSonContainer *parent)
  91. {
  92. JSonArray *result = nullptr;
  93. std::stringstream sbuf;
  94. JSonElement *child = consumeToken(parent, sbuf);
  95. std::string buf = sbuf.str();
  96. if (child == nullptr && buf == "]")
  97. return new JSonArray(parent); //Empty object
  98. do
  99. {
  100. if (child == nullptr && buf == "[")
  101. child = readArray(nullptr);
  102. if (child == nullptr && buf == "{")
  103. child = readObject(nullptr);
  104. if (child == nullptr)
  105. throw JsonNotJsonException(stream.tellg(), history);
  106. if (result == nullptr)
  107. result = new JSonArray(parent);
  108. child->setParent(result);
  109. result->push_back(child);
  110. child = consumeToken(result, sbuf);
  111. buf = sbuf.str();
  112. if (child != nullptr)
  113. throw JsonUnexpectedException(']', stream.tellg(), history);
  114. else if (buf == "]")
  115. break;
  116. else if (buf != ",")
  117. throw JsonUnexpectedException(']', stream.tellg(), history);
  118. child = consumeToken(result, sbuf);
  119. buf = sbuf.str();
  120. } while (true);
  121. return result;
  122. }
  123. JSonElement *StreamConsumer::consumeString(JSonContainer *parent, std::stringstream &buf)
  124. {
  125. bool escaped = false;
  126. buf.str("");
  127. buf.clear();
  128. while (stream.good())
  129. {
  130. char c = stream.get();
  131. history.put(c);
  132. if (!escaped)
  133. {
  134. if (c == '"')
  135. return new JSonPrimitive<std::string>(parent, buf.str());
  136. else if (c == '\\')
  137. escaped = true;
  138. else
  139. buf.write(&c, 1);
  140. }
  141. else
  142. {
  143. if (consumeEscapedChar(c, buf))
  144. escaped = false;
  145. else
  146. break;
  147. }
  148. }
  149. buf.str("");
  150. buf.clear();
  151. return nullptr;
  152. }
  153. bool StreamConsumer::consumeEscapedChar(char c, std::stringstream &buf)
  154. {
  155. if (c == '\\' || c == '"' || c == '/')
  156. buf.write(&c, 1);
  157. else if (c == 'u')
  158. {
  159. if (params && params->isIgnoringUnicode())
  160. buf.write("\\u", 2);
  161. else
  162. {
  163. char unicodeBuf[4];
  164. stream.read(unicodeBuf, 4);
  165. std::streamsize gcount = stream.gcount();
  166. history.put(unicodeBuf, gcount);
  167. if (gcount != 4)
  168. return false;
  169. try {
  170. appendUnicode(unicodeBuf, buf);
  171. }
  172. catch (std::invalid_argument &e)
  173. {
  174. throw JsonHexvalueException(e.what(), stream.tellg(), history);
  175. }
  176. }
  177. }
  178. else if (c == 'b' || c == 'f' || c == 'r' || c == 'n' || c == 't')
  179. buf.write("\\", 1).write(&c, 1);
  180. else if (params && params->isStrict())
  181. throw JsonEscapedException(c, stream.tellg(), history);
  182. else
  183. {
  184. buf.write("\\", 1).write(&c, 1);
  185. warnings.push_back(Warning(JsonEscapedException(c, stream.tellg(), history)));
  186. }
  187. return true;
  188. }
  189. JSonElement *StreamConsumer::consumeBool(JSonContainer *parent, std::stringstream &buf, char firstChar)
  190. {
  191. size_t read =1;
  192. buf.str("");
  193. buf.clear();
  194. buf.write(&firstChar, 1);
  195. //TODO batch-get 3 char, then do that
  196. while (stream.good())
  197. {
  198. char c = stream.get();
  199. history.put(c);
  200. if (c == 'a' || c == 'e' || c == 'l' || c == 'r' || c == 's' || c == 'u')
  201. {
  202. if ((read >= 5 && firstChar == 'f') || (read >= 4 && firstChar == 't'))
  203. throw JsonFormatException(stream.tellg(), history);
  204. buf.write(&c, 1);
  205. read++;
  206. }
  207. else if (buf.str() == "true")
  208. {
  209. history.pop_back();
  210. stream.unget();
  211. return new JSonPrimitive<bool>(parent, true);
  212. }
  213. else if (buf.str() == "false")
  214. {
  215. history.pop_back();
  216. stream.unget();
  217. return new JSonPrimitive<bool>(parent, false);
  218. }
  219. else if (ignoreChar(c))
  220. ;
  221. else
  222. throw JsonFormatException(stream.tellg(), history);
  223. }
  224. buf.str("");
  225. buf.clear();
  226. return nullptr;
  227. }
  228. JSonElement *StreamConsumer::consumeNumber(JSonContainer *parent, std::stringstream &buf, char firstChar)
  229. {
  230. bool numberIsDouble = false;
  231. buf.str("");
  232. buf.clear();
  233. buf.write(&firstChar, 1);
  234. while (stream.good())
  235. {
  236. char c = stream.get();
  237. history.put(c);
  238. if (c >= '0' && c <= '9')
  239. buf.write(&c, 1);
  240. else if (c == '.' && !numberIsDouble)
  241. {
  242. numberIsDouble = true;
  243. buf.write(&c, 1);
  244. }
  245. else
  246. {
  247. history.pop_back();
  248. stream.unget();
  249. if (numberIsDouble)
  250. {
  251. try {
  252. return new JSonPrimitive<double>(parent, atof(buf.str().c_str()));
  253. } catch (std::runtime_error &e)
  254. {
  255. throw JsonFormatException(stream.tellg(), history);
  256. }
  257. }
  258. try
  259. {
  260. return new JSonPrimitive<int>(parent, std::stoi(buf.str()));
  261. }
  262. catch(std::out_of_range e)
  263. {
  264. return new JSonPrimitive<long long>(parent, std::stol(buf.str()));
  265. }
  266. }
  267. }
  268. buf.str("");
  269. buf.clear();
  270. return nullptr;
  271. }
  272. JSonElement *StreamConsumer::consumeNull(JSonContainer *parent, std::stringstream &buf)
  273. {
  274. char _buf[5] = { 'n', '\0', '\0', '\0', '\0' };
  275. buf.str("");
  276. buf.clear();
  277. stream.read(&_buf[1], 3);
  278. buf.write(_buf, 4);
  279. history.put(&_buf[1], 3);
  280. if (!stream.good())
  281. {
  282. buf.str("");
  283. buf.clear();
  284. return nullptr;
  285. }
  286. if (std::string("null") == _buf)
  287. return new JSonPrimitive<Null>(parent, Null());
  288. throw JsonFormatException(stream.tellg(), history);
  289. }
  290. JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::stringstream &buf)
  291. {
  292. while (stream.good())
  293. {
  294. char c = stream.get();
  295. history.put(c);
  296. //!InString, !inbool
  297. if (c == '"')
  298. return consumeString(parent, buf);
  299. else if (c == 't' || c == 'f')
  300. return consumeBool(parent, buf, c);
  301. else if (c == 'n')
  302. return consumeNull(parent, buf);
  303. else if ((c >= '0' && c <= '9') || c == '.' || c == '-')
  304. return consumeNumber(parent, buf, c);
  305. else if (c == '{' || c == '[' || c == '}' || c == ']' || c == ':' || c == ',')
  306. {
  307. buf.str("");
  308. buf.clear();
  309. buf.write(&c, 1);
  310. return nullptr;
  311. }
  312. else if (!ignoreChar(c))
  313. throw JsonFormatException(stream.tellg(), history);
  314. }
  315. buf.str("");
  316. buf.clear();
  317. return nullptr;
  318. }
  319. void StreamConsumer::appendUnicode(const char unicode[4], std::stringstream &buf)
  320. {
  321. unsigned short uni = hexbyte<unsigned short>(unicode, 4);
  322. std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
  323. std::string unichar = converter.to_bytes(uni);
  324. buf.write(unichar.c_str(), unichar.size());
  325. }
  326. std::string StreamConsumer::extractUnicode(const char *buf)
  327. {
  328. std::stringstream result;
  329. for (; *buf; buf++)
  330. {
  331. if (*buf == '\\' && buf[1] == 'u' && buf[2] && buf[3] && buf[4] && buf[5])
  332. {
  333. appendUnicode(buf +2, result);
  334. buf += 6;
  335. }
  336. else
  337. result.write(buf, 1);
  338. }
  339. return result.str();
  340. }
  341. std::string StreamConsumer::extractUnicode(const std::string &buf)
  342. {
  343. return extractUnicode(buf.c_str());
  344. }
  345. bool StreamConsumer::ignoreChar(char c) const noexcept
  346. {
  347. return (c <= 32 || c >= 127 || c == '\n');
  348. }
  349. const std::list<Warning> &StreamConsumer::getMessages() const
  350. { return warnings; }