You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

754 lines
19 KiB

  1. // Copyright (c) From https://github.com/nbsdx/SimpleJSON
  2. // 2022 Binbin Zhang (binbzha@qq.com)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #ifndef UTILS_JSON_H_
  16. #define UTILS_JSON_H_
  17. #include <cctype>
  18. #include <cmath>
  19. #include <cstdint>
  20. #include <deque>
  21. #include <initializer_list>
  22. #include <iostream>
  23. #include <map>
  24. #include <ostream>
  25. #include <string>
  26. #include <type_traits>
  27. #include <utility>
  28. namespace json {
  29. using std::deque;
  30. using std::enable_if;
  31. using std::initializer_list;
  32. using std::is_convertible;
  33. using std::is_floating_point;
  34. using std::is_integral;
  35. using std::is_same;
  36. using std::map;
  37. using std::string;
  38. namespace { // NOLINT
  39. string json_escape(const string& str) {
  40. string output;
  41. for (unsigned i = 0; i < str.length(); ++i) switch (str[i]) {
  42. case '\"':
  43. output += "\\\"";
  44. break;
  45. case '\\':
  46. output += "\\\\";
  47. break;
  48. case '\b':
  49. output += "\\b";
  50. break;
  51. case '\f':
  52. output += "\\f";
  53. break;
  54. case '\n':
  55. output += "\\n";
  56. break;
  57. case '\r':
  58. output += "\\r";
  59. break;
  60. case '\t':
  61. output += "\\t";
  62. break;
  63. default:
  64. output += str[i];
  65. break;
  66. }
  67. return std::move(output);
  68. }
  69. } // namespace
  70. class JSON {
  71. union BackingData {
  72. BackingData(double d) : Float(d) {}
  73. BackingData(int l) : Int(l) {}
  74. BackingData(bool b) : Bool(b) {}
  75. BackingData(string s) : String(new string(s)) {}
  76. BackingData() : Int(0) {}
  77. deque<JSON>* List;
  78. map<string, JSON>* Map;
  79. string* String;
  80. double Float;
  81. int Int;
  82. bool Bool;
  83. } Internal;
  84. public:
  85. enum class Class { Null, Object, Array, String, Floating, Integral, Boolean };
  86. template <typename Container>
  87. class JSONWrapper {
  88. Container* object;
  89. public:
  90. explicit JSONWrapper(Container* val) : object(val) {}
  91. explicit JSONWrapper(std::nullptr_t) : object(nullptr) {}
  92. typename Container::iterator begin() {
  93. return object ? object->begin() : typename Container::iterator();
  94. }
  95. typename Container::iterator end() {
  96. return object ? object->end() : typename Container::iterator();
  97. }
  98. typename Container::const_iterator begin() const {
  99. return object ? object->begin() : typename Container::iterator();
  100. }
  101. typename Container::const_iterator end() const {
  102. return object ? object->end() : typename Container::iterator();
  103. }
  104. };
  105. template <typename Container>
  106. class JSONConstWrapper {
  107. const Container* object;
  108. public:
  109. explicit JSONConstWrapper(const Container* val) : object(val) {}
  110. explicit JSONConstWrapper(std::nullptr_t) : object(nullptr) {}
  111. typename Container::const_iterator begin() const {
  112. return object ? object->begin() : typename Container::const_iterator();
  113. }
  114. typename Container::const_iterator end() const {
  115. return object ? object->end() : typename Container::const_iterator();
  116. }
  117. };
  118. JSON() : Internal(), Type(Class::Null) {}
  119. explicit JSON(initializer_list<JSON> list) : JSON() {
  120. SetType(Class::Object);
  121. for (auto i = list.begin(), e = list.end(); i != e; ++i, ++i)
  122. operator[](i->ToString()) = *std::next(i);
  123. }
  124. JSON(JSON&& other) : Internal(other.Internal), Type(other.Type) {
  125. other.Type = Class::Null;
  126. other.Internal.Map = nullptr;
  127. }
  128. JSON& operator=(JSON&& other) {
  129. ClearInternal();
  130. Internal = other.Internal;
  131. Type = other.Type;
  132. other.Internal.Map = nullptr;
  133. other.Type = Class::Null;
  134. return *this;
  135. }
  136. JSON(const JSON& other) {
  137. switch (other.Type) {
  138. case Class::Object:
  139. Internal.Map = new map<string, JSON>(other.Internal.Map->begin(),
  140. other.Internal.Map->end());
  141. break;
  142. case Class::Array:
  143. Internal.List = new deque<JSON>(other.Internal.List->begin(),
  144. other.Internal.List->end());
  145. break;
  146. case Class::String:
  147. Internal.String = new string(*other.Internal.String);
  148. break;
  149. default:
  150. Internal = other.Internal;
  151. }
  152. Type = other.Type;
  153. }
  154. JSON& operator=(const JSON& other) {
  155. ClearInternal();
  156. switch (other.Type) {
  157. case Class::Object:
  158. Internal.Map = new map<string, JSON>(other.Internal.Map->begin(),
  159. other.Internal.Map->end());
  160. break;
  161. case Class::Array:
  162. Internal.List = new deque<JSON>(other.Internal.List->begin(),
  163. other.Internal.List->end());
  164. break;
  165. case Class::String:
  166. Internal.String = new string(*other.Internal.String);
  167. break;
  168. default:
  169. Internal = other.Internal;
  170. }
  171. Type = other.Type;
  172. return *this;
  173. }
  174. ~JSON() {
  175. switch (Type) {
  176. case Class::Array:
  177. delete Internal.List;
  178. break;
  179. case Class::Object:
  180. delete Internal.Map;
  181. break;
  182. case Class::String:
  183. delete Internal.String;
  184. break;
  185. default: {
  186. };
  187. }
  188. }
  189. template <typename T>
  190. explicit JSON(T b, typename enable_if<is_same<T, bool>::value>::type* = 0)
  191. : Internal(b), Type(Class::Boolean) {}
  192. template <typename T>
  193. explicit JSON(T i, typename enable_if<is_integral<T>::value &&
  194. !is_same<T, bool>::value>::type* = 0)
  195. : Internal(static_cast<int>(i)), Type(Class::Integral) {}
  196. template <typename T>
  197. explicit JSON(T f, typename enable_if<is_floating_point<T>::value>::type* = 0)
  198. : Internal(static_cast<double>(f)), Type(Class::Floating) {}
  199. template <typename T>
  200. explicit JSON(T s,
  201. typename enable_if<is_convertible<T, string>::value>::type* = 0)
  202. : Internal(string(s)), Type(Class::String) {}
  203. explicit JSON(std::nullptr_t) : Internal(), Type(Class::Null) {}
  204. static JSON Make(Class type) {
  205. JSON ret;
  206. ret.SetType(type);
  207. return ret;
  208. }
  209. static JSON Load(const string&);
  210. template <typename T>
  211. void append(T arg) {
  212. SetType(Class::Array);
  213. Internal.List->emplace_back(arg);
  214. }
  215. template <typename T, typename... U>
  216. void append(T arg, U... args) {
  217. append(arg);
  218. append(args...);
  219. }
  220. template <typename T>
  221. typename enable_if<is_same<T, bool>::value, JSON&>::type operator=(T b) {
  222. SetType(Class::Boolean);
  223. Internal.Bool = b;
  224. return *this;
  225. }
  226. template <typename T>
  227. typename enable_if<is_integral<T>::value && !is_same<T, bool>::value,
  228. JSON&>::type
  229. operator=(T i) {
  230. SetType(Class::Integral);
  231. Internal.Int = i;
  232. return *this;
  233. }
  234. template <typename T>
  235. typename enable_if<is_floating_point<T>::value, JSON&>::type operator=(T f) {
  236. SetType(Class::Floating);
  237. Internal.Float = f;
  238. return *this;
  239. }
  240. template <typename T>
  241. typename enable_if<is_convertible<T, string>::value, JSON&>::type operator=(
  242. T s) {
  243. SetType(Class::String);
  244. *Internal.String = string(s);
  245. return *this;
  246. }
  247. JSON& operator[](const string& key) {
  248. SetType(Class::Object);
  249. return Internal.Map->operator[](key);
  250. }
  251. JSON& operator[](unsigned index) {
  252. SetType(Class::Array);
  253. if (index >= Internal.List->size()) Internal.List->resize(index + 1);
  254. return Internal.List->operator[](index);
  255. }
  256. JSON& at(const string& key) { return operator[](key); }
  257. const JSON& at(const string& key) const { return Internal.Map->at(key); }
  258. JSON& at(unsigned index) { return operator[](index); }
  259. const JSON& at(unsigned index) const { return Internal.List->at(index); }
  260. int length() const {
  261. if (Type == Class::Array)
  262. return Internal.List->size();
  263. else
  264. return -1;
  265. }
  266. bool hasKey(const string& key) const {
  267. if (Type == Class::Object)
  268. return Internal.Map->find(key) != Internal.Map->end();
  269. return false;
  270. }
  271. int size() const {
  272. if (Type == Class::Object)
  273. return Internal.Map->size();
  274. else if (Type == Class::Array)
  275. return Internal.List->size();
  276. else
  277. return -1;
  278. }
  279. Class JSONType() const { return Type; }
  280. /// Functions for getting primitives from the JSON object.
  281. bool IsNull() const { return Type == Class::Null; }
  282. string ToString() const {
  283. bool b;
  284. return std::move(ToString(&b));
  285. }
  286. string ToString(bool* ok) const {
  287. *ok = (Type == Class::String);
  288. return *ok ? std::move(json_escape(*Internal.String)) : string("");
  289. }
  290. double ToFloat() const {
  291. bool b;
  292. return ToFloat(&b);
  293. }
  294. double ToFloat(bool* ok) const {
  295. *ok = (Type == Class::Floating);
  296. return *ok ? Internal.Float : 0.0;
  297. }
  298. int ToInt() const {
  299. bool b;
  300. return ToInt(&b);
  301. }
  302. int ToInt(bool* ok) const {
  303. *ok = (Type == Class::Integral);
  304. return *ok ? Internal.Int : 0;
  305. }
  306. bool ToBool() const {
  307. bool b;
  308. return ToBool(&b);
  309. }
  310. bool ToBool(bool* ok) const {
  311. *ok = (Type == Class::Boolean);
  312. return *ok ? Internal.Bool : false;
  313. }
  314. JSONWrapper<map<string, JSON>> ObjectRange() {
  315. if (Type == Class::Object)
  316. return JSONWrapper<map<string, JSON>>(Internal.Map);
  317. return JSONWrapper<map<string, JSON>>(nullptr);
  318. }
  319. JSONWrapper<deque<JSON>> ArrayRange() {
  320. if (Type == Class::Array) return JSONWrapper<deque<JSON>>(Internal.List);
  321. return JSONWrapper<deque<JSON>>(nullptr);
  322. }
  323. JSONConstWrapper<map<string, JSON>> ObjectRange() const {
  324. if (Type == Class::Object)
  325. return JSONConstWrapper<map<string, JSON>>(Internal.Map);
  326. return JSONConstWrapper<map<string, JSON>>(nullptr);
  327. }
  328. JSONConstWrapper<deque<JSON>> ArrayRange() const {
  329. if (Type == Class::Array)
  330. return JSONConstWrapper<deque<JSON>>(Internal.List);
  331. return JSONConstWrapper<deque<JSON>>(nullptr);
  332. }
  333. string dump(int depth = 1, string tab = " ") const {
  334. string pad = "";
  335. for (int i = 0; i < depth; ++i, pad += tab) {
  336. }
  337. switch (Type) {
  338. case Class::Null:
  339. return "null";
  340. case Class::Object: {
  341. string s = "{\n";
  342. bool skip = true;
  343. for (auto& p : *Internal.Map) {
  344. if (!skip) s += ",\n";
  345. s += (pad + "\"" + p.first + "\" : " + p.second.dump(depth + 1, tab));
  346. skip = false;
  347. }
  348. s += ("\n" + pad.erase(0, 2) + "}");
  349. return s;
  350. }
  351. case Class::Array: {
  352. string s = "[";
  353. bool skip = true;
  354. for (auto& p : *Internal.List) {
  355. if (!skip) s += ", ";
  356. s += p.dump(depth + 1, tab);
  357. skip = false;
  358. }
  359. s += "]";
  360. return s;
  361. }
  362. case Class::String:
  363. return "\"" + json_escape(*Internal.String) + "\"";
  364. case Class::Floating:
  365. return std::to_string(Internal.Float);
  366. case Class::Integral:
  367. return std::to_string(Internal.Int);
  368. case Class::Boolean:
  369. return Internal.Bool ? "true" : "false";
  370. default:
  371. return "";
  372. }
  373. return "";
  374. }
  375. friend std::ostream& operator<<(std::ostream&, const JSON&);
  376. private:
  377. void SetType(Class type) {
  378. if (type == Type) return;
  379. ClearInternal();
  380. switch (type) {
  381. case Class::Null:
  382. Internal.Map = nullptr;
  383. break;
  384. case Class::Object:
  385. Internal.Map = new map<string, JSON>();
  386. break;
  387. case Class::Array:
  388. Internal.List = new deque<JSON>();
  389. break;
  390. case Class::String:
  391. Internal.String = new string();
  392. break;
  393. case Class::Floating:
  394. Internal.Float = 0.0;
  395. break;
  396. case Class::Integral:
  397. Internal.Int = 0;
  398. break;
  399. case Class::Boolean:
  400. Internal.Bool = false;
  401. break;
  402. }
  403. Type = type;
  404. }
  405. private:
  406. /* beware: only call if YOU know that Internal is allocated. No checks
  407. performed here. This function should be called in a constructed JSON just
  408. before you are going to overwrite Internal...
  409. */
  410. void ClearInternal() {
  411. switch (Type) {
  412. case Class::Object:
  413. delete Internal.Map;
  414. break;
  415. case Class::Array:
  416. delete Internal.List;
  417. break;
  418. case Class::String:
  419. delete Internal.String;
  420. break;
  421. default: {
  422. };
  423. }
  424. }
  425. private:
  426. Class Type = Class::Null;
  427. };
  428. JSON Array() { return std::move(JSON::Make(JSON::Class::Array)); }
  429. template <typename... T>
  430. JSON Array(T... args) {
  431. JSON arr = JSON::Make(JSON::Class::Array);
  432. arr.append(args...);
  433. return std::move(arr);
  434. }
  435. JSON Object() { return std::move(JSON::Make(JSON::Class::Object)); }
  436. std::ostream& operator<<(std::ostream& os, const JSON& json) {
  437. os << json.dump();
  438. return os;
  439. }
  440. namespace { // NOLINT
  441. JSON parse_next(const string&, size_t&);
  442. void consume_ws(const string& str, size_t& offset) { // NOLINT
  443. while (isspace(str[offset])) ++offset;
  444. }
  445. JSON parse_object(const string& str, size_t& offset) { // NOLINT
  446. JSON Object = JSON::Make(JSON::Class::Object);
  447. ++offset;
  448. consume_ws(str, offset);
  449. if (str[offset] == '}') {
  450. ++offset;
  451. return std::move(Object);
  452. }
  453. while (true) {
  454. JSON Key = parse_next(str, offset);
  455. consume_ws(str, offset);
  456. if (str[offset] != ':') {
  457. std::cerr << "Error: Object: Expected colon, found '" << str[offset]
  458. << "'\n";
  459. break;
  460. }
  461. consume_ws(str, ++offset);
  462. JSON Value = parse_next(str, offset);
  463. Object[Key.ToString()] = Value;
  464. consume_ws(str, offset);
  465. if (str[offset] == ',') {
  466. ++offset;
  467. continue;
  468. } else if (str[offset] == '}') {
  469. ++offset;
  470. break;
  471. } else {
  472. std::cerr << "ERROR: Object: Expected comma, found '" << str[offset]
  473. << "'\n";
  474. break;
  475. }
  476. }
  477. return std::move(Object);
  478. }
  479. JSON parse_array(const string& str, size_t& offset) { // NOLINT
  480. JSON Array = JSON::Make(JSON::Class::Array);
  481. unsigned index = 0;
  482. ++offset;
  483. consume_ws(str, offset);
  484. if (str[offset] == ']') {
  485. ++offset;
  486. return std::move(Array);
  487. }
  488. while (true) {
  489. Array[index++] = parse_next(str, offset);
  490. consume_ws(str, offset);
  491. if (str[offset] == ',') {
  492. ++offset;
  493. continue;
  494. } else if (str[offset] == ']') {
  495. ++offset;
  496. break;
  497. } else {
  498. std::cerr << "ERROR: Array: Expected ',' or ']', found '" << str[offset]
  499. << "'\n";
  500. return std::move(JSON::Make(JSON::Class::Array));
  501. }
  502. }
  503. return std::move(Array);
  504. }
  505. JSON parse_string(const string& str, size_t& offset) { // NOLINT
  506. JSON String;
  507. string val;
  508. for (char c = str[++offset]; c != '\"'; c = str[++offset]) {
  509. if (c == '\\') {
  510. switch (str[++offset]) {
  511. case '\"':
  512. val += '\"';
  513. break;
  514. case '\\':
  515. val += '\\';
  516. break;
  517. case '/':
  518. val += '/';
  519. break;
  520. case 'b':
  521. val += '\b';
  522. break;
  523. case 'f':
  524. val += '\f';
  525. break;
  526. case 'n':
  527. val += '\n';
  528. break;
  529. case 'r':
  530. val += '\r';
  531. break;
  532. case 't':
  533. val += '\t';
  534. break;
  535. case 'u': {
  536. val += "\\u";
  537. for (unsigned i = 1; i <= 4; ++i) {
  538. c = str[offset + i];
  539. if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  540. (c >= 'A' && c <= 'F')) {
  541. val += c;
  542. } else {
  543. std::cerr << "ERROR: String: Expected hex character in unicode "
  544. "escape, found '"
  545. << c << "'\n";
  546. return std::move(JSON::Make(JSON::Class::String));
  547. }
  548. }
  549. offset += 4;
  550. } break;
  551. default:
  552. val += '\\';
  553. break;
  554. }
  555. } else {
  556. val += c;
  557. }
  558. }
  559. ++offset;
  560. String = val;
  561. return std::move(String);
  562. }
  563. JSON parse_number(const string& str, size_t& offset) { // NOLINT
  564. JSON Number;
  565. string val, exp_str;
  566. char c;
  567. bool isDouble = false;
  568. int exp = 0;
  569. while (true) {
  570. c = str[offset++];
  571. if ((c == '-') || (c >= '0' && c <= '9')) {
  572. val += c;
  573. } else if (c == '.') {
  574. val += c;
  575. isDouble = true;
  576. } else {
  577. break;
  578. }
  579. }
  580. if (c == 'E' || c == 'e') {
  581. c = str[offset++];
  582. if (c == '-') {
  583. ++offset;
  584. exp_str += '-';
  585. }
  586. while (true) {
  587. c = str[offset++];
  588. if (c >= '0' && c <= '9') {
  589. exp_str += c;
  590. } else if (!isspace(c) && c != ',' && c != ']' && c != '}') {
  591. std::cerr << "ERROR: Number: Expected a number for exponent, found '"
  592. << c << "'\n";
  593. return std::move(JSON::Make(JSON::Class::Null));
  594. } else {
  595. break;
  596. }
  597. }
  598. exp = std::stol(exp_str);
  599. } else if (!isspace(c) && c != ',' && c != ']' && c != '}') {
  600. std::cerr << "ERROR: Number: unexpected character '" << c << "'\n";
  601. return std::move(JSON::Make(JSON::Class::Null));
  602. }
  603. --offset;
  604. if (isDouble) {
  605. Number = std::stod(val) * std::pow(10, exp);
  606. } else {
  607. if (!exp_str.empty())
  608. Number = std::stol(val) * std::pow(10, exp);
  609. else
  610. Number = std::stol(val);
  611. }
  612. return std::move(Number);
  613. }
  614. JSON parse_bool(const string& str, size_t& offset) { // NOLINT
  615. JSON Bool;
  616. if (str.substr(offset, 4) == "true") {
  617. Bool = true;
  618. } else if (str.substr(offset, 5) == "false") {
  619. Bool = false;
  620. } else {
  621. std::cerr << "ERROR: Bool: Expected 'true' or 'false', found '"
  622. << str.substr(offset, 5) << "'\n";
  623. return std::move(JSON::Make(JSON::Class::Null));
  624. }
  625. offset += (Bool.ToBool() ? 4 : 5);
  626. return std::move(Bool);
  627. }
  628. JSON parse_null(const string& str, size_t& offset) { // NOLINT
  629. JSON Null;
  630. if (str.substr(offset, 4) != "null") {
  631. std::cerr << "ERROR: Null: Expected 'null', found '"
  632. << str.substr(offset, 4) << "'\n";
  633. return std::move(JSON::Make(JSON::Class::Null));
  634. }
  635. offset += 4;
  636. return std::move(Null);
  637. }
  638. JSON parse_next(const string& str, size_t& offset) { // NOLINT
  639. char value;
  640. consume_ws(str, offset);
  641. value = str[offset];
  642. switch (value) {
  643. case '[':
  644. return std::move(parse_array(str, offset));
  645. case '{':
  646. return std::move(parse_object(str, offset));
  647. case '\"':
  648. return std::move(parse_string(str, offset));
  649. case 't':
  650. case 'f':
  651. return std::move(parse_bool(str, offset));
  652. case 'n':
  653. return std::move(parse_null(str, offset));
  654. default:
  655. if ((value <= '9' && value >= '0') || value == '-')
  656. return std::move(parse_number(str, offset));
  657. }
  658. std::cerr << "ERROR: Parse: Unknown starting character '" << value << "'\n";
  659. return JSON();
  660. }
  661. } // namespace
  662. JSON JSON::Load(const string& str) {
  663. size_t offset = 0;
  664. return std::move(parse_next(str, offset));
  665. }
  666. } // namespace json
  667. #endif // UTILS_JSON_H_