JsonNode.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. * JsonNode.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "JsonNode.h"
  12. #include "filesystem/Filesystem.h"
  13. #include "JsonParser.h"
  14. #include "JsonWriter.h"
  15. namespace
  16. {
  17. // to avoid duplicating const and non-const code
  18. template<typename Node>
  19. Node & resolvePointer(Node & in, const std::string & pointer)
  20. {
  21. if(pointer.empty())
  22. return in;
  23. assert(pointer[0] == '/');
  24. size_t splitPos = pointer.find('/', 1);
  25. std::string entry = pointer.substr(1, splitPos - 1);
  26. std::string remainer = splitPos == std::string::npos ? "" : pointer.substr(splitPos);
  27. if(in.getType() == VCMI_LIB_WRAP_NAMESPACE(JsonNode)::JsonType::DATA_VECTOR)
  28. {
  29. if(entry.find_first_not_of("0123456789") != std::string::npos) // non-numbers in string
  30. throw std::runtime_error("Invalid Json pointer");
  31. if(entry.size() > 1 && entry[0] == '0') // leading zeros are not allowed
  32. throw std::runtime_error("Invalid Json pointer");
  33. auto index = boost::lexical_cast<size_t>(entry);
  34. if (in.Vector().size() > index)
  35. return in.Vector()[index].resolvePointer(remainer);
  36. }
  37. return in[entry].resolvePointer(remainer);
  38. }
  39. }
  40. VCMI_LIB_NAMESPACE_BEGIN
  41. using namespace JsonDetail;
  42. class LibClasses;
  43. class CModHandler;
  44. static const JsonNode nullNode;
  45. JsonNode::JsonNode(bool boolean)
  46. :data(boolean)
  47. {}
  48. JsonNode::JsonNode(int32_t number)
  49. :data(static_cast<int64_t>(number))
  50. {}
  51. JsonNode::JsonNode(uint32_t number)
  52. :data(static_cast<int64_t>(number))
  53. {}
  54. JsonNode::JsonNode(int64_t number)
  55. :data(number)
  56. {}
  57. JsonNode::JsonNode(double number)
  58. :data(number)
  59. {}
  60. JsonNode::JsonNode(const std::string & string)
  61. :data(string)
  62. {}
  63. JsonNode::JsonNode(const std::byte *data, size_t datasize)
  64. {
  65. JsonParser parser(reinterpret_cast<const char*>(data), datasize);
  66. *this = parser.parse("<unknown>");
  67. }
  68. JsonNode::JsonNode(const JsonPath & fileURI)
  69. {
  70. auto file = CResourceHandler::get()->load(fileURI)->readAll();
  71. JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second);
  72. *this = parser.parse(fileURI.getName());
  73. }
  74. JsonNode::JsonNode(const JsonPath & fileURI, const std::string & idx)
  75. {
  76. auto file = CResourceHandler::get(idx)->load(fileURI)->readAll();
  77. JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second);
  78. *this = parser.parse(fileURI.getName());
  79. }
  80. JsonNode::JsonNode(const JsonPath & fileURI, bool &isValidSyntax)
  81. {
  82. auto file = CResourceHandler::get()->load(fileURI)->readAll();
  83. JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second);
  84. *this = parser.parse(fileURI.getName());
  85. isValidSyntax = parser.isValid();
  86. }
  87. bool JsonNode::operator == (const JsonNode &other) const
  88. {
  89. return data == other.data;
  90. }
  91. bool JsonNode::operator != (const JsonNode &other) const
  92. {
  93. return !(*this == other);
  94. }
  95. JsonNode::JsonType JsonNode::getType() const
  96. {
  97. return static_cast<JsonType>(data.index());
  98. }
  99. void JsonNode::setMeta(const std::string & metadata, bool recursive)
  100. {
  101. meta = metadata;
  102. if (recursive)
  103. {
  104. switch (getType())
  105. {
  106. break; case JsonType::DATA_VECTOR:
  107. {
  108. for(auto & node : Vector())
  109. {
  110. node.setMeta(metadata);
  111. }
  112. }
  113. break; case JsonType::DATA_STRUCT:
  114. {
  115. for(auto & node : Struct())
  116. {
  117. node.second.setMeta(metadata);
  118. }
  119. }
  120. }
  121. }
  122. }
  123. void JsonNode::setType(JsonType Type)
  124. {
  125. if (getType() == Type)
  126. return;
  127. //float<->int conversion
  128. if(getType() == JsonType::DATA_FLOAT && Type == JsonType::DATA_INTEGER)
  129. {
  130. si64 converted = static_cast<si64>(std::get<double>(data));
  131. data = JsonData(converted);
  132. return;
  133. }
  134. else if(getType() == JsonType::DATA_INTEGER && Type == JsonType::DATA_FLOAT)
  135. {
  136. double converted = static_cast<double>(std::get<si64>(data));
  137. data = JsonData(converted);
  138. return;
  139. }
  140. //Set new node type
  141. switch(Type)
  142. {
  143. break; case JsonType::DATA_NULL: data = JsonData();
  144. break; case JsonType::DATA_BOOL: data = JsonData(false);
  145. break; case JsonType::DATA_FLOAT: data = JsonData(static_cast<double>(0.0));
  146. break; case JsonType::DATA_STRING: data = JsonData(std::string());
  147. break; case JsonType::DATA_VECTOR: data = JsonData(JsonVector());
  148. break; case JsonType::DATA_STRUCT: data = JsonData(JsonMap());
  149. break; case JsonType::DATA_INTEGER: data = JsonData(static_cast<si64>(0));
  150. }
  151. }
  152. bool JsonNode::isNull() const
  153. {
  154. return getType() == JsonType::DATA_NULL;
  155. }
  156. bool JsonNode::isNumber() const
  157. {
  158. return getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT;
  159. }
  160. bool JsonNode::isString() const
  161. {
  162. return getType() == JsonType::DATA_STRING;
  163. }
  164. bool JsonNode::isVector() const
  165. {
  166. return getType() == JsonType::DATA_VECTOR;
  167. }
  168. bool JsonNode::isStruct() const
  169. {
  170. return getType() == JsonType::DATA_STRUCT;
  171. }
  172. bool JsonNode::containsBaseData() const
  173. {
  174. switch(getType())
  175. {
  176. case JsonType::DATA_NULL:
  177. return false;
  178. case JsonType::DATA_STRUCT:
  179. for(const auto & elem : Struct())
  180. {
  181. if(elem.second.containsBaseData())
  182. return true;
  183. }
  184. return false;
  185. default:
  186. //other types (including vector) cannot be extended via merge
  187. return true;
  188. }
  189. }
  190. bool JsonNode::isCompact() const
  191. {
  192. switch(getType())
  193. {
  194. case JsonType::DATA_VECTOR:
  195. for(const JsonNode & elem : Vector())
  196. {
  197. if(!elem.isCompact())
  198. return false;
  199. }
  200. return true;
  201. case JsonType::DATA_STRUCT:
  202. {
  203. auto propertyCount = Struct().size();
  204. if(propertyCount == 0)
  205. return true;
  206. else if(propertyCount == 1)
  207. return Struct().begin()->second.isCompact();
  208. }
  209. return false;
  210. default:
  211. return true;
  212. }
  213. }
  214. bool JsonNode::TryBoolFromString(bool & success) const
  215. {
  216. success = true;
  217. if(getType() == JsonNode::JsonType::DATA_BOOL)
  218. return Bool();
  219. success = getType() == JsonNode::JsonType::DATA_STRING;
  220. if(success)
  221. {
  222. auto boolParamStr = String();
  223. boost::algorithm::trim(boolParamStr);
  224. boost::algorithm::to_lower(boolParamStr);
  225. success = boolParamStr == "true";
  226. if(success)
  227. return true;
  228. success = boolParamStr == "false";
  229. }
  230. return false;
  231. }
  232. void JsonNode::clear()
  233. {
  234. setType(JsonType::DATA_NULL);
  235. }
  236. bool & JsonNode::Bool()
  237. {
  238. setType(JsonType::DATA_BOOL);
  239. return std::get<bool>(data);
  240. }
  241. double & JsonNode::Float()
  242. {
  243. setType(JsonType::DATA_FLOAT);
  244. return std::get<double>(data);
  245. }
  246. si64 & JsonNode::Integer()
  247. {
  248. setType(JsonType::DATA_INTEGER);
  249. return std::get<si64>(data);
  250. }
  251. std::string & JsonNode::String()
  252. {
  253. setType(JsonType::DATA_STRING);
  254. return std::get<std::string>(data);
  255. }
  256. JsonVector & JsonNode::Vector()
  257. {
  258. setType(JsonType::DATA_VECTOR);
  259. return std::get<JsonVector>(data);
  260. }
  261. JsonMap & JsonNode::Struct()
  262. {
  263. setType(JsonType::DATA_STRUCT);
  264. return std::get<JsonMap>(data);
  265. }
  266. const bool boolDefault = false;
  267. bool JsonNode::Bool() const
  268. {
  269. assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_BOOL);
  270. if (getType() == JsonType::DATA_BOOL)
  271. return std::get<bool>(data);
  272. return boolDefault;
  273. }
  274. const double floatDefault = 0;
  275. double JsonNode::Float() const
  276. {
  277. assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT);
  278. if(getType() == JsonType::DATA_FLOAT)
  279. return std::get<double>(data);
  280. if(getType() == JsonType::DATA_INTEGER)
  281. return static_cast<double>(std::get<si64>(data));
  282. return floatDefault;
  283. }
  284. const si64 integerDefault = 0;
  285. si64 JsonNode::Integer() const
  286. {
  287. assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT);
  288. if(getType() == JsonType::DATA_INTEGER)
  289. return std::get<si64>(data);
  290. if(getType() == JsonType::DATA_FLOAT)
  291. return static_cast<si64>(std::get<double>(data));
  292. return integerDefault;
  293. }
  294. const std::string stringDefault = std::string();
  295. const std::string & JsonNode::String() const
  296. {
  297. assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRING);
  298. if (getType() == JsonType::DATA_STRING)
  299. return std::get<std::string>(data);
  300. return stringDefault;
  301. }
  302. const JsonVector vectorDefault = JsonVector();
  303. const JsonVector & JsonNode::Vector() const
  304. {
  305. assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_VECTOR);
  306. if (getType() == JsonType::DATA_VECTOR)
  307. return std::get<JsonVector>(data);
  308. return vectorDefault;
  309. }
  310. const JsonMap mapDefault = JsonMap();
  311. const JsonMap & JsonNode::Struct() const
  312. {
  313. assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRUCT);
  314. if (getType() == JsonType::DATA_STRUCT)
  315. return std::get<JsonMap>(data);
  316. return mapDefault;
  317. }
  318. JsonNode & JsonNode::operator[](const std::string & child)
  319. {
  320. return Struct()[child];
  321. }
  322. const JsonNode & JsonNode::operator[](const std::string & child) const
  323. {
  324. auto it = Struct().find(child);
  325. if (it != Struct().end())
  326. return it->second;
  327. return nullNode;
  328. }
  329. JsonNode & JsonNode::operator[](size_t child)
  330. {
  331. if (child >= Vector().size() )
  332. Vector().resize(child + 1);
  333. return Vector()[child];
  334. }
  335. const JsonNode & JsonNode::operator[](size_t child) const
  336. {
  337. if (child < Vector().size() )
  338. return Vector()[child];
  339. return nullNode;
  340. }
  341. const JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer) const
  342. {
  343. return ::resolvePointer(*this, jsonPointer);
  344. }
  345. JsonNode & JsonNode::resolvePointer(const std::string &jsonPointer)
  346. {
  347. return ::resolvePointer(*this, jsonPointer);
  348. }
  349. std::vector<std::byte> JsonNode::toBytes() const
  350. {
  351. std::string jsonString = toString();
  352. auto dataBegin = reinterpret_cast<const std::byte*>(jsonString.data());
  353. auto dataEnd = dataBegin + jsonString.size();
  354. std::vector<std::byte> result(dataBegin, dataEnd);
  355. return result;
  356. }
  357. std::string JsonNode::toCompactString() const
  358. {
  359. std::ostringstream out;
  360. JsonWriter writer(out, true);
  361. writer.writeNode(*this);
  362. return out.str();
  363. }
  364. std::string JsonNode::toString() const
  365. {
  366. std::ostringstream out;
  367. JsonWriter writer(out, false);
  368. writer.writeNode(*this);
  369. return out.str();
  370. }
  371. VCMI_LIB_NAMESPACE_END