json.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2011 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "json.h"
  36. #include <sstream>
  37. #include "array_fun.h"
  38. #include "DlAbortEx.h"
  39. #include "error_code.h"
  40. #include "a2functional.h"
  41. #include "util.h"
  42. #include "fmt.h"
  43. namespace aria2 {
  44. namespace json {
  45. // Function prototype declaration
  46. namespace {
  47. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  48. decode
  49. (std::string::const_iterator first,
  50. std::string::const_iterator last,
  51. size_t depth);
  52. } // namespace
  53. namespace {
  54. const char WS[] = { 0x20, 0x09, 0x0a, 0x0d };
  55. const char ESCAPE_CHARS[] = { '"', '\\', '/', '\b', '\f', '\n', '\r', '\t' };
  56. const size_t MAX_STRUCTURE_DEPTH = 100;
  57. } // namespace
  58. namespace {
  59. std::string::const_iterator skipWs
  60. (std::string::const_iterator first,
  61. std::string::const_iterator last)
  62. {
  63. while(first != last && std::find(vbegin(WS), vend(WS), *first) != vend(WS)) {
  64. ++first;
  65. }
  66. return first;
  67. }
  68. } // namespace
  69. namespace {
  70. void checkEof
  71. (std::string::const_iterator first,
  72. std::string::const_iterator last)
  73. {
  74. if(first == last) {
  75. throw DL_ABORT_EX2("JSON decoding failed: unexpected EOF",
  76. error_code::JSON_PARSE_ERROR);
  77. }
  78. }
  79. } // namespace
  80. namespace {
  81. std::string::const_iterator
  82. decodeKeyword
  83. (std::string::const_iterator first,
  84. std::string::const_iterator last,
  85. const std::string& keyword)
  86. {
  87. size_t len = keyword.size();
  88. for(size_t i = 0; i < len; ++i) {
  89. checkEof(first, last);
  90. if(*first != keyword[i]) {
  91. throw DL_ABORT_EX2(fmt("JSON decoding failed: %s not found.",
  92. keyword.c_str()),
  93. error_code::JSON_PARSE_ERROR);
  94. }
  95. ++first;
  96. }
  97. return first;
  98. }
  99. } // namespace
  100. namespace {
  101. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  102. decodeTrue
  103. (std::string::const_iterator first,
  104. std::string::const_iterator last)
  105. {
  106. first = decodeKeyword(first, last, "true");
  107. return std::make_pair(Bool::gTrue(), first);
  108. }
  109. } // namespace
  110. namespace {
  111. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  112. decodeFalse
  113. (std::string::const_iterator first,
  114. std::string::const_iterator last)
  115. {
  116. first = decodeKeyword(first, last, "false");
  117. return std::make_pair(Bool::gFalse(), first);
  118. }
  119. } // namespace
  120. namespace {
  121. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  122. decodeNull
  123. (std::string::const_iterator first,
  124. std::string::const_iterator last)
  125. {
  126. first = decodeKeyword(first, last, "null");
  127. return std::make_pair(Null::g(), first);
  128. }
  129. } // namespace
  130. namespace {
  131. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  132. decodeString
  133. (std::string::const_iterator first,
  134. std::string::const_iterator last)
  135. {
  136. // Consume first char, assuming it is '"'.
  137. ++first;
  138. std::string s;
  139. std::string::const_iterator offset = first;
  140. while(first != last) {
  141. if(*first == '"') {
  142. break;
  143. }
  144. if(*first == '\\') {
  145. s += std::string(offset, first);
  146. ++first;
  147. checkEof(first, last);
  148. if(*first == 'u') {
  149. ++first;
  150. std::string uchars;
  151. for(int i = 0; i < 4; ++i, ++first) {
  152. checkEof(first, last);
  153. uchars += *first;
  154. }
  155. checkEof(first, last);
  156. uint16_t codepoint = util::parseUInt(uchars, 16);
  157. if(codepoint <= 0x007fu) {
  158. s += static_cast<char>(codepoint);
  159. } else if(codepoint <= 0x07ffu) {
  160. unsigned char c2 = 0x80u | (codepoint & 0x003fu);
  161. unsigned char c1 = 0xC0u | (codepoint >> 6);
  162. s += c1;
  163. s += c2;
  164. } else if(in(codepoint, 0xD800u, 0xDBFFu)) {
  165. // surrogate pair
  166. if(*first != '\\' || first+1 == last ||
  167. *(first+1) != 'u') {
  168. throw DL_ABORT_EX2("JSON decoding failed: bad UTF-8 sequence.",
  169. error_code::JSON_PARSE_ERROR);
  170. }
  171. first += 2;
  172. std::string uchars;
  173. for(int i = 0; i < 4; ++i, ++first) {
  174. checkEof(first, last);
  175. uchars += *first;
  176. }
  177. checkEof(first, last);
  178. uint16_t codepoint2 = util::parseUInt(uchars, 16);
  179. if(!in(codepoint2, 0xDC00u, 0xDFFFu)) {
  180. throw DL_ABORT_EX2("JSON decoding failed: bad UTF-8 sequence.",
  181. error_code::JSON_PARSE_ERROR);
  182. }
  183. uint32_t fullcodepoint = 0x010000u;
  184. fullcodepoint += (codepoint & 0x03FFu) << 10;
  185. fullcodepoint += (codepoint2 & 0x03FFu);
  186. unsigned char c4 = 0x80u | (fullcodepoint & 0x003Fu);
  187. unsigned char c3 = 0x80u | ((fullcodepoint >> 6) & 0x003Fu);
  188. unsigned char c2 = 0x80u | ((fullcodepoint >> 12) & 0x003Fu);
  189. unsigned char c1 = 0xf0u | (fullcodepoint >> 18);
  190. s += c1;
  191. s += c2;
  192. s += c3;
  193. s += c4;
  194. } else if(codepoint <= 0xffffu) {
  195. unsigned char c3 = 0x80u | (codepoint & 0x003Fu);
  196. unsigned char c2 = 0x80u | ((codepoint >> 6) & 0x003Fu);
  197. unsigned char c1 = 0xE0u | (codepoint >> 12);
  198. s += c1;
  199. s += c2;
  200. s += c3;
  201. }
  202. offset = first;
  203. } else {
  204. if(*first == 'b') {
  205. s += '\b';
  206. } else if(*first == 'f') {
  207. s += '\f';
  208. } else if(*first == 'n') {
  209. s += '\n';
  210. } else if(*first == 'r') {
  211. s += '\r';
  212. } else if(*first == 't') {
  213. s += '\t';
  214. } else {
  215. s += *first;
  216. }
  217. ++first;
  218. offset = first;
  219. }
  220. } else {
  221. ++first;
  222. }
  223. }
  224. checkEof(first, last);
  225. if(std::distance(offset, first) > 0) {
  226. s += std::string(offset, first);
  227. }
  228. if(!util::isUtf8(s)) {
  229. throw DL_ABORT_EX2("JSON decoding failed: Non UTF-8 string.",
  230. error_code::JSON_PARSE_ERROR);
  231. }
  232. ++first;
  233. return std::make_pair(String::g(s), first);
  234. }
  235. } // namespace
  236. namespace {
  237. void checkEmptyDigit
  238. (std::string::const_iterator first,
  239. std::string::const_iterator last)
  240. {
  241. if(std::distance(first, last) == 0) {
  242. throw DL_ABORT_EX2("JSON decoding failed: zero DIGIT.",
  243. error_code::JSON_PARSE_ERROR);
  244. }
  245. }
  246. } // namespace
  247. namespace {
  248. void checkLeadingZero
  249. (std::string::const_iterator first,
  250. std::string::const_iterator last)
  251. {
  252. if(std::distance(first, last) > 2 && *first == '0') {
  253. throw DL_ABORT_EX2("JSON decoding failed: leading zero.",
  254. error_code::JSON_PARSE_ERROR);
  255. }
  256. }
  257. } // namespace
  258. namespace {
  259. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  260. decodeNumber
  261. (std::string::const_iterator first,
  262. std::string::const_iterator last)
  263. {
  264. std::string s;
  265. if(*first == '-') {
  266. s += *first;
  267. ++first;
  268. }
  269. std::string::const_iterator offset = first;
  270. while(first != last && in(*first, '0', '9')) {
  271. ++first;
  272. }
  273. checkEof(first, last);
  274. checkEmptyDigit(offset, first);
  275. checkLeadingZero(offset, first);
  276. s += std::string(offset, first);
  277. bool fp = false;
  278. if(*first == '.') {
  279. fp = true;
  280. s += *first;
  281. ++first;
  282. offset = first;
  283. while(first != last && in(*first, '0', '9')) {
  284. ++first;
  285. }
  286. checkEof(first, last);
  287. checkEmptyDigit(offset, first);
  288. s += std::string(offset, first);
  289. }
  290. if(*first == 'e') {
  291. fp = true;
  292. s += *first;
  293. ++first;
  294. checkEof(first, last);
  295. if(*first == '+' || *first == '-') {
  296. s += *first;
  297. ++first;
  298. }
  299. offset = first;
  300. while(first != last && in(*first, '0', '9')) {
  301. ++first;
  302. }
  303. checkEof(first, last);
  304. checkEmptyDigit(offset, first);
  305. s += std::string(offset, first);
  306. }
  307. if(fp) {
  308. // Since we don't have floating point coutner part in ValueBase,
  309. // we just treat it as string.
  310. return std::make_pair(String::g(s), first);
  311. } else {
  312. Integer::ValueType val = util::parseLLInt(s);
  313. return std::make_pair(Integer::g(val), first);
  314. }
  315. }
  316. } // namespace
  317. namespace {
  318. void checkDepth(size_t depth)
  319. {
  320. if(depth >= MAX_STRUCTURE_DEPTH) {
  321. throw DL_ABORT_EX2("JSON decoding failed: Structure is too deep.",
  322. error_code::JSON_PARSE_ERROR);
  323. }
  324. }
  325. } // namespace
  326. namespace {
  327. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  328. decodeArray
  329. (std::string::const_iterator first,
  330. std::string::const_iterator last,
  331. size_t depth)
  332. {
  333. checkDepth(depth);
  334. SharedHandle<List> list = List::g();
  335. // Consume first char, assuming it is '['.
  336. ++first;
  337. first = skipWs(first, last);
  338. checkEof(first, last);
  339. if(*first != ']') {
  340. while(1) {
  341. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  342. r = decode(first, last, depth);
  343. list->append(r.first);
  344. first = r.second;
  345. first = skipWs(first, last);
  346. if(first == last || (*first != ',' && *first != ']')) {
  347. throw DL_ABORT_EX2("JSON decoding failed:"
  348. " value-separator ',' or ']' is not found.",
  349. error_code::JSON_PARSE_ERROR);
  350. }
  351. if(*first == ']') {
  352. break;
  353. }
  354. ++first;
  355. }
  356. }
  357. ++first;
  358. return std::make_pair(list, first);
  359. }
  360. } // namespace
  361. namespace {
  362. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  363. decodeObject
  364. (std::string::const_iterator first,
  365. std::string::const_iterator last,
  366. size_t depth)
  367. {
  368. checkDepth(depth);
  369. SharedHandle<Dict> dict = Dict::g();
  370. // Consume first char, assuming it is '{'
  371. ++first;
  372. first = skipWs(first, last);
  373. checkEof(first, last);
  374. if(*first != '}') {
  375. while(1) {
  376. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  377. keyRet = decodeString(first, last);
  378. first = keyRet.second;
  379. first = skipWs(first, last);
  380. if(first == last || *first != ':') {
  381. throw DL_ABORT_EX2("JSON decoding failed:"
  382. " name-separator ':' is not found.",
  383. error_code::JSON_PARSE_ERROR);
  384. }
  385. ++first;
  386. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  387. valueRet = decode(first, last, depth);
  388. dict->put(asString(keyRet.first)->s(), valueRet.first);
  389. first = valueRet.second;
  390. first = skipWs(first, last);
  391. if(first == last || (*first != ',' && *first != '}')) {
  392. throw DL_ABORT_EX2("JSON decoding failed:"
  393. " value-separator ',' or '}' is not found.",
  394. error_code::JSON_PARSE_ERROR);
  395. }
  396. if(*first == '}') {
  397. break;
  398. }
  399. ++first;
  400. first = skipWs(first, last);
  401. checkEof(first, last);
  402. }
  403. }
  404. ++first;
  405. return std::make_pair(dict, first);
  406. }
  407. } // namespace
  408. namespace {
  409. std::pair<SharedHandle<ValueBase>, std::string::const_iterator>
  410. decode
  411. (std::string::const_iterator first,
  412. std::string::const_iterator last,
  413. size_t depth)
  414. {
  415. first = skipWs(first, last);
  416. if(first == last) {
  417. throw DL_ABORT_EX2("JSON decoding failed:"
  418. " Unexpected EOF in term context.",
  419. error_code::JSON_PARSE_ERROR);
  420. }
  421. if(*first == '[') {
  422. return decodeArray(first, last, depth+1);
  423. } else if(*first == '{') {
  424. return decodeObject(first, last, depth+1);
  425. } else if(*first == '"') {
  426. return decodeString(first, last);
  427. } else if(*first == '-' || in(*first, '0', '9')) {
  428. return decodeNumber(first, last);
  429. } else if(*first == 't') {
  430. return decodeTrue(first, last);
  431. } else if(*first == 'f') {
  432. return decodeFalse(first, last);
  433. } else if(*first == 'n') {
  434. return decodeNull(first, last);
  435. } else {
  436. throw DL_ABORT_EX2("JSON decoding failed:"
  437. " Unexpected EOF in term context.",
  438. error_code::JSON_PARSE_ERROR);
  439. }
  440. }
  441. } // namespace
  442. SharedHandle<ValueBase> decode(const std::string& json)
  443. {
  444. std::string::const_iterator first = json.begin();
  445. std::string::const_iterator last = json.end();
  446. first = skipWs(first, last);
  447. if(first == last) {
  448. throw DL_ABORT_EX2("JSON decoding failed:"
  449. " Unexpected EOF in term context.",
  450. error_code::JSON_PARSE_ERROR);
  451. }
  452. std::pair<SharedHandle<ValueBase>, std::string::const_iterator> r;
  453. if(*first == '[') {
  454. r = decodeArray(first, last, 1);
  455. } else if(*first == '{') {
  456. r = decodeObject(first, last, 1);
  457. } else {
  458. throw DL_ABORT_EX2("JSON decoding failed:"
  459. " Unexpected EOF in term context.",
  460. error_code::JSON_PARSE_ERROR);
  461. }
  462. return r.first;
  463. }
  464. std::string jsonEscape(const std::string& s)
  465. {
  466. std::string t;
  467. for(std::string::const_iterator i = s.begin(), eoi = s.end(); i != eoi;
  468. ++i) {
  469. if(*i == '"' || *i == '\\' || *i == '/') {
  470. t += '\\';
  471. t += *i;
  472. } else if(*i == '\b') {
  473. t += "\\b";
  474. } else if(*i == '\f') {
  475. t += "\\f";
  476. } else if(*i == '\n') {
  477. t += "\\n";
  478. } else if(*i == '\r') {
  479. t += "\\r";
  480. } else if(*i == '\t') {
  481. t += "\\t";
  482. } else if(in(static_cast<unsigned char>(*i), 0x00u, 0x1Fu)) {
  483. t += "\\u00";
  484. char temp[3];
  485. temp[2] = '\0';
  486. temp[0] = (*i >> 4);
  487. temp[1] = (*i)&0x0Fu;
  488. for(int j = 0; j < 2; ++j) {
  489. if(temp[j] < 10) {
  490. temp[j] += '0';
  491. } else {
  492. temp[j] += 'A'-10;
  493. }
  494. }
  495. t += temp;
  496. } else {
  497. t += *i;
  498. }
  499. }
  500. return t;
  501. }
  502. std::string encode(const ValueBase* vlb)
  503. {
  504. class JsonValueBaseVisitor:public ValueBaseVisitor {
  505. private:
  506. std::ostringstream out_;
  507. public:
  508. virtual void visit(const String& string)
  509. {
  510. const std::string& s = string.s();
  511. std::string t = jsonEscape(s);
  512. out_ << '"';
  513. out_.write(t.data(), t.size());
  514. out_ << '"';
  515. }
  516. virtual void visit(const Integer& integer)
  517. {
  518. out_ << integer.i();
  519. }
  520. virtual void visit(const Bool& boolValue)
  521. {
  522. out_ << (boolValue.val() ? "true" : "false");
  523. }
  524. virtual void visit(const Null& nullValue)
  525. {
  526. out_ << "null";
  527. }
  528. virtual void visit(const List& list)
  529. {
  530. out_ << '[';
  531. List::ValueType::const_iterator i = list.begin();
  532. if(!list.empty()) {
  533. (*i)->accept(*this);
  534. }
  535. ++i;
  536. for(List::ValueType::const_iterator eoi = list.end(); i != eoi; ++i){
  537. out_ << ',';
  538. (*i)->accept(*this);
  539. }
  540. out_ << ']';
  541. }
  542. virtual void visit(const Dict& dict)
  543. {
  544. out_ << '{';
  545. Dict::ValueType::const_iterator i = dict.begin();
  546. if(!dict.empty()) {
  547. std::string key = jsonEscape((*i).first);
  548. out_ << '"';
  549. out_.write(key.data(), key.size());
  550. out_ << "\":";
  551. (*i).second->accept(*this);
  552. }
  553. ++i;
  554. for(Dict::ValueType::const_iterator eoi = dict.end(); i != eoi; ++i){
  555. out_ << ',';
  556. std::string key = jsonEscape((*i).first);
  557. out_ << '"';
  558. out_.write(key.data(), key.size());
  559. out_ << "\":";
  560. (*i).second->accept(*this);
  561. }
  562. out_ << '}';
  563. }
  564. std::string getResult() const
  565. {
  566. return out_.str();
  567. }
  568. };
  569. JsonValueBaseVisitor visitor;
  570. vlb->accept(visitor);
  571. return visitor.getResult();
  572. }
  573. // Serializes JSON object or array.
  574. std::string encode(const SharedHandle<ValueBase>& json)
  575. {
  576. std::ostringstream out;
  577. return encode(out, json.get()).str();
  578. }
  579. } // namespace json
  580. } // namespace aria2