json_reader.cpp 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016
  1. // Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
  2. // Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
  3. // Distributed under MIT license, or public domain if desired and
  4. // recognized in your jurisdiction.
  5. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
  6. #if !defined(JSON_IS_AMALGAMATION)
  7. #include "json_tool.h"
  8. #include <json/assertions.h>
  9. #include <json/reader.h>
  10. #include <json/value.h>
  11. #endif // if !defined(JSON_IS_AMALGAMATION)
  12. #include <algorithm>
  13. #include <cassert>
  14. #include <cmath>
  15. #include <cstring>
  16. #include <iostream>
  17. #include <istream>
  18. #include <limits>
  19. #include <memory>
  20. #include <set>
  21. #include <sstream>
  22. #include <utility>
  23. #include <cstdio>
  24. #if __cplusplus >= 201103L
  25. #if !defined(sscanf)
  26. #define sscanf std::sscanf
  27. #endif
  28. #endif //__cplusplus
  29. #if defined(_MSC_VER)
  30. #if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
  31. #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
  32. #endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
  33. #endif //_MSC_VER
  34. #if defined(_MSC_VER)
  35. // Disable warning about strdup being deprecated.
  36. #pragma warning(disable : 4996)
  37. #endif
  38. // Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
  39. // time to change the stack limit
  40. #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
  41. #define JSONCPP_DEPRECATED_STACK_LIMIT 1000
  42. #endif
  43. static size_t const stackLimit_g =
  44. JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
  45. namespace Json {
  46. #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
  47. using CharReaderPtr = std::unique_ptr<CharReader>;
  48. #else
  49. using CharReaderPtr = std::auto_ptr<CharReader>;
  50. #endif
  51. // Implementation of class Features
  52. // ////////////////////////////////
  53. Features::Features() = default;
  54. Features Features::all() { return {}; }
  55. Features Features::strictMode() {
  56. Features features;
  57. features.allowComments_ = false;
  58. features.strictRoot_ = true;
  59. features.allowDroppedNullPlaceholders_ = false;
  60. features.allowNumericKeys_ = false;
  61. return features;
  62. }
  63. // Implementation of class Reader
  64. // ////////////////////////////////
  65. bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
  66. return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
  67. }
  68. // Class Reader
  69. // //////////////////////////////////////////////////////////////////
  70. Reader::Reader() : features_(Features::all()) {}
  71. Reader::Reader(const Features& features) : features_(features) {}
  72. bool Reader::parse(const std::string& document, Value& root,
  73. bool collectComments) {
  74. document_.assign(document.begin(), document.end());
  75. const char* begin = document_.c_str();
  76. const char* end = begin + document_.length();
  77. return parse(begin, end, root, collectComments);
  78. }
  79. bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
  80. // std::istream_iterator<char> begin(is);
  81. // std::istream_iterator<char> end;
  82. // Those would allow streamed input from a file, if parse() were a
  83. // template function.
  84. // Since String is reference-counted, this at least does not
  85. // create an extra copy.
  86. String doc(std::istreambuf_iterator<char>(is), {});
  87. return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
  88. }
  89. bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
  90. bool collectComments) {
  91. if (!features_.allowComments_) {
  92. collectComments = false;
  93. }
  94. begin_ = beginDoc;
  95. end_ = endDoc;
  96. collectComments_ = collectComments;
  97. current_ = begin_;
  98. lastValueEnd_ = nullptr;
  99. lastValue_ = nullptr;
  100. commentsBefore_.clear();
  101. errors_.clear();
  102. while (!nodes_.empty())
  103. nodes_.pop();
  104. nodes_.push(&root);
  105. bool successful = readValue();
  106. Token token;
  107. readTokenSkippingComments(token);
  108. if (collectComments_ && !commentsBefore_.empty())
  109. root.setComment(commentsBefore_, commentAfter);
  110. if (features_.strictRoot_) {
  111. if (!root.isArray() && !root.isObject()) {
  112. // Set error location to start of doc, ideally should be first token found
  113. // in doc
  114. token.type_ = tokenError;
  115. token.start_ = beginDoc;
  116. token.end_ = endDoc;
  117. addError(
  118. "A valid JSON document must be either an array or an object value.",
  119. token);
  120. return false;
  121. }
  122. }
  123. return successful;
  124. }
  125. bool Reader::readValue() {
  126. // readValue() may call itself only if it calls readObject() or ReadArray().
  127. // These methods execute nodes_.push() just before and nodes_.pop)() just
  128. // after calling readValue(). parse() executes one nodes_.push(), so > instead
  129. // of >=.
  130. if (nodes_.size() > stackLimit_g)
  131. throwRuntimeError("Exceeded stackLimit in readValue().");
  132. Token token;
  133. readTokenSkippingComments(token);
  134. bool successful = true;
  135. if (collectComments_ && !commentsBefore_.empty()) {
  136. currentValue().setComment(commentsBefore_, commentBefore);
  137. commentsBefore_.clear();
  138. }
  139. switch (token.type_) {
  140. case tokenObjectBegin:
  141. successful = readObject(token);
  142. currentValue().setOffsetLimit(current_ - begin_);
  143. break;
  144. case tokenArrayBegin:
  145. successful = readArray(token);
  146. currentValue().setOffsetLimit(current_ - begin_);
  147. break;
  148. case tokenNumber:
  149. successful = decodeNumber(token);
  150. break;
  151. case tokenString:
  152. successful = decodeString(token);
  153. break;
  154. case tokenTrue: {
  155. Value v(true);
  156. currentValue().swapPayload(v);
  157. currentValue().setOffsetStart(token.start_ - begin_);
  158. currentValue().setOffsetLimit(token.end_ - begin_);
  159. } break;
  160. case tokenFalse: {
  161. Value v(false);
  162. currentValue().swapPayload(v);
  163. currentValue().setOffsetStart(token.start_ - begin_);
  164. currentValue().setOffsetLimit(token.end_ - begin_);
  165. } break;
  166. case tokenNull: {
  167. Value v;
  168. currentValue().swapPayload(v);
  169. currentValue().setOffsetStart(token.start_ - begin_);
  170. currentValue().setOffsetLimit(token.end_ - begin_);
  171. } break;
  172. case tokenArraySeparator:
  173. case tokenObjectEnd:
  174. case tokenArrayEnd:
  175. if (features_.allowDroppedNullPlaceholders_) {
  176. // "Un-read" the current token and mark the current value as a null
  177. // token.
  178. current_--;
  179. Value v;
  180. currentValue().swapPayload(v);
  181. currentValue().setOffsetStart(current_ - begin_ - 1);
  182. currentValue().setOffsetLimit(current_ - begin_);
  183. break;
  184. } // Else, fall through...
  185. default:
  186. currentValue().setOffsetStart(token.start_ - begin_);
  187. currentValue().setOffsetLimit(token.end_ - begin_);
  188. return addError("Syntax error: value, object or array expected.", token);
  189. }
  190. if (collectComments_) {
  191. lastValueEnd_ = current_;
  192. lastValue_ = &currentValue();
  193. }
  194. return successful;
  195. }
  196. bool Reader::readTokenSkippingComments(Token& token) {
  197. bool success = readToken(token);
  198. if (features_.allowComments_) {
  199. while (success && token.type_ == tokenComment) {
  200. success = readToken(token);
  201. }
  202. }
  203. return success;
  204. }
  205. bool Reader::readToken(Token& token) {
  206. skipSpaces();
  207. token.start_ = current_;
  208. Char c = getNextChar();
  209. bool ok = true;
  210. switch (c) {
  211. case '{':
  212. token.type_ = tokenObjectBegin;
  213. break;
  214. case '}':
  215. token.type_ = tokenObjectEnd;
  216. break;
  217. case '[':
  218. token.type_ = tokenArrayBegin;
  219. break;
  220. case ']':
  221. token.type_ = tokenArrayEnd;
  222. break;
  223. case '"':
  224. token.type_ = tokenString;
  225. ok = readString();
  226. break;
  227. case '/':
  228. token.type_ = tokenComment;
  229. ok = readComment();
  230. break;
  231. case '0':
  232. case '1':
  233. case '2':
  234. case '3':
  235. case '4':
  236. case '5':
  237. case '6':
  238. case '7':
  239. case '8':
  240. case '9':
  241. case '-':
  242. token.type_ = tokenNumber;
  243. readNumber();
  244. break;
  245. case 't':
  246. token.type_ = tokenTrue;
  247. ok = match("rue", 3);
  248. break;
  249. case 'f':
  250. token.type_ = tokenFalse;
  251. ok = match("alse", 4);
  252. break;
  253. case 'n':
  254. token.type_ = tokenNull;
  255. ok = match("ull", 3);
  256. break;
  257. case ',':
  258. token.type_ = tokenArraySeparator;
  259. break;
  260. case ':':
  261. token.type_ = tokenMemberSeparator;
  262. break;
  263. case 0:
  264. token.type_ = tokenEndOfStream;
  265. break;
  266. default:
  267. ok = false;
  268. break;
  269. }
  270. if (!ok)
  271. token.type_ = tokenError;
  272. token.end_ = current_;
  273. return ok;
  274. }
  275. void Reader::skipSpaces() {
  276. while (current_ != end_) {
  277. Char c = *current_;
  278. if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
  279. ++current_;
  280. else
  281. break;
  282. }
  283. }
  284. bool Reader::match(const Char* pattern, int patternLength) {
  285. if (end_ - current_ < patternLength)
  286. return false;
  287. int index = patternLength;
  288. while (index--)
  289. if (current_[index] != pattern[index])
  290. return false;
  291. current_ += patternLength;
  292. return true;
  293. }
  294. bool Reader::readComment() {
  295. Location commentBegin = current_ - 1;
  296. Char c = getNextChar();
  297. bool successful = false;
  298. if (c == '*')
  299. successful = readCStyleComment();
  300. else if (c == '/')
  301. successful = readCppStyleComment();
  302. if (!successful)
  303. return false;
  304. if (collectComments_) {
  305. CommentPlacement placement = commentBefore;
  306. if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
  307. if (c != '*' || !containsNewLine(commentBegin, current_))
  308. placement = commentAfterOnSameLine;
  309. }
  310. addComment(commentBegin, current_, placement);
  311. }
  312. return true;
  313. }
  314. String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
  315. String normalized;
  316. normalized.reserve(static_cast<size_t>(end - begin));
  317. Reader::Location current = begin;
  318. while (current != end) {
  319. char c = *current++;
  320. if (c == '\r') {
  321. if (current != end && *current == '\n')
  322. // convert dos EOL
  323. ++current;
  324. // convert Mac EOL
  325. normalized += '\n';
  326. } else {
  327. normalized += c;
  328. }
  329. }
  330. return normalized;
  331. }
  332. void Reader::addComment(Location begin, Location end,
  333. CommentPlacement placement) {
  334. assert(collectComments_);
  335. const String& normalized = normalizeEOL(begin, end);
  336. if (placement == commentAfterOnSameLine) {
  337. assert(lastValue_ != nullptr);
  338. lastValue_->setComment(normalized, placement);
  339. } else {
  340. commentsBefore_ += normalized;
  341. }
  342. }
  343. bool Reader::readCStyleComment() {
  344. while ((current_ + 1) < end_) {
  345. Char c = getNextChar();
  346. if (c == '*' && *current_ == '/')
  347. break;
  348. }
  349. return getNextChar() == '/';
  350. }
  351. bool Reader::readCppStyleComment() {
  352. while (current_ != end_) {
  353. Char c = getNextChar();
  354. if (c == '\n')
  355. break;
  356. if (c == '\r') {
  357. // Consume DOS EOL. It will be normalized in addComment.
  358. if (current_ != end_ && *current_ == '\n')
  359. getNextChar();
  360. // Break on Moc OS 9 EOL.
  361. break;
  362. }
  363. }
  364. return true;
  365. }
  366. void Reader::readNumber() {
  367. Location p = current_;
  368. char c = '0'; // stopgap for already consumed character
  369. // integral part
  370. while (c >= '0' && c <= '9')
  371. c = (current_ = p) < end_ ? *p++ : '\0';
  372. // fractional part
  373. if (c == '.') {
  374. c = (current_ = p) < end_ ? *p++ : '\0';
  375. while (c >= '0' && c <= '9')
  376. c = (current_ = p) < end_ ? *p++ : '\0';
  377. }
  378. // exponential part
  379. if (c == 'e' || c == 'E') {
  380. c = (current_ = p) < end_ ? *p++ : '\0';
  381. if (c == '+' || c == '-')
  382. c = (current_ = p) < end_ ? *p++ : '\0';
  383. while (c >= '0' && c <= '9')
  384. c = (current_ = p) < end_ ? *p++ : '\0';
  385. }
  386. }
  387. bool Reader::readString() {
  388. Char c = '\0';
  389. while (current_ != end_) {
  390. c = getNextChar();
  391. if (c == '\\')
  392. getNextChar();
  393. else if (c == '"')
  394. break;
  395. }
  396. return c == '"';
  397. }
  398. bool Reader::readObject(Token& token) {
  399. Token tokenName;
  400. String name;
  401. Value init(objectValue);
  402. currentValue().swapPayload(init);
  403. currentValue().setOffsetStart(token.start_ - begin_);
  404. while (readTokenSkippingComments(tokenName)) {
  405. if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
  406. return true;
  407. name.clear();
  408. if (tokenName.type_ == tokenString) {
  409. if (!decodeString(tokenName, name))
  410. return recoverFromError(tokenObjectEnd);
  411. } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
  412. Value numberName;
  413. if (!decodeNumber(tokenName, numberName))
  414. return recoverFromError(tokenObjectEnd);
  415. name = numberName.asString();
  416. } else {
  417. break;
  418. }
  419. Token colon;
  420. if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
  421. return addErrorAndRecover("Missing ':' after object member name", colon,
  422. tokenObjectEnd);
  423. }
  424. Value& value = currentValue()[name];
  425. nodes_.push(&value);
  426. bool ok = readValue();
  427. nodes_.pop();
  428. if (!ok) // error already set
  429. return recoverFromError(tokenObjectEnd);
  430. Token comma;
  431. if (!readTokenSkippingComments(comma) ||
  432. (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) {
  433. return addErrorAndRecover("Missing ',' or '}' in object declaration",
  434. comma, tokenObjectEnd);
  435. }
  436. if (comma.type_ == tokenObjectEnd)
  437. return true;
  438. }
  439. return addErrorAndRecover("Missing '}' or object member name", tokenName,
  440. tokenObjectEnd);
  441. }
  442. bool Reader::readArray(Token& token) {
  443. Value init(arrayValue);
  444. currentValue().swapPayload(init);
  445. currentValue().setOffsetStart(token.start_ - begin_);
  446. skipSpaces();
  447. if (current_ != end_ && *current_ == ']') // empty array
  448. {
  449. Token endArray;
  450. readToken(endArray);
  451. return true;
  452. }
  453. int index = 0;
  454. for (;;) {
  455. Value& value = currentValue()[index++];
  456. nodes_.push(&value);
  457. bool ok = readValue();
  458. nodes_.pop();
  459. if (!ok) // error already set
  460. return recoverFromError(tokenArrayEnd);
  461. Token currentToken;
  462. // Accept Comment after last item in the array.
  463. ok = readTokenSkippingComments(currentToken);
  464. bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
  465. currentToken.type_ != tokenArrayEnd);
  466. if (!ok || badTokenType) {
  467. return addErrorAndRecover("Missing ',' or ']' in array declaration",
  468. currentToken, tokenArrayEnd);
  469. }
  470. if (currentToken.type_ == tokenArrayEnd)
  471. break;
  472. }
  473. return true;
  474. }
  475. bool Reader::decodeNumber(Token& token) {
  476. Value decoded;
  477. if (!decodeNumber(token, decoded))
  478. return false;
  479. currentValue().swapPayload(decoded);
  480. currentValue().setOffsetStart(token.start_ - begin_);
  481. currentValue().setOffsetLimit(token.end_ - begin_);
  482. return true;
  483. }
  484. bool Reader::decodeNumber(Token& token, Value& decoded) {
  485. // Attempts to parse the number as an integer. If the number is
  486. // larger than the maximum supported value of an integer then
  487. // we decode the number as a double.
  488. Location current = token.start_;
  489. bool isNegative = *current == '-';
  490. if (isNegative)
  491. ++current;
  492. // TODO: Help the compiler do the div and mod at compile time or get rid of
  493. // them.
  494. Value::LargestUInt maxIntegerValue =
  495. isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
  496. : Value::maxLargestUInt;
  497. Value::LargestUInt threshold = maxIntegerValue / 10;
  498. Value::LargestUInt value = 0;
  499. while (current < token.end_) {
  500. Char c = *current++;
  501. if (c < '0' || c > '9')
  502. return decodeDouble(token, decoded);
  503. auto digit(static_cast<Value::UInt>(c - '0'));
  504. if (value >= threshold) {
  505. // We've hit or exceeded the max value divided by 10 (rounded down). If
  506. // a) we've only just touched the limit, b) this is the last digit, and
  507. // c) it's small enough to fit in that rounding delta, we're okay.
  508. // Otherwise treat this number as a double to avoid overflow.
  509. if (value > threshold || current != token.end_ ||
  510. digit > maxIntegerValue % 10) {
  511. return decodeDouble(token, decoded);
  512. }
  513. }
  514. value = value * 10 + digit;
  515. }
  516. if (isNegative && value == maxIntegerValue)
  517. decoded = Value::minLargestInt;
  518. else if (isNegative)
  519. decoded = -Value::LargestInt(value);
  520. else if (value <= Value::LargestUInt(Value::maxInt))
  521. decoded = Value::LargestInt(value);
  522. else
  523. decoded = value;
  524. return true;
  525. }
  526. bool Reader::decodeDouble(Token& token) {
  527. Value decoded;
  528. if (!decodeDouble(token, decoded))
  529. return false;
  530. currentValue().swapPayload(decoded);
  531. currentValue().setOffsetStart(token.start_ - begin_);
  532. currentValue().setOffsetLimit(token.end_ - begin_);
  533. return true;
  534. }
  535. bool Reader::decodeDouble(Token& token, Value& decoded) {
  536. double value = 0;
  537. IStringStream is(String(token.start_, token.end_));
  538. if (!(is >> value)) {
  539. if (value == std::numeric_limits<double>::max())
  540. value = std::numeric_limits<double>::infinity();
  541. else if (value == std::numeric_limits<double>::lowest())
  542. value = -std::numeric_limits<double>::infinity();
  543. else if (!std::isinf(value))
  544. return addError(
  545. "'" + String(token.start_, token.end_) + "' is not a number.", token);
  546. }
  547. decoded = value;
  548. return true;
  549. }
  550. bool Reader::decodeString(Token& token) {
  551. String decoded_string;
  552. if (!decodeString(token, decoded_string))
  553. return false;
  554. Value decoded(decoded_string);
  555. currentValue().swapPayload(decoded);
  556. currentValue().setOffsetStart(token.start_ - begin_);
  557. currentValue().setOffsetLimit(token.end_ - begin_);
  558. return true;
  559. }
  560. bool Reader::decodeString(Token& token, String& decoded) {
  561. decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
  562. Location current = token.start_ + 1; // skip '"'
  563. Location end = token.end_ - 1; // do not include '"'
  564. while (current != end) {
  565. Char c = *current++;
  566. if (c == '"')
  567. break;
  568. if (c == '\\') {
  569. if (current == end)
  570. return addError("Empty escape sequence in string", token, current);
  571. Char escape = *current++;
  572. switch (escape) {
  573. case '"':
  574. decoded += '"';
  575. break;
  576. case '/':
  577. decoded += '/';
  578. break;
  579. case '\\':
  580. decoded += '\\';
  581. break;
  582. case 'b':
  583. decoded += '\b';
  584. break;
  585. case 'f':
  586. decoded += '\f';
  587. break;
  588. case 'n':
  589. decoded += '\n';
  590. break;
  591. case 'r':
  592. decoded += '\r';
  593. break;
  594. case 't':
  595. decoded += '\t';
  596. break;
  597. case 'u': {
  598. unsigned int unicode;
  599. if (!decodeUnicodeCodePoint(token, current, end, unicode))
  600. return false;
  601. decoded += codePointToUTF8(unicode);
  602. } break;
  603. default:
  604. return addError("Bad escape sequence in string", token, current);
  605. }
  606. } else {
  607. decoded += c;
  608. }
  609. }
  610. return true;
  611. }
  612. bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
  613. Location end, unsigned int& unicode) {
  614. if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
  615. return false;
  616. if (unicode >= 0xD800 && unicode <= 0xDBFF) {
  617. // surrogate pairs
  618. if (end - current < 6)
  619. return addError(
  620. "additional six characters expected to parse unicode surrogate pair.",
  621. token, current);
  622. if (*(current++) == '\\' && *(current++) == 'u') {
  623. unsigned int surrogatePair;
  624. if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
  625. unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
  626. } else
  627. return false;
  628. } else
  629. return addError("expecting another \\u token to begin the second half of "
  630. "a unicode surrogate pair",
  631. token, current);
  632. }
  633. return true;
  634. }
  635. bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
  636. Location end,
  637. unsigned int& ret_unicode) {
  638. if (end - current < 4)
  639. return addError(
  640. "Bad unicode escape sequence in string: four digits expected.", token,
  641. current);
  642. int unicode = 0;
  643. for (int index = 0; index < 4; ++index) {
  644. Char c = *current++;
  645. unicode *= 16;
  646. if (c >= '0' && c <= '9')
  647. unicode += c - '0';
  648. else if (c >= 'a' && c <= 'f')
  649. unicode += c - 'a' + 10;
  650. else if (c >= 'A' && c <= 'F')
  651. unicode += c - 'A' + 10;
  652. else
  653. return addError(
  654. "Bad unicode escape sequence in string: hexadecimal digit expected.",
  655. token, current);
  656. }
  657. ret_unicode = static_cast<unsigned int>(unicode);
  658. return true;
  659. }
  660. bool Reader::addError(const String& message, Token& token, Location extra) {
  661. ErrorInfo info;
  662. info.token_ = token;
  663. info.message_ = message;
  664. info.extra_ = extra;
  665. errors_.push_back(info);
  666. return false;
  667. }
  668. bool Reader::recoverFromError(TokenType skipUntilToken) {
  669. size_t const errorCount = errors_.size();
  670. Token skip;
  671. for (;;) {
  672. if (!readToken(skip))
  673. errors_.resize(errorCount); // discard errors caused by recovery
  674. if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
  675. break;
  676. }
  677. errors_.resize(errorCount);
  678. return false;
  679. }
  680. bool Reader::addErrorAndRecover(const String& message, Token& token,
  681. TokenType skipUntilToken) {
  682. addError(message, token);
  683. return recoverFromError(skipUntilToken);
  684. }
  685. Value& Reader::currentValue() { return *(nodes_.top()); }
  686. Reader::Char Reader::getNextChar() {
  687. if (current_ == end_)
  688. return 0;
  689. return *current_++;
  690. }
  691. void Reader::getLocationLineAndColumn(Location location, int& line,
  692. int& column) const {
  693. Location current = begin_;
  694. Location lastLineStart = current;
  695. line = 0;
  696. while (current < location && current != end_) {
  697. Char c = *current++;
  698. if (c == '\r') {
  699. if (current != end_ && *current == '\n')
  700. ++current;
  701. lastLineStart = current;
  702. ++line;
  703. } else if (c == '\n') {
  704. lastLineStart = current;
  705. ++line;
  706. }
  707. }
  708. // column & line start at 1
  709. column = int(location - lastLineStart) + 1;
  710. ++line;
  711. }
  712. String Reader::getLocationLineAndColumn(Location location) const {
  713. int line, column;
  714. getLocationLineAndColumn(location, line, column);
  715. char buffer[18 + 16 + 16 + 1];
  716. jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
  717. return buffer;
  718. }
  719. // Deprecated. Preserved for backward compatibility
  720. String Reader::getFormatedErrorMessages() const {
  721. return getFormattedErrorMessages();
  722. }
  723. String Reader::getFormattedErrorMessages() const {
  724. String formattedMessage;
  725. for (const auto& error : errors_) {
  726. formattedMessage +=
  727. "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
  728. formattedMessage += " " + error.message_ + "\n";
  729. if (error.extra_)
  730. formattedMessage +=
  731. "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
  732. }
  733. return formattedMessage;
  734. }
  735. std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
  736. std::vector<Reader::StructuredError> allErrors;
  737. for (const auto& error : errors_) {
  738. Reader::StructuredError structured;
  739. structured.offset_start = error.token_.start_ - begin_;
  740. structured.offset_limit = error.token_.end_ - begin_;
  741. structured.message = error.message_;
  742. allErrors.push_back(structured);
  743. }
  744. return allErrors;
  745. }
  746. bool Reader::pushError(const Value& value, const String& message) {
  747. ptrdiff_t const length = end_ - begin_;
  748. if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
  749. return false;
  750. Token token;
  751. token.type_ = tokenError;
  752. token.start_ = begin_ + value.getOffsetStart();
  753. token.end_ = begin_ + value.getOffsetLimit();
  754. ErrorInfo info;
  755. info.token_ = token;
  756. info.message_ = message;
  757. info.extra_ = nullptr;
  758. errors_.push_back(info);
  759. return true;
  760. }
  761. bool Reader::pushError(const Value& value, const String& message,
  762. const Value& extra) {
  763. ptrdiff_t const length = end_ - begin_;
  764. if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
  765. extra.getOffsetLimit() > length)
  766. return false;
  767. Token token;
  768. token.type_ = tokenError;
  769. token.start_ = begin_ + value.getOffsetStart();
  770. token.end_ = begin_ + value.getOffsetLimit();
  771. ErrorInfo info;
  772. info.token_ = token;
  773. info.message_ = message;
  774. info.extra_ = begin_ + extra.getOffsetStart();
  775. errors_.push_back(info);
  776. return true;
  777. }
  778. bool Reader::good() const { return errors_.empty(); }
  779. // Originally copied from the Features class (now deprecated), used internally
  780. // for features implementation.
  781. class OurFeatures {
  782. public:
  783. static OurFeatures all();
  784. bool allowComments_;
  785. bool allowTrailingCommas_;
  786. bool strictRoot_;
  787. bool allowDroppedNullPlaceholders_;
  788. bool allowNumericKeys_;
  789. bool allowSingleQuotes_;
  790. bool failIfExtra_;
  791. bool rejectDupKeys_;
  792. bool allowSpecialFloats_;
  793. bool skipBom_;
  794. size_t stackLimit_;
  795. }; // OurFeatures
  796. OurFeatures OurFeatures::all() { return {}; }
  797. // Implementation of class Reader
  798. // ////////////////////////////////
  799. // Originally copied from the Reader class (now deprecated), used internally
  800. // for implementing JSON reading.
  801. class OurReader {
  802. public:
  803. using Char = char;
  804. using Location = const Char*;
  805. explicit OurReader(OurFeatures const& features);
  806. bool parse(const char* beginDoc, const char* endDoc, Value& root,
  807. bool collectComments = true);
  808. String getFormattedErrorMessages() const;
  809. std::vector<CharReader::StructuredError> getStructuredErrors() const;
  810. private:
  811. OurReader(OurReader const&); // no impl
  812. void operator=(OurReader const&); // no impl
  813. enum TokenType {
  814. tokenEndOfStream = 0,
  815. tokenObjectBegin,
  816. tokenObjectEnd,
  817. tokenArrayBegin,
  818. tokenArrayEnd,
  819. tokenString,
  820. tokenNumber,
  821. tokenTrue,
  822. tokenFalse,
  823. tokenNull,
  824. tokenNaN,
  825. tokenPosInf,
  826. tokenNegInf,
  827. tokenArraySeparator,
  828. tokenMemberSeparator,
  829. tokenComment,
  830. tokenError
  831. };
  832. class Token {
  833. public:
  834. TokenType type_;
  835. Location start_;
  836. Location end_;
  837. };
  838. class ErrorInfo {
  839. public:
  840. Token token_;
  841. String message_;
  842. Location extra_;
  843. };
  844. using Errors = std::deque<ErrorInfo>;
  845. bool readToken(Token& token);
  846. bool readTokenSkippingComments(Token& token);
  847. void skipSpaces();
  848. void skipBom(bool skipBom);
  849. bool match(const Char* pattern, int patternLength);
  850. bool readComment();
  851. bool readCStyleComment(bool* containsNewLineResult);
  852. bool readCppStyleComment();
  853. bool readString();
  854. bool readStringSingleQuote();
  855. bool readNumber(bool checkInf);
  856. bool readValue();
  857. bool readObject(Token& token);
  858. bool readArray(Token& token);
  859. bool decodeNumber(Token& token);
  860. bool decodeNumber(Token& token, Value& decoded);
  861. bool decodeString(Token& token);
  862. bool decodeString(Token& token, String& decoded);
  863. bool decodeDouble(Token& token);
  864. bool decodeDouble(Token& token, Value& decoded);
  865. bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
  866. unsigned int& unicode);
  867. bool decodeUnicodeEscapeSequence(Token& token, Location& current,
  868. Location end, unsigned int& unicode);
  869. bool addError(const String& message, Token& token, Location extra = nullptr);
  870. bool recoverFromError(TokenType skipUntilToken);
  871. bool addErrorAndRecover(const String& message, Token& token,
  872. TokenType skipUntilToken);
  873. void skipUntilSpace();
  874. Value& currentValue();
  875. Char getNextChar();
  876. void getLocationLineAndColumn(Location location, int& line,
  877. int& column) const;
  878. String getLocationLineAndColumn(Location location) const;
  879. void addComment(Location begin, Location end, CommentPlacement placement);
  880. static String normalizeEOL(Location begin, Location end);
  881. static bool containsNewLine(Location begin, Location end);
  882. using Nodes = std::stack<Value*>;
  883. Nodes nodes_{};
  884. Errors errors_{};
  885. String document_{};
  886. Location begin_ = nullptr;
  887. Location end_ = nullptr;
  888. Location current_ = nullptr;
  889. Location lastValueEnd_ = nullptr;
  890. Value* lastValue_ = nullptr;
  891. bool lastValueHasAComment_ = false;
  892. String commentsBefore_{};
  893. OurFeatures const features_;
  894. bool collectComments_ = false;
  895. }; // OurReader
  896. // complete copy of Read impl, for OurReader
  897. bool OurReader::containsNewLine(OurReader::Location begin,
  898. OurReader::Location end) {
  899. return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
  900. }
  901. OurReader::OurReader(OurFeatures const& features) : features_(features) {}
  902. bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
  903. bool collectComments) {
  904. if (!features_.allowComments_) {
  905. collectComments = false;
  906. }
  907. begin_ = beginDoc;
  908. end_ = endDoc;
  909. collectComments_ = collectComments;
  910. current_ = begin_;
  911. lastValueEnd_ = nullptr;
  912. lastValue_ = nullptr;
  913. commentsBefore_.clear();
  914. errors_.clear();
  915. while (!nodes_.empty())
  916. nodes_.pop();
  917. nodes_.push(&root);
  918. // skip byte order mark if it exists at the beginning of the UTF-8 text.
  919. skipBom(features_.skipBom_);
  920. bool successful = readValue();
  921. nodes_.pop();
  922. Token token;
  923. readTokenSkippingComments(token);
  924. if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
  925. addError("Extra non-whitespace after JSON value.", token);
  926. return false;
  927. }
  928. if (collectComments_ && !commentsBefore_.empty())
  929. root.setComment(commentsBefore_, commentAfter);
  930. if (features_.strictRoot_) {
  931. if (!root.isArray() && !root.isObject()) {
  932. // Set error location to start of doc, ideally should be first token found
  933. // in doc
  934. token.type_ = tokenError;
  935. token.start_ = beginDoc;
  936. token.end_ = endDoc;
  937. addError(
  938. "A valid JSON document must be either an array or an object value.",
  939. token);
  940. return false;
  941. }
  942. }
  943. return successful;
  944. }
  945. bool OurReader::readValue() {
  946. // To preserve the old behaviour we cast size_t to int.
  947. if (nodes_.size() > features_.stackLimit_)
  948. throwRuntimeError("Exceeded stackLimit in readValue().");
  949. Token token;
  950. readTokenSkippingComments(token);
  951. bool successful = true;
  952. if (collectComments_ && !commentsBefore_.empty()) {
  953. currentValue().setComment(commentsBefore_, commentBefore);
  954. commentsBefore_.clear();
  955. }
  956. switch (token.type_) {
  957. case tokenObjectBegin:
  958. successful = readObject(token);
  959. currentValue().setOffsetLimit(current_ - begin_);
  960. break;
  961. case tokenArrayBegin:
  962. successful = readArray(token);
  963. currentValue().setOffsetLimit(current_ - begin_);
  964. break;
  965. case tokenNumber:
  966. successful = decodeNumber(token);
  967. break;
  968. case tokenString:
  969. successful = decodeString(token);
  970. break;
  971. case tokenTrue: {
  972. Value v(true);
  973. currentValue().swapPayload(v);
  974. currentValue().setOffsetStart(token.start_ - begin_);
  975. currentValue().setOffsetLimit(token.end_ - begin_);
  976. } break;
  977. case tokenFalse: {
  978. Value v(false);
  979. currentValue().swapPayload(v);
  980. currentValue().setOffsetStart(token.start_ - begin_);
  981. currentValue().setOffsetLimit(token.end_ - begin_);
  982. } break;
  983. case tokenNull: {
  984. Value v;
  985. currentValue().swapPayload(v);
  986. currentValue().setOffsetStart(token.start_ - begin_);
  987. currentValue().setOffsetLimit(token.end_ - begin_);
  988. } break;
  989. case tokenNaN: {
  990. Value v(std::numeric_limits<double>::quiet_NaN());
  991. currentValue().swapPayload(v);
  992. currentValue().setOffsetStart(token.start_ - begin_);
  993. currentValue().setOffsetLimit(token.end_ - begin_);
  994. } break;
  995. case tokenPosInf: {
  996. Value v(std::numeric_limits<double>::infinity());
  997. currentValue().swapPayload(v);
  998. currentValue().setOffsetStart(token.start_ - begin_);
  999. currentValue().setOffsetLimit(token.end_ - begin_);
  1000. } break;
  1001. case tokenNegInf: {
  1002. Value v(-std::numeric_limits<double>::infinity());
  1003. currentValue().swapPayload(v);
  1004. currentValue().setOffsetStart(token.start_ - begin_);
  1005. currentValue().setOffsetLimit(token.end_ - begin_);
  1006. } break;
  1007. case tokenArraySeparator:
  1008. case tokenObjectEnd:
  1009. case tokenArrayEnd:
  1010. if (features_.allowDroppedNullPlaceholders_) {
  1011. // "Un-read" the current token and mark the current value as a null
  1012. // token.
  1013. current_--;
  1014. Value v;
  1015. currentValue().swapPayload(v);
  1016. currentValue().setOffsetStart(current_ - begin_ - 1);
  1017. currentValue().setOffsetLimit(current_ - begin_);
  1018. break;
  1019. } // else, fall through ...
  1020. default:
  1021. currentValue().setOffsetStart(token.start_ - begin_);
  1022. currentValue().setOffsetLimit(token.end_ - begin_);
  1023. return addError("Syntax error: value, object or array expected.", token);
  1024. }
  1025. if (collectComments_) {
  1026. lastValueEnd_ = current_;
  1027. lastValueHasAComment_ = false;
  1028. lastValue_ = &currentValue();
  1029. }
  1030. return successful;
  1031. }
  1032. bool OurReader::readTokenSkippingComments(Token& token) {
  1033. bool success = readToken(token);
  1034. if (features_.allowComments_) {
  1035. while (success && token.type_ == tokenComment) {
  1036. success = readToken(token);
  1037. }
  1038. }
  1039. return success;
  1040. }
  1041. bool OurReader::readToken(Token& token) {
  1042. skipSpaces();
  1043. token.start_ = current_;
  1044. Char c = getNextChar();
  1045. bool ok = true;
  1046. switch (c) {
  1047. case '{':
  1048. token.type_ = tokenObjectBegin;
  1049. break;
  1050. case '}':
  1051. token.type_ = tokenObjectEnd;
  1052. break;
  1053. case '[':
  1054. token.type_ = tokenArrayBegin;
  1055. break;
  1056. case ']':
  1057. token.type_ = tokenArrayEnd;
  1058. break;
  1059. case '"':
  1060. token.type_ = tokenString;
  1061. ok = readString();
  1062. break;
  1063. case '\'':
  1064. if (features_.allowSingleQuotes_) {
  1065. token.type_ = tokenString;
  1066. ok = readStringSingleQuote();
  1067. } else {
  1068. // If we don't allow single quotes, this is a failure case.
  1069. ok = false;
  1070. }
  1071. break;
  1072. case '/':
  1073. token.type_ = tokenComment;
  1074. ok = readComment();
  1075. break;
  1076. case '0':
  1077. case '1':
  1078. case '2':
  1079. case '3':
  1080. case '4':
  1081. case '5':
  1082. case '6':
  1083. case '7':
  1084. case '8':
  1085. case '9':
  1086. token.type_ = tokenNumber;
  1087. readNumber(false);
  1088. break;
  1089. case '-':
  1090. if (readNumber(true)) {
  1091. token.type_ = tokenNumber;
  1092. } else {
  1093. token.type_ = tokenNegInf;
  1094. ok = features_.allowSpecialFloats_ && match("nfinity", 7);
  1095. }
  1096. break;
  1097. case '+':
  1098. if (readNumber(true)) {
  1099. token.type_ = tokenNumber;
  1100. } else {
  1101. token.type_ = tokenPosInf;
  1102. ok = features_.allowSpecialFloats_ && match("nfinity", 7);
  1103. }
  1104. break;
  1105. case 't':
  1106. token.type_ = tokenTrue;
  1107. ok = match("rue", 3);
  1108. break;
  1109. case 'f':
  1110. token.type_ = tokenFalse;
  1111. ok = match("alse", 4);
  1112. break;
  1113. case 'n':
  1114. token.type_ = tokenNull;
  1115. ok = match("ull", 3);
  1116. break;
  1117. case 'N':
  1118. if (features_.allowSpecialFloats_) {
  1119. token.type_ = tokenNaN;
  1120. ok = match("aN", 2);
  1121. } else {
  1122. ok = false;
  1123. }
  1124. break;
  1125. case 'I':
  1126. if (features_.allowSpecialFloats_) {
  1127. token.type_ = tokenPosInf;
  1128. ok = match("nfinity", 7);
  1129. } else {
  1130. ok = false;
  1131. }
  1132. break;
  1133. case ',':
  1134. token.type_ = tokenArraySeparator;
  1135. break;
  1136. case ':':
  1137. token.type_ = tokenMemberSeparator;
  1138. break;
  1139. case 0:
  1140. token.type_ = tokenEndOfStream;
  1141. break;
  1142. default:
  1143. ok = false;
  1144. break;
  1145. }
  1146. if (!ok)
  1147. token.type_ = tokenError;
  1148. token.end_ = current_;
  1149. return ok;
  1150. }
  1151. void OurReader::skipSpaces() {
  1152. while (current_ != end_) {
  1153. Char c = *current_;
  1154. if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
  1155. ++current_;
  1156. else
  1157. break;
  1158. }
  1159. }
  1160. void OurReader::skipBom(bool skipBom) {
  1161. // The default behavior is to skip BOM.
  1162. if (skipBom) {
  1163. if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
  1164. begin_ += 3;
  1165. current_ = begin_;
  1166. }
  1167. }
  1168. }
  1169. bool OurReader::match(const Char* pattern, int patternLength) {
  1170. if (end_ - current_ < patternLength)
  1171. return false;
  1172. int index = patternLength;
  1173. while (index--)
  1174. if (current_[index] != pattern[index])
  1175. return false;
  1176. current_ += patternLength;
  1177. return true;
  1178. }
  1179. bool OurReader::readComment() {
  1180. const Location commentBegin = current_ - 1;
  1181. const Char c = getNextChar();
  1182. bool successful = false;
  1183. bool cStyleWithEmbeddedNewline = false;
  1184. const bool isCStyleComment = (c == '*');
  1185. const bool isCppStyleComment = (c == '/');
  1186. if (isCStyleComment) {
  1187. successful = readCStyleComment(&cStyleWithEmbeddedNewline);
  1188. } else if (isCppStyleComment) {
  1189. successful = readCppStyleComment();
  1190. }
  1191. if (!successful)
  1192. return false;
  1193. if (collectComments_) {
  1194. CommentPlacement placement = commentBefore;
  1195. if (!lastValueHasAComment_) {
  1196. if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
  1197. if (isCppStyleComment || !cStyleWithEmbeddedNewline) {
  1198. placement = commentAfterOnSameLine;
  1199. lastValueHasAComment_ = true;
  1200. }
  1201. }
  1202. }
  1203. addComment(commentBegin, current_, placement);
  1204. }
  1205. return true;
  1206. }
  1207. String OurReader::normalizeEOL(OurReader::Location begin,
  1208. OurReader::Location end) {
  1209. String normalized;
  1210. normalized.reserve(static_cast<size_t>(end - begin));
  1211. OurReader::Location current = begin;
  1212. while (current != end) {
  1213. char c = *current++;
  1214. if (c == '\r') {
  1215. if (current != end && *current == '\n')
  1216. // convert dos EOL
  1217. ++current;
  1218. // convert Mac EOL
  1219. normalized += '\n';
  1220. } else {
  1221. normalized += c;
  1222. }
  1223. }
  1224. return normalized;
  1225. }
  1226. void OurReader::addComment(Location begin, Location end,
  1227. CommentPlacement placement) {
  1228. assert(collectComments_);
  1229. const String& normalized = normalizeEOL(begin, end);
  1230. if (placement == commentAfterOnSameLine) {
  1231. assert(lastValue_ != nullptr);
  1232. lastValue_->setComment(normalized, placement);
  1233. } else {
  1234. commentsBefore_ += normalized;
  1235. }
  1236. }
  1237. bool OurReader::readCStyleComment(bool* containsNewLineResult) {
  1238. *containsNewLineResult = false;
  1239. while ((current_ + 1) < end_) {
  1240. Char c = getNextChar();
  1241. if (c == '*' && *current_ == '/')
  1242. break;
  1243. if (c == '\n')
  1244. *containsNewLineResult = true;
  1245. }
  1246. return getNextChar() == '/';
  1247. }
  1248. bool OurReader::readCppStyleComment() {
  1249. while (current_ != end_) {
  1250. Char c = getNextChar();
  1251. if (c == '\n')
  1252. break;
  1253. if (c == '\r') {
  1254. // Consume DOS EOL. It will be normalized in addComment.
  1255. if (current_ != end_ && *current_ == '\n')
  1256. getNextChar();
  1257. // Break on Moc OS 9 EOL.
  1258. break;
  1259. }
  1260. }
  1261. return true;
  1262. }
  1263. bool OurReader::readNumber(bool checkInf) {
  1264. Location p = current_;
  1265. if (checkInf && p != end_ && *p == 'I') {
  1266. current_ = ++p;
  1267. return false;
  1268. }
  1269. char c = '0'; // stopgap for already consumed character
  1270. // integral part
  1271. while (c >= '0' && c <= '9')
  1272. c = (current_ = p) < end_ ? *p++ : '\0';
  1273. // fractional part
  1274. if (c == '.') {
  1275. c = (current_ = p) < end_ ? *p++ : '\0';
  1276. while (c >= '0' && c <= '9')
  1277. c = (current_ = p) < end_ ? *p++ : '\0';
  1278. }
  1279. // exponential part
  1280. if (c == 'e' || c == 'E') {
  1281. c = (current_ = p) < end_ ? *p++ : '\0';
  1282. if (c == '+' || c == '-')
  1283. c = (current_ = p) < end_ ? *p++ : '\0';
  1284. while (c >= '0' && c <= '9')
  1285. c = (current_ = p) < end_ ? *p++ : '\0';
  1286. }
  1287. return true;
  1288. }
  1289. bool OurReader::readString() {
  1290. Char c = 0;
  1291. while (current_ != end_) {
  1292. c = getNextChar();
  1293. if (c == '\\')
  1294. getNextChar();
  1295. else if (c == '"')
  1296. break;
  1297. }
  1298. return c == '"';
  1299. }
  1300. bool OurReader::readStringSingleQuote() {
  1301. Char c = 0;
  1302. while (current_ != end_) {
  1303. c = getNextChar();
  1304. if (c == '\\')
  1305. getNextChar();
  1306. else if (c == '\'')
  1307. break;
  1308. }
  1309. return c == '\'';
  1310. }
  1311. bool OurReader::readObject(Token& token) {
  1312. Token tokenName;
  1313. String name;
  1314. Value init(objectValue);
  1315. currentValue().swapPayload(init);
  1316. currentValue().setOffsetStart(token.start_ - begin_);
  1317. while (readTokenSkippingComments(tokenName)) {
  1318. if (tokenName.type_ == tokenObjectEnd &&
  1319. (name.empty() ||
  1320. features_.allowTrailingCommas_)) // empty object or trailing comma
  1321. return true;
  1322. name.clear();
  1323. if (tokenName.type_ == tokenString) {
  1324. if (!decodeString(tokenName, name))
  1325. return recoverFromError(tokenObjectEnd);
  1326. } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
  1327. Value numberName;
  1328. if (!decodeNumber(tokenName, numberName))
  1329. return recoverFromError(tokenObjectEnd);
  1330. name = numberName.asString();
  1331. } else {
  1332. break;
  1333. }
  1334. if (name.length() >= (1U << 30))
  1335. throwRuntimeError("keylength >= 2^30");
  1336. if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
  1337. String msg = "Duplicate key: '" + name + "'";
  1338. return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
  1339. }
  1340. Token colon;
  1341. if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
  1342. return addErrorAndRecover("Missing ':' after object member name", colon,
  1343. tokenObjectEnd);
  1344. }
  1345. Value& value = currentValue()[name];
  1346. nodes_.push(&value);
  1347. bool ok = readValue();
  1348. nodes_.pop();
  1349. if (!ok) // error already set
  1350. return recoverFromError(tokenObjectEnd);
  1351. Token comma;
  1352. if (!readTokenSkippingComments(comma) ||
  1353. (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) {
  1354. return addErrorAndRecover("Missing ',' or '}' in object declaration",
  1355. comma, tokenObjectEnd);
  1356. }
  1357. if (comma.type_ == tokenObjectEnd)
  1358. return true;
  1359. }
  1360. return addErrorAndRecover("Missing '}' or object member name", tokenName,
  1361. tokenObjectEnd);
  1362. }
  1363. bool OurReader::readArray(Token& token) {
  1364. Value init(arrayValue);
  1365. currentValue().swapPayload(init);
  1366. currentValue().setOffsetStart(token.start_ - begin_);
  1367. int index = 0;
  1368. for (;;) {
  1369. skipSpaces();
  1370. if (current_ != end_ && *current_ == ']' &&
  1371. (index == 0 ||
  1372. (features_.allowTrailingCommas_ &&
  1373. !features_.allowDroppedNullPlaceholders_))) // empty array or trailing
  1374. // comma
  1375. {
  1376. Token endArray;
  1377. readToken(endArray);
  1378. return true;
  1379. }
  1380. Value& value = currentValue()[index++];
  1381. nodes_.push(&value);
  1382. bool ok = readValue();
  1383. nodes_.pop();
  1384. if (!ok) // error already set
  1385. return recoverFromError(tokenArrayEnd);
  1386. Token currentToken;
  1387. // Accept Comment after last item in the array.
  1388. ok = readTokenSkippingComments(currentToken);
  1389. bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
  1390. currentToken.type_ != tokenArrayEnd);
  1391. if (!ok || badTokenType) {
  1392. return addErrorAndRecover("Missing ',' or ']' in array declaration",
  1393. currentToken, tokenArrayEnd);
  1394. }
  1395. if (currentToken.type_ == tokenArrayEnd)
  1396. break;
  1397. }
  1398. return true;
  1399. }
  1400. bool OurReader::decodeNumber(Token& token) {
  1401. Value decoded;
  1402. if (!decodeNumber(token, decoded))
  1403. return false;
  1404. currentValue().swapPayload(decoded);
  1405. currentValue().setOffsetStart(token.start_ - begin_);
  1406. currentValue().setOffsetLimit(token.end_ - begin_);
  1407. return true;
  1408. }
  1409. bool OurReader::decodeNumber(Token& token, Value& decoded) {
  1410. // Attempts to parse the number as an integer. If the number is
  1411. // larger than the maximum supported value of an integer then
  1412. // we decode the number as a double.
  1413. Location current = token.start_;
  1414. const bool isNegative = *current == '-';
  1415. if (isNegative) {
  1416. ++current;
  1417. }
  1418. // We assume we can represent the largest and smallest integer types as
  1419. // unsigned integers with separate sign. This is only true if they can fit
  1420. // into an unsigned integer.
  1421. static_assert(Value::maxLargestInt <= Value::maxLargestUInt,
  1422. "Int must be smaller than UInt");
  1423. // We need to convert minLargestInt into a positive number. The easiest way
  1424. // to do this conversion is to assume our "threshold" value of minLargestInt
  1425. // divided by 10 can fit in maxLargestInt when absolute valued. This should
  1426. // be a safe assumption.
  1427. static_assert(Value::minLargestInt <= -Value::maxLargestInt,
  1428. "The absolute value of minLargestInt must be greater than or "
  1429. "equal to maxLargestInt");
  1430. static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
  1431. "The absolute value of minLargestInt must be only 1 magnitude "
  1432. "larger than maxLargest Int");
  1433. static constexpr Value::LargestUInt positive_threshold =
  1434. Value::maxLargestUInt / 10;
  1435. static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10;
  1436. // For the negative values, we have to be more careful. Since typically
  1437. // -Value::minLargestInt will cause an overflow, we first divide by 10 and
  1438. // then take the inverse. This assumes that minLargestInt is only a single
  1439. // power of 10 different in magnitude, which we check above. For the last
  1440. // digit, we take the modulus before negating for the same reason.
  1441. static constexpr auto negative_threshold =
  1442. Value::LargestUInt(-(Value::minLargestInt / 10));
  1443. static constexpr auto negative_last_digit =
  1444. Value::UInt(-(Value::minLargestInt % 10));
  1445. const Value::LargestUInt threshold =
  1446. isNegative ? negative_threshold : positive_threshold;
  1447. const Value::UInt max_last_digit =
  1448. isNegative ? negative_last_digit : positive_last_digit;
  1449. Value::LargestUInt value = 0;
  1450. while (current < token.end_) {
  1451. Char c = *current++;
  1452. if (c < '0' || c > '9')
  1453. return decodeDouble(token, decoded);
  1454. const auto digit(static_cast<Value::UInt>(c - '0'));
  1455. if (value >= threshold) {
  1456. // We've hit or exceeded the max value divided by 10 (rounded down). If
  1457. // a) we've only just touched the limit, meaning value == threshold,
  1458. // b) this is the last digit, or
  1459. // c) it's small enough to fit in that rounding delta, we're okay.
  1460. // Otherwise treat this number as a double to avoid overflow.
  1461. if (value > threshold || current != token.end_ ||
  1462. digit > max_last_digit) {
  1463. return decodeDouble(token, decoded);
  1464. }
  1465. }
  1466. value = value * 10 + digit;
  1467. }
  1468. if (isNegative) {
  1469. // We use the same magnitude assumption here, just in case.
  1470. const auto last_digit = static_cast<Value::UInt>(value % 10);
  1471. decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
  1472. } else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
  1473. decoded = Value::LargestInt(value);
  1474. } else {
  1475. decoded = value;
  1476. }
  1477. return true;
  1478. }
  1479. bool OurReader::decodeDouble(Token& token) {
  1480. Value decoded;
  1481. if (!decodeDouble(token, decoded))
  1482. return false;
  1483. currentValue().swapPayload(decoded);
  1484. currentValue().setOffsetStart(token.start_ - begin_);
  1485. currentValue().setOffsetLimit(token.end_ - begin_);
  1486. return true;
  1487. }
  1488. bool OurReader::decodeDouble(Token& token, Value& decoded) {
  1489. double value = 0;
  1490. IStringStream is(String(token.start_, token.end_));
  1491. if (!(is >> value)) {
  1492. if (value == std::numeric_limits<double>::max())
  1493. value = std::numeric_limits<double>::infinity();
  1494. else if (value == std::numeric_limits<double>::lowest())
  1495. value = -std::numeric_limits<double>::infinity();
  1496. else if (!std::isinf(value))
  1497. return addError(
  1498. "'" + String(token.start_, token.end_) + "' is not a number.", token);
  1499. }
  1500. decoded = value;
  1501. return true;
  1502. }
  1503. bool OurReader::decodeString(Token& token) {
  1504. String decoded_string;
  1505. if (!decodeString(token, decoded_string))
  1506. return false;
  1507. Value decoded(decoded_string);
  1508. currentValue().swapPayload(decoded);
  1509. currentValue().setOffsetStart(token.start_ - begin_);
  1510. currentValue().setOffsetLimit(token.end_ - begin_);
  1511. return true;
  1512. }
  1513. bool OurReader::decodeString(Token& token, String& decoded) {
  1514. decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
  1515. Location current = token.start_ + 1; // skip '"'
  1516. Location end = token.end_ - 1; // do not include '"'
  1517. while (current != end) {
  1518. Char c = *current++;
  1519. if (c == '"')
  1520. break;
  1521. if (c == '\\') {
  1522. if (current == end)
  1523. return addError("Empty escape sequence in string", token, current);
  1524. Char escape = *current++;
  1525. switch (escape) {
  1526. case '"':
  1527. decoded += '"';
  1528. break;
  1529. case '/':
  1530. decoded += '/';
  1531. break;
  1532. case '\\':
  1533. decoded += '\\';
  1534. break;
  1535. case 'b':
  1536. decoded += '\b';
  1537. break;
  1538. case 'f':
  1539. decoded += '\f';
  1540. break;
  1541. case 'n':
  1542. decoded += '\n';
  1543. break;
  1544. case 'r':
  1545. decoded += '\r';
  1546. break;
  1547. case 't':
  1548. decoded += '\t';
  1549. break;
  1550. case 'u': {
  1551. unsigned int unicode;
  1552. if (!decodeUnicodeCodePoint(token, current, end, unicode))
  1553. return false;
  1554. decoded += codePointToUTF8(unicode);
  1555. } break;
  1556. default:
  1557. return addError("Bad escape sequence in string", token, current);
  1558. }
  1559. } else {
  1560. decoded += c;
  1561. }
  1562. }
  1563. return true;
  1564. }
  1565. bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
  1566. Location end, unsigned int& unicode) {
  1567. if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
  1568. return false;
  1569. if (unicode >= 0xD800 && unicode <= 0xDBFF) {
  1570. // surrogate pairs
  1571. if (end - current < 6)
  1572. return addError(
  1573. "additional six characters expected to parse unicode surrogate pair.",
  1574. token, current);
  1575. if (*(current++) == '\\' && *(current++) == 'u') {
  1576. unsigned int surrogatePair;
  1577. if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
  1578. unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
  1579. } else
  1580. return false;
  1581. } else
  1582. return addError("expecting another \\u token to begin the second half of "
  1583. "a unicode surrogate pair",
  1584. token, current);
  1585. }
  1586. return true;
  1587. }
  1588. bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
  1589. Location end,
  1590. unsigned int& ret_unicode) {
  1591. if (end - current < 4)
  1592. return addError(
  1593. "Bad unicode escape sequence in string: four digits expected.", token,
  1594. current);
  1595. int unicode = 0;
  1596. for (int index = 0; index < 4; ++index) {
  1597. Char c = *current++;
  1598. unicode *= 16;
  1599. if (c >= '0' && c <= '9')
  1600. unicode += c - '0';
  1601. else if (c >= 'a' && c <= 'f')
  1602. unicode += c - 'a' + 10;
  1603. else if (c >= 'A' && c <= 'F')
  1604. unicode += c - 'A' + 10;
  1605. else
  1606. return addError(
  1607. "Bad unicode escape sequence in string: hexadecimal digit expected.",
  1608. token, current);
  1609. }
  1610. ret_unicode = static_cast<unsigned int>(unicode);
  1611. return true;
  1612. }
  1613. bool OurReader::addError(const String& message, Token& token, Location extra) {
  1614. ErrorInfo info;
  1615. info.token_ = token;
  1616. info.message_ = message;
  1617. info.extra_ = extra;
  1618. errors_.push_back(info);
  1619. return false;
  1620. }
  1621. bool OurReader::recoverFromError(TokenType skipUntilToken) {
  1622. size_t errorCount = errors_.size();
  1623. Token skip;
  1624. for (;;) {
  1625. if (!readToken(skip))
  1626. errors_.resize(errorCount); // discard errors caused by recovery
  1627. if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
  1628. break;
  1629. }
  1630. errors_.resize(errorCount);
  1631. return false;
  1632. }
  1633. bool OurReader::addErrorAndRecover(const String& message, Token& token,
  1634. TokenType skipUntilToken) {
  1635. addError(message, token);
  1636. return recoverFromError(skipUntilToken);
  1637. }
  1638. Value& OurReader::currentValue() { return *(nodes_.top()); }
  1639. OurReader::Char OurReader::getNextChar() {
  1640. if (current_ == end_)
  1641. return 0;
  1642. return *current_++;
  1643. }
  1644. void OurReader::getLocationLineAndColumn(Location location, int& line,
  1645. int& column) const {
  1646. Location current = begin_;
  1647. Location lastLineStart = current;
  1648. line = 0;
  1649. while (current < location && current != end_) {
  1650. Char c = *current++;
  1651. if (c == '\r') {
  1652. if (current != end_ && *current == '\n')
  1653. ++current;
  1654. lastLineStart = current;
  1655. ++line;
  1656. } else if (c == '\n') {
  1657. lastLineStart = current;
  1658. ++line;
  1659. }
  1660. }
  1661. // column & line start at 1
  1662. column = int(location - lastLineStart) + 1;
  1663. ++line;
  1664. }
  1665. String OurReader::getLocationLineAndColumn(Location location) const {
  1666. int line, column;
  1667. getLocationLineAndColumn(location, line, column);
  1668. char buffer[18 + 16 + 16 + 1];
  1669. jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
  1670. return buffer;
  1671. }
  1672. String OurReader::getFormattedErrorMessages() const {
  1673. String formattedMessage;
  1674. for (const auto& error : errors_) {
  1675. formattedMessage +=
  1676. "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
  1677. formattedMessage += " " + error.message_ + "\n";
  1678. if (error.extra_)
  1679. formattedMessage +=
  1680. "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
  1681. }
  1682. return formattedMessage;
  1683. }
  1684. std::vector<CharReader::StructuredError>
  1685. OurReader::getStructuredErrors() const {
  1686. std::vector<CharReader::StructuredError> allErrors;
  1687. for (const auto& error : errors_) {
  1688. CharReader::StructuredError structured;
  1689. structured.offset_start = error.token_.start_ - begin_;
  1690. structured.offset_limit = error.token_.end_ - begin_;
  1691. structured.message = error.message_;
  1692. allErrors.push_back(structured);
  1693. }
  1694. return allErrors;
  1695. }
  1696. class OurCharReader : public CharReader {
  1697. public:
  1698. OurCharReader(bool collectComments, OurFeatures const& features)
  1699. : CharReader(
  1700. std::unique_ptr<OurImpl>(new OurImpl(collectComments, features))) {}
  1701. protected:
  1702. class OurImpl : public Impl {
  1703. public:
  1704. OurImpl(bool collectComments, OurFeatures const& features)
  1705. : collectComments_(collectComments), reader_(features) {}
  1706. bool parse(char const* beginDoc, char const* endDoc, Value* root,
  1707. String* errs) override {
  1708. bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
  1709. if (errs) {
  1710. *errs = reader_.getFormattedErrorMessages();
  1711. }
  1712. return ok;
  1713. }
  1714. std::vector<CharReader::StructuredError>
  1715. getStructuredErrors() const override {
  1716. return reader_.getStructuredErrors();
  1717. }
  1718. private:
  1719. bool const collectComments_;
  1720. OurReader reader_;
  1721. };
  1722. };
  1723. CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
  1724. CharReaderBuilder::~CharReaderBuilder() = default;
  1725. CharReader* CharReaderBuilder::newCharReader() const {
  1726. bool collectComments = settings_["collectComments"].asBool();
  1727. OurFeatures features = OurFeatures::all();
  1728. features.allowComments_ = settings_["allowComments"].asBool();
  1729. features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
  1730. features.strictRoot_ = settings_["strictRoot"].asBool();
  1731. features.allowDroppedNullPlaceholders_ =
  1732. settings_["allowDroppedNullPlaceholders"].asBool();
  1733. features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
  1734. features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
  1735. // Stack limit is always a size_t, so we get this as an unsigned int
  1736. // regardless of it we have 64-bit integer support enabled.
  1737. features.stackLimit_ = static_cast<size_t>(settings_["stackLimit"].asUInt());
  1738. features.failIfExtra_ = settings_["failIfExtra"].asBool();
  1739. features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
  1740. features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
  1741. features.skipBom_ = settings_["skipBom"].asBool();
  1742. return new OurCharReader(collectComments, features);
  1743. }
  1744. bool CharReaderBuilder::validate(Json::Value* invalid) const {
  1745. static const auto& valid_keys = *new std::set<String>{
  1746. "collectComments",
  1747. "allowComments",
  1748. "allowTrailingCommas",
  1749. "strictRoot",
  1750. "allowDroppedNullPlaceholders",
  1751. "allowNumericKeys",
  1752. "allowSingleQuotes",
  1753. "stackLimit",
  1754. "failIfExtra",
  1755. "rejectDupKeys",
  1756. "allowSpecialFloats",
  1757. "skipBom",
  1758. };
  1759. for (auto si = settings_.begin(); si != settings_.end(); ++si) {
  1760. auto key = si.name();
  1761. if (valid_keys.count(key))
  1762. continue;
  1763. if (invalid)
  1764. (*invalid)[key] = *si;
  1765. else
  1766. return false;
  1767. }
  1768. return invalid ? invalid->empty() : true;
  1769. }
  1770. Value& CharReaderBuilder::operator[](const String& key) {
  1771. return settings_[key];
  1772. }
  1773. // static
  1774. void CharReaderBuilder::strictMode(Json::Value* settings) {
  1775. //! [CharReaderBuilderStrictMode]
  1776. (*settings)["allowComments"] = false;
  1777. (*settings)["allowTrailingCommas"] = false;
  1778. (*settings)["strictRoot"] = true;
  1779. (*settings)["allowDroppedNullPlaceholders"] = false;
  1780. (*settings)["allowNumericKeys"] = false;
  1781. (*settings)["allowSingleQuotes"] = false;
  1782. (*settings)["stackLimit"] = 1000;
  1783. (*settings)["failIfExtra"] = true;
  1784. (*settings)["rejectDupKeys"] = true;
  1785. (*settings)["allowSpecialFloats"] = false;
  1786. (*settings)["skipBom"] = true;
  1787. //! [CharReaderBuilderStrictMode]
  1788. }
  1789. // static
  1790. void CharReaderBuilder::setDefaults(Json::Value* settings) {
  1791. //! [CharReaderBuilderDefaults]
  1792. (*settings)["collectComments"] = true;
  1793. (*settings)["allowComments"] = true;
  1794. (*settings)["allowTrailingCommas"] = true;
  1795. (*settings)["strictRoot"] = false;
  1796. (*settings)["allowDroppedNullPlaceholders"] = false;
  1797. (*settings)["allowNumericKeys"] = false;
  1798. (*settings)["allowSingleQuotes"] = false;
  1799. (*settings)["stackLimit"] = 1000;
  1800. (*settings)["failIfExtra"] = false;
  1801. (*settings)["rejectDupKeys"] = false;
  1802. (*settings)["allowSpecialFloats"] = false;
  1803. (*settings)["skipBom"] = true;
  1804. //! [CharReaderBuilderDefaults]
  1805. }
  1806. // static
  1807. void CharReaderBuilder::ecma404Mode(Json::Value* settings) {
  1808. //! [CharReaderBuilderECMA404Mode]
  1809. (*settings)["allowComments"] = false;
  1810. (*settings)["allowTrailingCommas"] = false;
  1811. (*settings)["strictRoot"] = false;
  1812. (*settings)["allowDroppedNullPlaceholders"] = false;
  1813. (*settings)["allowNumericKeys"] = false;
  1814. (*settings)["allowSingleQuotes"] = false;
  1815. (*settings)["stackLimit"] = 1000;
  1816. (*settings)["failIfExtra"] = true;
  1817. (*settings)["rejectDupKeys"] = false;
  1818. (*settings)["allowSpecialFloats"] = false;
  1819. (*settings)["skipBom"] = false;
  1820. //! [CharReaderBuilderECMA404Mode]
  1821. }
  1822. std::vector<CharReader::StructuredError>
  1823. CharReader::getStructuredErrors() const {
  1824. return _impl->getStructuredErrors();
  1825. }
  1826. bool CharReader::parse(char const* beginDoc, char const* endDoc, Value* root,
  1827. String* errs) {
  1828. return _impl->parse(beginDoc, endDoc, root, errs);
  1829. }
  1830. //////////////////////////////////
  1831. // global functions
  1832. bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
  1833. String* errs) {
  1834. OStringStream ssin;
  1835. ssin << sin.rdbuf();
  1836. String doc = std::move(ssin).str();
  1837. char const* begin = doc.data();
  1838. char const* end = begin + doc.size();
  1839. // Note that we do not actually need a null-terminator.
  1840. CharReaderPtr const reader(fact.newCharReader());
  1841. return reader->parse(begin, end, root, errs);
  1842. }
  1843. IStream& operator>>(IStream& sin, Value& root) {
  1844. CharReaderBuilder b;
  1845. String errs;
  1846. bool ok = parseFromStream(b, sin, &root, &errs);
  1847. if (!ok) {
  1848. throwRuntimeError(errs);
  1849. }
  1850. return sin;
  1851. }
  1852. } // namespace Json