streamConsumer.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include <iostream>
  2. #include <sstream>
  3. #include "jsonException.hh"
  4. #include "jsonElement.hh"
  5. #include "streamConsumer.hh"
  6. StreamConsumer::StreamConsumer(std::istream &s): stream(s)
  7. { }
  8. StreamConsumer::~StreamConsumer()
  9. {
  10. if (root)
  11. delete root;
  12. }
  13. StreamConsumer *StreamConsumer::read(std::istream &stream)
  14. {
  15. StreamConsumer *inst = new StreamConsumer(stream);
  16. inst->root = inst->readNext(nullptr);
  17. return inst;
  18. }
  19. JSonElement *StreamConsumer::readNext(JSonContainer *parent)
  20. {
  21. std::string buf;
  22. JSonElement *root = consumeToken(parent, buf);
  23. if (root == nullptr)
  24. {
  25. if (buf == "{")
  26. {
  27. return readObject(parent);
  28. }
  29. else if (buf == "[")
  30. {
  31. return readArray(parent);
  32. }
  33. else
  34. return nullptr;
  35. }
  36. return root;
  37. }
  38. JSonElement * const StreamConsumer::getRoot() const
  39. {
  40. return root;
  41. }
  42. JSonObject *StreamConsumer::readObject(JSonContainer *parent)
  43. {
  44. JSonElement *keyObj;
  45. JSonObject *result = nullptr;
  46. std::string buf;
  47. do
  48. {
  49. keyObj = consumeToken(result, buf);
  50. if (result == nullptr && keyObj == nullptr && buf == "}")
  51. return new JSonObject(parent);
  52. JSonPrimitive<std::string> *key = dynamic_cast<JSonPrimitive<std::string> *>(keyObj);
  53. if (key == nullptr)
  54. throw JSonObject::NotAKeyException(stream.tellg(), history);
  55. if (consumeToken(parent, buf) != nullptr || buf != ":")
  56. throw JsonUnexpectedException(':', stream.tellg(), history);
  57. if (result == nullptr)
  58. result = new JSonObject(parent);
  59. else if (result->contains(key->getValue()))
  60. throw JSonObject::DoubleKeyException(stream.tellg(), key->getValue(), history); //Double key
  61. JSonElement *child = readNext(result);
  62. result->push(key->getValue(), child);
  63. delete keyObj;
  64. keyObj = consumeToken(result, buf);
  65. } while (!keyObj && buf != "}");
  66. return result;
  67. }
  68. JSonArray *StreamConsumer::readArray(JSonContainer *parent)
  69. {
  70. JSonArray *result = nullptr;
  71. std::string buf;
  72. JSonElement *child = consumeToken(parent, buf);
  73. if (child == nullptr && buf == "]")
  74. return new JSonArray(parent); //Empty object
  75. do
  76. {
  77. if (child == nullptr && buf == "[")
  78. child = readArray(nullptr);
  79. if (child == nullptr && buf == "{")
  80. child = readObject(nullptr);
  81. if (child == nullptr)
  82. throw JsonNotJsonException(stream.tellg(), history);
  83. if (result == nullptr)
  84. result = new JSonArray(parent);
  85. child->setParent(result);
  86. result->push_back(child);
  87. child = consumeToken(result, buf);
  88. if (child != nullptr)
  89. throw JsonUnexpectedException(']', stream.tellg(), history);
  90. else if (buf == "]")
  91. break;
  92. else if (buf != ",")
  93. throw JsonUnexpectedException(']', stream.tellg(), history);
  94. child = consumeToken(result, buf);
  95. } while (true);
  96. return result;
  97. }
  98. JSonElement *StreamConsumer::consumeToken(JSonContainer *parent, std::string &buf)
  99. {
  100. bool escaped = false;
  101. bool inString = false;
  102. bool inBool = false;
  103. bool inNumber = false;
  104. bool numberIsDouble = false;
  105. while (stream.good())
  106. {
  107. char c = stream.get();
  108. history.put(c);
  109. if (inString)
  110. {
  111. if (!escaped)
  112. {
  113. if (c == '"')
  114. return new JSonPrimitive<std::string>(parent, buf);
  115. else if (c == '\\')
  116. escaped = true;
  117. else
  118. buf += c;
  119. }
  120. else
  121. {
  122. if (c == '\\' || c == '"')
  123. {
  124. buf += c;
  125. escaped = false;
  126. }
  127. else
  128. throw JsonEscapedException(c, stream.tellg(), history);
  129. }
  130. }
  131. else if (inBool)
  132. {
  133. if (c == 'a' || c == 'e' || c == 'l' || c == 'r' || c == 's' || c == 'u')
  134. buf += c;
  135. else if (buf == "true")
  136. {
  137. history.pop_back();
  138. stream.unget();
  139. return new JSonPrimitive<bool>(parent, true);
  140. }
  141. else if (buf == "false")
  142. {
  143. history.pop_back();
  144. stream.unget();
  145. return new JSonPrimitive<bool>(parent, false);
  146. }
  147. else if (ignoreChar(c))
  148. ;
  149. else
  150. throw JsonFormatException(stream.tellg(), history);
  151. }
  152. else if (inNumber)
  153. {
  154. if (c >= '0' && c <= '9')
  155. buf += c;
  156. else if (c == '.' && !numberIsDouble)
  157. {
  158. numberIsDouble = true;
  159. buf += c;
  160. }
  161. else
  162. {
  163. history.pop_back();
  164. stream.unget();
  165. if (numberIsDouble)
  166. {
  167. try {
  168. return new JSonPrimitive<double>(parent, atof(buf.c_str()));
  169. } catch (std::runtime_error &e)
  170. {
  171. throw JsonFormatException(stream.tellg(), history);
  172. }
  173. }
  174. try
  175. {
  176. return new JSonPrimitive<int>(parent, std::stoi(buf));
  177. }
  178. catch(std::out_of_range e)
  179. {
  180. return new JSonPrimitive<long long>(parent, std::stol(buf));
  181. }
  182. }
  183. }
  184. else
  185. {
  186. //!InString, !inbool
  187. if (c == '"')
  188. {
  189. buf = "";
  190. inString = true;
  191. }
  192. else if (c == 't' || c == 'f')
  193. {
  194. buf = c;
  195. inBool = true;
  196. }
  197. else if (c == '{' || c == '[' || c == '}' || c == ']' || c == ':' || c == ',')
  198. {
  199. buf = c;
  200. return nullptr;
  201. }
  202. else if ((c >= '0' && c <= '9') || c == '.' || c == '-')
  203. {
  204. buf = c;
  205. inNumber = true;
  206. }
  207. else if (!ignoreChar(c))
  208. throw JsonFormatException(stream.tellg(), history);
  209. }
  210. }
  211. buf = "";
  212. return nullptr;
  213. }
  214. bool StreamConsumer::ignoreChar(char c) const noexcept
  215. {
  216. return (c <= 32 || c >= 127 || c == '\n');
  217. }