streamConsumer.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #include <iostream>
  2. #include <sstream>
  3. #include "jsonElement.hh"
  4. #include "streamConsumer.hh"
  5. StreamConsumer::StreamConsumer(std::istream &s): stream(s), root(nullptr)
  6. { }
  7. StreamConsumer::~StreamConsumer()
  8. {
  9. if (root)
  10. delete root;
  11. for (Warning i : warnings)
  12. {
  13. delete i.getPtrUnsafe();
  14. }
  15. }
  16. StreamConsumer *StreamConsumer::withConfig(const AParams *p)
  17. {
  18. params = p;
  19. return this;
  20. }
  21. StreamConsumer *StreamConsumer::read()
  22. {
  23. if (root)
  24. return this;
  25. root = readNext(nullptr);
  26. return this;
  27. }
  28. JSonElement *StreamConsumer::readNext(JSonContainer *parent)
  29. {
  30. std::string buf;
  31. JSonElement *root = consumeToken(parent, buf);
  32. if (root == nullptr)
  33. {
  34. if (buf == "{")
  35. {
  36. return readObject(parent);
  37. }
  38. else if (buf == "[")
  39. {
  40. return readArray(parent);
  41. }
  42. else
  43. return nullptr;
  44. }
  45. return root;
  46. }
  47. JSonElement * const StreamConsumer::getRoot() const
  48. {
  49. return root;
  50. }
  51. JSonObject *StreamConsumer::readObject(JSonContainer *parent)
  52. {
  53. JSonElement *keyObj;
  54. JSonObject *result = nullptr;
  55. std::string buf;
  56. do
  57. {
  58. keyObj = consumeToken(result, buf);
  59. if (result == nullptr && keyObj == nullptr && buf == "}")
  60. return new JSonObject(parent);
  61. JSonPrimitive<std::string> *key = dynamic_cast<JSonPrimitive<std::string> *>(keyObj);
  62. if (key == nullptr)
  63. throw JSonObject::NotAKeyException(stream.tellg(), history);
  64. if (consumeToken(parent, buf) != nullptr || buf != ":")
  65. throw JsonUnexpectedException(':', stream.tellg(), history);
  66. if (result == nullptr)
  67. result = new JSonObject(parent);
  68. else if (result->contains(key->getValue()))
  69. {
  70. if (params->isStrict())
  71. throw JSonObject::DoubleKeyException(stream.tellg(), key->getValue(), history);
  72. else // add Warning, new key erase previous one
  73. {
  74. result->erase(key->getValue());
  75. warnings.push_back(Warning(new JSonObject::DoubleKeyException(stream.tellg(), key->getValue(), history)));
  76. }
  77. }
  78. JSonElement *child = readNext(result);
  79. result->push(key->getValue(), child);
  80. delete keyObj;
  81. keyObj = consumeToken(result, buf);
  82. } while (!keyObj && buf != "}");
  83. return result;
  84. }
  85. JSonArray *StreamConsumer::readArray(JSonContainer *parent)
  86. {
  87. JSonArray *result = nullptr;
  88. std::string buf;
  89. JSonElement *child = consumeToken(parent, buf);
  90. if (child == nullptr && buf == "]")
  91. return new JSonArray(parent); //Empty object
  92. do
  93. {
  94. if (child == nullptr && buf == "[")
  95. child = readArray(nullptr);
  96. if (child == nullptr && buf == "{")
  97. child = readObject(nullptr);
  98. if (child == nullptr)
  99. throw JsonNotJsonException(stream.tellg(), history);
  100. if (result == nullptr)
  101. result = new JSonArray(parent);
  102. child->setParent(result);
  103. result->push_back(child);
  104. child = consumeToken(result, buf);
  105. if (child != nullptr)
  106. throw JsonUnexpectedException(']', stream.tellg(), history);
  107. else if (buf == "]")
  108. break;
  109. else if (buf != ",")
  110. throw JsonUnexpectedException(']', stream.tellg(), history);
  111. child = consumeToken(result, buf);
  112. } while (true);
  113. return result;
  114. }
  115. JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &buf)
  116. {
  117. bool escaped = false;
  118. bool inString = false;
  119. bool inBool = false;
  120. bool inNumber = false;
  121. bool numberIsDouble = false;
  122. while (stream.good())
  123. {
  124. char c = stream.get();
  125. history.put(c);
  126. if (inString)
  127. {
  128. if (!escaped)
  129. {
  130. if (c == '"')
  131. return new JSonPrimitive<std::string>(parent, buf);
  132. else if (c == '\\')
  133. escaped = true;
  134. else
  135. buf += c;
  136. }
  137. else
  138. {
  139. if (c == '\\' || c == '"')
  140. {
  141. buf += c;
  142. escaped = false;
  143. }
  144. else if (c == 'u')
  145. {
  146. if (params && params->isIgnoringUnicode())
  147. {
  148. buf += "\\u";
  149. escaped = false;
  150. }
  151. else
  152. {
  153. char unicodeBuf[4];
  154. stream.read(unicodeBuf, 4);
  155. std::streamsize gcount = stream.gcount();
  156. history.put(unicodeBuf, gcount);
  157. if (gcount != 4)
  158. break;
  159. try {
  160. appendUnicode(unicodeBuf, buf);
  161. }
  162. catch (std::invalid_argument &e)
  163. {
  164. throw JsonHexvalueException(e.what(), stream.tellg(), history);
  165. }
  166. escaped = false;
  167. }
  168. }
  169. else
  170. throw JsonEscapedException(c, stream.tellg(), history);
  171. }
  172. }
  173. else if (inBool)
  174. {
  175. if (c == 'a' || c == 'e' || c == 'l' || c == 'r' || c == 's' || c == 'u')
  176. buf += c;
  177. else if (buf == "true")
  178. {
  179. history.pop_back();
  180. stream.unget();
  181. return new JSonPrimitive<bool>(parent, true);
  182. }
  183. else if (buf == "false")
  184. {
  185. history.pop_back();
  186. stream.unget();
  187. return new JSonPrimitive<bool>(parent, false);
  188. }
  189. else if (ignoreChar(c))
  190. ;
  191. else
  192. throw JsonFormatException(stream.tellg(), history);
  193. }
  194. else if (inNumber)
  195. {
  196. if (c >= '0' && c <= '9')
  197. buf += c;
  198. else if (c == '.' && !numberIsDouble)
  199. {
  200. numberIsDouble = true;
  201. buf += c;
  202. }
  203. else
  204. {
  205. history.pop_back();
  206. stream.unget();
  207. if (numberIsDouble)
  208. {
  209. try {
  210. return new JSonPrimitive<double>(parent, atof(buf.c_str()));
  211. } catch (std::runtime_error &e)
  212. {
  213. throw JsonFormatException(stream.tellg(), history);
  214. }
  215. }
  216. try
  217. {
  218. return new JSonPrimitive<int>(parent, std::stoi(buf));
  219. }
  220. catch(std::out_of_range e)
  221. {
  222. return new JSonPrimitive<long long>(parent, std::stol(buf));
  223. }
  224. }
  225. }
  226. else
  227. {
  228. //!InString, !inbool
  229. if (c == '"')
  230. {
  231. buf = "";
  232. inString = true;
  233. }
  234. else if (c == 't' || c == 'f')
  235. {
  236. buf = c;
  237. inBool = true;
  238. }
  239. else if (c == '{' || c == '[' || c == '}' || c == ']' || c == ':' || c == ',')
  240. {
  241. buf = c;
  242. return nullptr;
  243. }
  244. else if ((c >= '0' && c <= '9') || c == '.' || c == '-')
  245. {
  246. buf = c;
  247. inNumber = true;
  248. }
  249. else if (!ignoreChar(c))
  250. throw JsonFormatException(stream.tellg(), history);
  251. }
  252. }
  253. buf = "";
  254. return nullptr;
  255. }
  256. static unsigned char hexbyte(const char c)
  257. {
  258. if (c >= '0' && c <= '9')
  259. return c - '0';
  260. if (c >= 'A' && c <= 'F')
  261. return c - 'A' + 10;
  262. if (c >= 'a' && c <= 'f')
  263. return c - 'a' + 10;
  264. throw std::invalid_argument(JsonHexvalueException::msg(c));
  265. }
  266. static unsigned char hexbyte(const char str[2])
  267. {
  268. unsigned char result = 0;
  269. result = (hexbyte(*str) <<4) + hexbyte(str[1]);
  270. return result;
  271. }
  272. void StreamConsumer::appendUnicode(const char unicode[4], std::string &buf)
  273. {
  274. unsigned short uni = (hexbyte(unicode) <<8) + hexbyte(unicode+2);
  275. char test[5];
  276. bzero(test, sizeof(*test) *5);
  277. snprintf(test, 4, "%lc", uni);
  278. buf += test;
  279. }
  280. bool StreamConsumer::ignoreChar(char c) const noexcept
  281. {
  282. return (c <= 32 || c >= 127 || c == '\n');
  283. }
  284. const std::list<Warning> &StreamConsumer::getMessages() const
  285. { return warnings; }