JsonNode.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. #define VCMI_DLL
  2. #include "JsonNode.h"
  3. #include <assert.h>
  4. #include <fstream>
  5. #include <sstream>
  6. #include <iostream>
  7. const JsonNode JsonNode::nullNode;
  8. JsonNode::JsonNode(JsonType Type):
  9. type(DATA_NULL)
  10. {
  11. setType(Type);
  12. }
  13. JsonNode::JsonNode(std::string input):
  14. type(DATA_NULL)
  15. {
  16. JsonParser parser(input, *this);
  17. }
  18. JsonNode::JsonNode(const char *filename):
  19. type(DATA_NULL)
  20. {
  21. std::ifstream file(filename);
  22. std::string str((std::istreambuf_iterator<char>(file)),
  23. std::istreambuf_iterator<char>());
  24. JsonParser parser(str, *this);
  25. }
  26. JsonNode::JsonNode(const JsonNode &copy):
  27. type(DATA_NULL)
  28. {
  29. *this = copy;
  30. }
  31. JsonNode::~JsonNode()
  32. {
  33. setType(DATA_NULL);
  34. }
  35. JsonNode & JsonNode::operator =(const JsonNode &node)
  36. {
  37. setType(node.getType());
  38. switch(type)
  39. {
  40. break; case DATA_NULL:
  41. break; case DATA_BOOL: Bool() = node.Bool();
  42. break; case DATA_FLOAT: Float() = node.Float();
  43. break; case DATA_STRING: String() = node.String();
  44. break; case DATA_VECTOR: Vector() = node.Vector();
  45. break; case DATA_STRUCT: Struct() = node.Struct();
  46. }
  47. return *this;
  48. }
  49. JsonNode::JsonType JsonNode::getType() const
  50. {
  51. return type;
  52. }
  53. void JsonNode::setType(JsonType Type)
  54. {
  55. if (type == Type)
  56. return;
  57. if (Type != DATA_NULL)
  58. setType(DATA_NULL);
  59. switch (type)
  60. {
  61. break; case DATA_STRING: delete data.String;
  62. break; case DATA_VECTOR : delete data.Vector;
  63. break; case DATA_STRUCT: delete data.Struct;
  64. break; default:
  65. break;
  66. }
  67. type = Type;
  68. switch(type)
  69. {
  70. break; case DATA_NULL:
  71. break; case DATA_BOOL: data.Bool = false;
  72. break; case DATA_FLOAT: data.Float = 0;
  73. break; case DATA_STRING: data.String = new std::string;
  74. break; case DATA_VECTOR: data.Vector = new JsonVector;
  75. break; case DATA_STRUCT: data.Struct = new JsonMap;
  76. }
  77. }
  78. bool JsonNode::isNull() const
  79. {
  80. return type == DATA_NULL;
  81. }
  82. bool & JsonNode::Bool()
  83. {
  84. setType(DATA_BOOL);
  85. return data.Bool;
  86. }
  87. float & JsonNode::Float()
  88. {
  89. setType(DATA_FLOAT);
  90. return data.Float;
  91. }
  92. std::string & JsonNode::String()
  93. {
  94. setType(DATA_STRING);
  95. return *data.String;
  96. }
  97. JsonVector & JsonNode::Vector()
  98. {
  99. setType(DATA_VECTOR);
  100. return *data.Vector;
  101. }
  102. JsonMap & JsonNode::Struct()
  103. {
  104. setType(DATA_STRUCT);
  105. return *data.Struct;
  106. }
  107. const bool & JsonNode::Bool(const bool &value) const
  108. {
  109. if (isNull())
  110. return value;
  111. assert(type == DATA_BOOL);
  112. return data.Bool;
  113. }
  114. const float & JsonNode::Float(const float &value) const
  115. {
  116. if (isNull())
  117. return value;
  118. assert(type == DATA_FLOAT);
  119. return data.Float;
  120. }
  121. const std::string & JsonNode::String(const std::string &value) const
  122. {
  123. if (isNull())
  124. return value;
  125. assert(type == DATA_STRING);
  126. return *data.String;
  127. }
  128. const JsonVector & JsonNode::Vector(const JsonVector &value) const
  129. {
  130. if (isNull())
  131. return value;
  132. assert(type == DATA_VECTOR);
  133. return *data.Vector;
  134. }
  135. const JsonMap & JsonNode::Struct(const JsonMap &value) const
  136. {
  137. if (isNull())
  138. return value;
  139. assert(type == DATA_STRUCT);
  140. return *data.Struct;
  141. }
  142. JsonNode & JsonNode::operator[](std::string child)
  143. {
  144. return Struct()[child];
  145. }
  146. const JsonNode & JsonNode::operator[](std::string child) const
  147. {
  148. JsonMap::const_iterator it = Struct().find(child);
  149. if (it != Struct().end())
  150. return it->second;
  151. return nullNode;
  152. }
  153. ////////////////////////////////////////////////////////////////////////////////
  154. //Helper to write content of map/vector
  155. template<class iterator>
  156. void writeContainer(const iterator &begin, const iterator &end, std::ostream &out, std::string prefix)
  157. {
  158. if (begin == end)
  159. return;
  160. iterator last = end;
  161. last--;
  162. for (iterator it=begin; it != last; ++it)
  163. {
  164. writeNode(it, out, prefix);
  165. out<<",\n";
  166. }
  167. writeNode(last, out, prefix);
  168. out<<"\n";
  169. }
  170. void writeNode(JsonVector::const_iterator it, std::ostream &out, std::string prefix)
  171. {
  172. out << prefix;
  173. it->write(out, prefix);
  174. }
  175. void writeNode(JsonMap::const_iterator it, std::ostream &out, std::string prefix)
  176. {
  177. out << prefix << '\"' << it->first << '\"' << " : ";
  178. it->second.write(out, prefix);
  179. }
  180. void JsonNode::write(std::ostream &out, std::string prefix) const
  181. {
  182. switch(type)
  183. {
  184. break; case DATA_NULL:
  185. out << "null";
  186. break; case DATA_BOOL:
  187. if (Bool())
  188. out << "true";
  189. else
  190. out << "false";
  191. break; case DATA_FLOAT:
  192. out << Float();
  193. break; case DATA_STRING:
  194. out << "\"" << String() << "\"";
  195. break; case DATA_VECTOR:
  196. out << "[" << "\n";
  197. writeContainer(Vector().begin(), Vector().end(), out, prefix+'\t');
  198. out << prefix << "]";
  199. break; case DATA_STRUCT:
  200. out << "{" << "\n";
  201. writeContainer(Struct().begin(), Struct().end(), out, prefix+'\t');
  202. out << prefix << "}";
  203. }
  204. }
  205. std::ostream & operator<<(std::ostream &out, const JsonNode &node)
  206. {
  207. node.write(out);
  208. return out << "\n";
  209. }
  210. ////////////////////////////////////////////////////////////////////////////////
  211. JsonParser::JsonParser(const std::string inputString, JsonNode &root):
  212. input(inputString),
  213. lineCount(1),
  214. lineStart(0),
  215. pos(0)
  216. {
  217. extractValue(root);
  218. extractWhitespace(false);
  219. //Warn if there are any non-whitespace symbols left
  220. if (pos < input.size())
  221. error("Not all file was parsed!", true);
  222. //TODO: better way to show errors (like printing file name as well)
  223. tlog2<<errors;
  224. }
  225. bool JsonParser::extractSeparator()
  226. {
  227. if (!extractWhitespace())
  228. return false;
  229. if ( input[pos] !=':')
  230. return error("Separator expected");
  231. pos++;
  232. return true;
  233. }
  234. bool JsonParser::extractValue(JsonNode &node)
  235. {
  236. if (!extractWhitespace())
  237. return false;
  238. switch (input[pos])
  239. {
  240. case '\"': return extractString(node);
  241. case 'n' : return extractNull(node);
  242. case 't' : return extractTrue(node);
  243. case 'f' : return extractFalse(node);
  244. case '{' : return extractStruct(node);
  245. case '[' : return extractArray(node);
  246. case '-' : return extractFloat(node);
  247. default:
  248. {
  249. if (input[pos] >= '0' && input[pos] <= '9')
  250. return extractFloat(node);
  251. return error("Value expected!");
  252. }
  253. }
  254. }
  255. bool JsonParser::extractWhitespace(bool verbose)
  256. {
  257. while (true)
  258. {
  259. while (pos < input.size() && (unsigned char)input[pos] <= ' ')
  260. {
  261. if (input[pos] == '\n')
  262. {
  263. lineCount++;
  264. lineStart = pos+1;
  265. }
  266. pos++;
  267. }
  268. if (pos >= input.size() || input[pos] != '/')
  269. break;
  270. pos++;
  271. if (pos == input.size())
  272. break;
  273. if (input[pos] == '/')
  274. pos++;
  275. else
  276. error("Comments should have two slashes!", true);
  277. pos = input.find('\n', pos);
  278. }
  279. if (pos >= input.size() && verbose)
  280. return error("Unexpected end of file!");
  281. return true;
  282. }
  283. bool JsonParser::extractEscaping(std::string &str)
  284. {
  285. switch(input[pos++])
  286. {
  287. break; case '\"': str += '\"';
  288. break; case '\\': str += '\\';
  289. break; case '/': str += '/';
  290. break; case '\b': str += '\b';
  291. break; case '\f': str += '\f';
  292. break; case '\n': str += '\n';
  293. break; case '\r': str += '\r';
  294. break; case '\t': str += '\t';
  295. break; default: return error("Uknown escape sequence!", true);
  296. };
  297. return true;
  298. }
  299. bool JsonParser::extractString(std::string &str)
  300. {
  301. if (input[pos] != '\"')
  302. return error("String expected!");
  303. pos++;
  304. size_t first = pos;
  305. while (pos != input.size())
  306. {
  307. if (input[pos] == '\"') // Correct end of string
  308. {
  309. str += input.substr(first, pos-first);
  310. pos++;
  311. return true;
  312. }
  313. if (input[pos] == '\\') // Escaping
  314. {
  315. str += input.substr(first, pos-first);
  316. first = pos++;
  317. if (pos == input.size())
  318. break;
  319. extractEscaping(str);
  320. }
  321. if (input[pos] == '\n') // end-of-line
  322. {
  323. str += input.substr(first, pos-first);
  324. return error("Closing quote not found!", true);
  325. }
  326. if (input[pos] < ' ') // control character
  327. {
  328. str += input.substr(first, pos-first);
  329. first = pos+1;
  330. error("Illegal character in the string!", true);
  331. }
  332. pos++;
  333. }
  334. return error("Unterminated string!");
  335. }
  336. bool JsonParser::extractString(JsonNode &node)
  337. {
  338. std::string str;
  339. if (!extractString(str))
  340. return false;
  341. node.setType(JsonNode::DATA_STRING);
  342. node.String() = str;
  343. return true;
  344. }
  345. bool JsonParser::extractLiteral(const std::string &literal)
  346. {
  347. if (input.compare(pos, literal.size(), literal) != 0)
  348. {
  349. pos = input.find_first_of(" \n\r\t", pos);
  350. return error("Unknown literal found", true);
  351. }
  352. pos += literal.size();
  353. return true;
  354. }
  355. bool JsonParser::extractNull(JsonNode &node)
  356. {
  357. if (!extractLiteral("null"))
  358. return false;
  359. node.setType(JsonNode::DATA_NULL);
  360. return true;
  361. }
  362. bool JsonParser::extractTrue(JsonNode &node)
  363. {
  364. if (!extractLiteral("true"))
  365. return false;
  366. node.setType(JsonNode::DATA_BOOL);
  367. node.Bool() = true;
  368. return true;
  369. }
  370. bool JsonParser::extractFalse(JsonNode &node)
  371. {
  372. if (!extractLiteral("false"))
  373. return false;
  374. node.setType(JsonNode::DATA_BOOL);
  375. node.Bool() = false;
  376. return true;
  377. }
  378. bool JsonParser::extractStruct(JsonNode &node)
  379. {
  380. node.setType(JsonNode::DATA_STRUCT);
  381. pos++;
  382. if (!extractWhitespace())
  383. return false;
  384. //Empty struct found
  385. if (input[pos] == '}')
  386. {
  387. pos++;
  388. return true;
  389. }
  390. while (true)
  391. {
  392. if (!extractWhitespace())
  393. return false;
  394. std::string key;
  395. if (!extractString(key))
  396. return false;
  397. if (node.Struct().find(key) != node.Struct().end())
  398. error("Dublicated element encountered!", true);
  399. JsonNode &child = node.Struct()[key];
  400. if (!extractSeparator())
  401. return false;
  402. if (!extractValue(child))
  403. return false;
  404. if (!extractWhitespace())
  405. return false;
  406. bool comma = (input[pos] == ',');
  407. if (comma )
  408. {
  409. pos++;
  410. if (!extractWhitespace())
  411. return false;
  412. }
  413. if (input[pos] == '}')
  414. {
  415. pos++;
  416. return true;
  417. }
  418. if (!comma)
  419. error("Comma expected!", true);
  420. }
  421. }
  422. bool JsonParser::extractArray(JsonNode &node)
  423. {
  424. pos++;
  425. node.setType(JsonNode::DATA_VECTOR);
  426. if (!extractWhitespace())
  427. return false;
  428. //Empty array found
  429. if (input[pos] == ']')
  430. {
  431. pos++;
  432. return true;
  433. }
  434. while (true)
  435. {
  436. node.Vector().resize(node.Vector().size()+1);
  437. if (!extractValue(node.Vector().back()))
  438. return false;
  439. if (!extractWhitespace())
  440. return false;
  441. bool comma = (input[pos] == ',');
  442. if (comma )
  443. {
  444. pos++;
  445. if (!extractWhitespace())
  446. return false;
  447. }
  448. if (input[pos] == ']')
  449. {
  450. pos++;
  451. return true;
  452. }
  453. if (!comma)
  454. error("Comma expected!", true);
  455. }
  456. }
  457. bool JsonParser::extractFloat(JsonNode &node)
  458. {
  459. assert(input[pos] == '-' || (input[pos] >= '0' && input[pos] <= '9'));
  460. bool negative=false;
  461. float result=0;
  462. if (input[pos] == '-')
  463. {
  464. pos++;
  465. negative = true;
  466. }
  467. if (input[pos] < '0' || input[pos] > '9')
  468. return error("Number expected!");
  469. //Extract integer part
  470. while (input[pos] >= '0' && input[pos] <= '9')
  471. {
  472. result = result*10+(input[pos]-'0');
  473. pos++;
  474. }
  475. if (input[pos] == '.')
  476. {
  477. //extract fractional part
  478. pos++;
  479. float fractMult = 0.1;
  480. if (input[pos] < '0' || input[pos] > '9')
  481. return error("Decimal part expected!");
  482. while (input[pos] >= '0' && input[pos] <= '9')
  483. {
  484. result = result + fractMult*(input[pos]-'0');
  485. fractMult /= 10;
  486. pos++;
  487. }
  488. }
  489. //TODO: exponential part
  490. if (negative)
  491. result = -result;
  492. node.setType(JsonNode::DATA_FLOAT);
  493. node.Float() = result;
  494. return true;
  495. }
  496. bool JsonParser::error(const std::string &message, bool warning)
  497. {
  498. std::ostringstream stream;
  499. std::string type(warning?" warning: ":" error: ");
  500. stream << "At line " << lineCount << ", position "<<pos-lineStart
  501. << type << message <<"\n";
  502. errors += stream.str();
  503. return warning;
  504. }