json_reader.cpp 57 KB

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