json_reader.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. #include "json/reader.h"
  2. #include "json/value.h"
  3. #include <utility>
  4. #include <cstdio>
  5. #include <cassert>
  6. #include <cstring>
  7. #include <iostream>
  8. #include <stdexcept>
  9. #if _MSC_VER >= 1400 // VC++ 8.0
  10. #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
  11. #endif
  12. namespace Json {
  13. // Implementation of class Features
  14. // ////////////////////////////////
  15. Features::Features()
  16. : allowComments_( true )
  17. , strictRoot_( false )
  18. {
  19. }
  20. Features
  21. Features::all()
  22. {
  23. return Features();
  24. }
  25. Features
  26. Features::strictMode()
  27. {
  28. Features features;
  29. features.allowComments_ = false;
  30. features.strictRoot_ = true;
  31. return features;
  32. }
  33. // Implementation of class Reader
  34. // ////////////////////////////////
  35. static inline bool
  36. in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
  37. {
  38. return c == c1 || c == c2 || c == c3 || c == c4;
  39. }
  40. static inline bool
  41. in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
  42. {
  43. return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
  44. }
  45. static bool
  46. containsNewLine( Reader::Location begin,
  47. Reader::Location end )
  48. {
  49. for ( ;begin < end; ++begin )
  50. if ( *begin == '\n' || *begin == '\r' )
  51. return true;
  52. return false;
  53. }
  54. static std::string codePointToUTF8(unsigned int cp)
  55. {
  56. std::string result;
  57. // based on description from http://en.wikipedia.org/wiki/UTF-8
  58. if (cp <= 0x7f)
  59. {
  60. result.resize(1);
  61. result[0] = static_cast<char>(cp);
  62. }
  63. else if (cp <= 0x7FF)
  64. {
  65. result.resize(2);
  66. result[1] = static_cast<char>(0x80 | (0x3f & cp));
  67. result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
  68. }
  69. else if (cp <= 0xFFFF)
  70. {
  71. result.resize(3);
  72. result[2] = static_cast<char>(0x80 | (0x3f & cp));
  73. result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
  74. result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
  75. }
  76. else if (cp <= 0x10FFFF)
  77. {
  78. result.resize(4);
  79. result[3] = static_cast<char>(0x80 | (0x3f & cp));
  80. result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
  81. result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
  82. result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
  83. }
  84. return result;
  85. }
  86. // Class Reader
  87. // //////////////////////////////////////////////////////////////////
  88. Reader::Reader()
  89. : features_( Features::all() )
  90. {
  91. }
  92. Reader::Reader( const Features &features )
  93. : features_( features )
  94. {
  95. }
  96. bool
  97. Reader::parse( const std::string &document,
  98. Value &root,
  99. bool collectComments )
  100. {
  101. document_ = document;
  102. const char *begin = document_.c_str();
  103. const char *end = begin + document_.length();
  104. return parse( begin, end, root, collectComments );
  105. }
  106. bool
  107. Reader::parse( std::istream& sin,
  108. Value &root,
  109. bool collectComments )
  110. {
  111. //std::istream_iterator<char> begin(sin);
  112. //std::istream_iterator<char> end;
  113. // Those would allow streamed input from a file, if parse() were a
  114. // template function.
  115. // Since std::string is reference-counted, this at least does not
  116. // create an extra copy.
  117. std::string doc;
  118. std::getline(sin, doc, (char)EOF);
  119. return parse( doc, root, collectComments );
  120. }
  121. bool
  122. Reader::parse( const char *beginDoc, const char *endDoc,
  123. Value &root,
  124. bool collectComments )
  125. {
  126. if ( !features_.allowComments_ )
  127. {
  128. collectComments = false;
  129. }
  130. begin_ = beginDoc;
  131. end_ = endDoc;
  132. collectComments_ = collectComments;
  133. current_ = begin_;
  134. lastValueEnd_ = 0;
  135. lastValue_ = 0;
  136. commentsBefore_ = "";
  137. errors_.clear();
  138. while ( !nodes_.empty() )
  139. nodes_.pop();
  140. nodes_.push( &root );
  141. bool successful = readValue();
  142. Token token;
  143. skipCommentTokens( token );
  144. if ( collectComments_ && !commentsBefore_.empty() )
  145. root.setComment( commentsBefore_, commentAfter );
  146. if ( features_.strictRoot_ )
  147. {
  148. if ( !root.isArray() && !root.isObject() )
  149. {
  150. // Set error location to start of doc, ideally should be first token found in doc
  151. token.type_ = tokenError;
  152. token.start_ = beginDoc;
  153. token.end_ = endDoc;
  154. addError( "A valid JSON document must be either an array or an object value.",
  155. token );
  156. return false;
  157. }
  158. }
  159. return successful;
  160. }
  161. bool
  162. Reader::readValue()
  163. {
  164. Token token;
  165. skipCommentTokens( token );
  166. bool successful = true;
  167. if ( collectComments_ && !commentsBefore_.empty() )
  168. {
  169. currentValue().setComment( commentsBefore_, commentBefore );
  170. commentsBefore_ = "";
  171. }
  172. switch ( token.type_ )
  173. {
  174. case tokenObjectBegin:
  175. successful = readObject( token );
  176. break;
  177. case tokenArrayBegin:
  178. successful = readArray( token );
  179. break;
  180. case tokenNumber:
  181. successful = decodeNumber( token );
  182. break;
  183. case tokenString:
  184. successful = decodeString( token );
  185. break;
  186. case tokenTrue:
  187. currentValue() = true;
  188. break;
  189. case tokenFalse:
  190. currentValue() = false;
  191. break;
  192. case tokenNull:
  193. currentValue() = Value();
  194. break;
  195. default:
  196. return addError( "Syntax error: value, object or array expected.", token );
  197. }
  198. if ( collectComments_ )
  199. {
  200. lastValueEnd_ = current_;
  201. lastValue_ = &currentValue();
  202. }
  203. return successful;
  204. }
  205. void
  206. Reader::skipCommentTokens( Token &token )
  207. {
  208. if ( features_.allowComments_ )
  209. {
  210. do
  211. {
  212. readToken( token );
  213. }
  214. while ( token.type_ == tokenComment );
  215. }
  216. else
  217. {
  218. readToken( token );
  219. }
  220. }
  221. bool
  222. Reader::expectToken( TokenType type, Token &token, const char *message )
  223. {
  224. readToken( token );
  225. if ( token.type_ != type )
  226. return addError( message, token );
  227. return true;
  228. }
  229. bool
  230. Reader::readToken( Token &token )
  231. {
  232. skipSpaces();
  233. token.start_ = current_;
  234. Char c = getNextChar();
  235. bool ok = true;
  236. switch ( c )
  237. {
  238. case '{':
  239. token.type_ = tokenObjectBegin;
  240. break;
  241. case '}':
  242. token.type_ = tokenObjectEnd;
  243. break;
  244. case '[':
  245. token.type_ = tokenArrayBegin;
  246. break;
  247. case ']':
  248. token.type_ = tokenArrayEnd;
  249. break;
  250. case '"':
  251. token.type_ = tokenString;
  252. ok = readString();
  253. break;
  254. case '/':
  255. token.type_ = tokenComment;
  256. ok = readComment();
  257. break;
  258. case '0':
  259. case '1':
  260. case '2':
  261. case '3':
  262. case '4':
  263. case '5':
  264. case '6':
  265. case '7':
  266. case '8':
  267. case '9':
  268. case '-':
  269. token.type_ = tokenNumber;
  270. readNumber();
  271. break;
  272. case 't':
  273. token.type_ = tokenTrue;
  274. ok = match( "rue", 3 );
  275. break;
  276. case 'f':
  277. token.type_ = tokenFalse;
  278. ok = match( "alse", 4 );
  279. break;
  280. case 'n':
  281. token.type_ = tokenNull;
  282. ok = match( "ull", 3 );
  283. break;
  284. case ',':
  285. token.type_ = tokenArraySeparator;
  286. break;
  287. case ':':
  288. token.type_ = tokenMemberSeparator;
  289. break;
  290. case 0:
  291. token.type_ = tokenEndOfStream;
  292. break;
  293. default:
  294. ok = false;
  295. break;
  296. }
  297. if ( !ok )
  298. token.type_ = tokenError;
  299. token.end_ = current_;
  300. return true;
  301. }
  302. void
  303. Reader::skipSpaces()
  304. {
  305. while ( current_ != end_ )
  306. {
  307. Char c = *current_;
  308. if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
  309. ++current_;
  310. else
  311. break;
  312. }
  313. }
  314. bool
  315. Reader::match( Location pattern,
  316. int patternLength )
  317. {
  318. if ( end_ - current_ < patternLength )
  319. return false;
  320. int index = patternLength;
  321. while ( index-- )
  322. if ( current_[index] != pattern[index] )
  323. return false;
  324. current_ += patternLength;
  325. return true;
  326. }
  327. bool
  328. Reader::readComment()
  329. {
  330. Location commentBegin = current_ - 1;
  331. Char c = getNextChar();
  332. bool successful = false;
  333. if ( c == '*' )
  334. successful = readCStyleComment();
  335. else if ( c == '/' )
  336. successful = readCppStyleComment();
  337. if ( !successful )
  338. return false;
  339. if ( collectComments_ )
  340. {
  341. CommentPlacement placement = commentBefore;
  342. if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
  343. {
  344. if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
  345. placement = commentAfterOnSameLine;
  346. }
  347. addComment( commentBegin, current_, placement );
  348. }
  349. return true;
  350. }
  351. void
  352. Reader::addComment( Location begin,
  353. Location end,
  354. CommentPlacement placement )
  355. {
  356. assert( collectComments_ );
  357. if ( placement == commentAfterOnSameLine )
  358. {
  359. assert( lastValue_ != 0 );
  360. lastValue_->setComment( std::string( begin, end ), placement );
  361. }
  362. else
  363. {
  364. if ( !commentsBefore_.empty() )
  365. commentsBefore_ += "\n";
  366. commentsBefore_ += std::string( begin, end );
  367. }
  368. }
  369. bool
  370. Reader::readCStyleComment()
  371. {
  372. while ( current_ != end_ )
  373. {
  374. Char c = getNextChar();
  375. if ( c == '*' && *current_ == '/' )
  376. break;
  377. }
  378. return getNextChar() == '/';
  379. }
  380. bool
  381. Reader::readCppStyleComment()
  382. {
  383. while ( current_ != end_ )
  384. {
  385. Char c = getNextChar();
  386. if ( c == '\r' || c == '\n' )
  387. break;
  388. }
  389. return true;
  390. }
  391. void
  392. Reader::readNumber()
  393. {
  394. while ( current_ != end_ )
  395. {
  396. if ( !(*current_ >= '0' && *current_ <= '9') &&
  397. !in( *current_, '.', 'e', 'E', '+', '-' ) )
  398. break;
  399. ++current_;
  400. }
  401. }
  402. bool
  403. Reader::readString()
  404. {
  405. Char c = 0;
  406. while ( current_ != end_ )
  407. {
  408. c = getNextChar();
  409. if ( c == '\\' )
  410. getNextChar();
  411. else if ( c == '"' )
  412. break;
  413. }
  414. return c == '"';
  415. }
  416. bool
  417. Reader::readObject( Token &tokenStart )
  418. {
  419. Token tokenName;
  420. std::string name;
  421. currentValue() = Value( objectValue );
  422. while ( readToken( tokenName ) )
  423. {
  424. bool initialTokenOk = true;
  425. while ( tokenName.type_ == tokenComment && initialTokenOk )
  426. initialTokenOk = readToken( tokenName );
  427. if ( !initialTokenOk )
  428. break;
  429. if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
  430. return true;
  431. if ( tokenName.type_ != tokenString )
  432. break;
  433. name = "";
  434. if ( !decodeString( tokenName, name ) )
  435. return recoverFromError( tokenObjectEnd );
  436. Token colon;
  437. if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
  438. {
  439. return addErrorAndRecover( "Missing ':' after object member name",
  440. colon,
  441. tokenObjectEnd );
  442. }
  443. Value &value = currentValue()[ name ];
  444. nodes_.push( &value );
  445. bool ok = readValue();
  446. nodes_.pop();
  447. if ( !ok ) // error already set
  448. return recoverFromError( tokenObjectEnd );
  449. Token comma;
  450. if ( !readToken( comma )
  451. || ( comma.type_ != tokenObjectEnd &&
  452. comma.type_ != tokenArraySeparator &&
  453. comma.type_ != tokenComment ) )
  454. {
  455. return addErrorAndRecover( "Missing ',' or '}' in object declaration",
  456. comma,
  457. tokenObjectEnd );
  458. }
  459. bool finalizeTokenOk = true;
  460. while ( comma.type_ == tokenComment &&
  461. finalizeTokenOk )
  462. finalizeTokenOk = readToken( comma );
  463. if ( comma.type_ == tokenObjectEnd )
  464. return true;
  465. }
  466. return addErrorAndRecover( "Missing '}' or object member name",
  467. tokenName,
  468. tokenObjectEnd );
  469. }
  470. bool
  471. Reader::readArray( Token &tokenStart )
  472. {
  473. currentValue() = Value( arrayValue );
  474. skipSpaces();
  475. if ( *current_ == ']' ) // empty array
  476. {
  477. Token endArray;
  478. readToken( endArray );
  479. return true;
  480. }
  481. int index = 0;
  482. while ( true )
  483. {
  484. Value &value = currentValue()[ index++ ];
  485. nodes_.push( &value );
  486. bool ok = readValue();
  487. nodes_.pop();
  488. if ( !ok ) // error already set
  489. return recoverFromError( tokenArrayEnd );
  490. Token token;
  491. // Accept Comment after last item in the array.
  492. ok = readToken( token );
  493. while ( token.type_ == tokenComment && ok )
  494. {
  495. ok = readToken( token );
  496. }
  497. bool badTokenType = ( token.type_ == tokenArraySeparator &&
  498. token.type_ == tokenArrayEnd );
  499. if ( !ok || badTokenType )
  500. {
  501. return addErrorAndRecover( "Missing ',' or ']' in array declaration",
  502. token,
  503. tokenArrayEnd );
  504. }
  505. if ( token.type_ == tokenArrayEnd )
  506. break;
  507. }
  508. return true;
  509. }
  510. bool
  511. Reader::decodeNumber( Token &token )
  512. {
  513. bool isDouble = false;
  514. for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
  515. {
  516. isDouble = isDouble
  517. || in( *inspect, '.', 'e', 'E', '+' )
  518. || ( *inspect == '-' && inspect != token.start_ );
  519. }
  520. if ( isDouble )
  521. return decodeDouble( token );
  522. Location current = token.start_;
  523. bool isNegative = *current == '-';
  524. if ( isNegative )
  525. ++current;
  526. Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt)
  527. : Value::maxUInt) / 10;
  528. Value::UInt value = 0;
  529. while ( current < token.end_ )
  530. {
  531. Char c = *current++;
  532. if ( c < '0' || c > '9' )
  533. return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
  534. if ( value >= threshold )
  535. return decodeDouble( token );
  536. value = value * 10 + Value::UInt(c - '0');
  537. }
  538. if ( isNegative )
  539. currentValue() = -Value::Int( value );
  540. else if ( value <= Value::UInt(Value::maxInt) )
  541. currentValue() = Value::Int( value );
  542. else
  543. currentValue() = value;
  544. return true;
  545. }
  546. bool
  547. Reader::decodeDouble( Token &token )
  548. {
  549. double value = 0;
  550. const int bufferSize = 32;
  551. int count;
  552. int length = int(token.end_ - token.start_);
  553. if ( length <= bufferSize )
  554. {
  555. Char buffer[bufferSize];
  556. memcpy( buffer, token.start_, length );
  557. buffer[length] = 0;
  558. count = sscanf( buffer, "%lf", &value );
  559. }
  560. else
  561. {
  562. std::string buffer( token.start_, token.end_ );
  563. count = sscanf( buffer.c_str(), "%lf", &value );
  564. }
  565. if ( count != 1 )
  566. return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
  567. currentValue() = value;
  568. return true;
  569. }
  570. bool
  571. Reader::decodeString( Token &token )
  572. {
  573. std::string decoded;
  574. if ( !decodeString( token, decoded ) )
  575. return false;
  576. currentValue() = decoded;
  577. return true;
  578. }
  579. bool
  580. Reader::decodeString( Token &token, std::string &decoded )
  581. {
  582. decoded.reserve( token.end_ - token.start_ - 2 );
  583. Location current = token.start_ + 1; // skip '"'
  584. Location end = token.end_ - 1; // do not include '"'
  585. while ( current != end )
  586. {
  587. Char c = *current++;
  588. if ( c == '"' )
  589. break;
  590. else if ( c == '\\' )
  591. {
  592. if ( current == end )
  593. return addError( "Empty escape sequence in string", token, current );
  594. Char escape = *current++;
  595. switch ( escape )
  596. {
  597. case '"': decoded += '"'; break;
  598. case '/': decoded += '/'; break;
  599. case '\\': decoded += '\\'; break;
  600. case 'b': decoded += '\b'; break;
  601. case 'f': decoded += '\f'; break;
  602. case 'n': decoded += '\n'; break;
  603. case 'r': decoded += '\r'; break;
  604. case 't': decoded += '\t'; break;
  605. case 'u':
  606. {
  607. unsigned int unicode;
  608. if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
  609. return false;
  610. decoded += codePointToUTF8(unicode);
  611. }
  612. break;
  613. default:
  614. return addError( "Bad escape sequence in string", token, current );
  615. }
  616. }
  617. else
  618. {
  619. decoded += c;
  620. }
  621. }
  622. return true;
  623. }
  624. bool
  625. Reader::decodeUnicodeCodePoint( Token &token,
  626. Location &current,
  627. Location end,
  628. unsigned int &unicode )
  629. {
  630. if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
  631. return false;
  632. if (unicode >= 0xD800 && unicode <= 0xDBFF)
  633. {
  634. // surrogate pairs
  635. if (end - current < 6)
  636. return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
  637. unsigned int surrogatePair;
  638. if (*(current++) == '\\' && *(current++)== 'u')
  639. {
  640. if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
  641. {
  642. unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
  643. }
  644. else
  645. return false;
  646. }
  647. else
  648. return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
  649. }
  650. return true;
  651. }
  652. bool
  653. Reader::decodeUnicodeEscapeSequence( Token &token,
  654. Location &current,
  655. Location end,
  656. unsigned int &unicode )
  657. {
  658. if ( end - current < 4 )
  659. return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
  660. unicode = 0;
  661. for ( int index =0; index < 4; ++index )
  662. {
  663. Char c = *current++;
  664. unicode *= 16;
  665. if ( c >= '0' && c <= '9' )
  666. unicode += c - '0';
  667. else if ( c >= 'a' && c <= 'f' )
  668. unicode += c - 'a' + 10;
  669. else if ( c >= 'A' && c <= 'F' )
  670. unicode += c - 'A' + 10;
  671. else
  672. return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
  673. }
  674. return true;
  675. }
  676. bool
  677. Reader::addError( const std::string &message,
  678. Token &token,
  679. Location extra )
  680. {
  681. ErrorInfo info;
  682. info.token_ = token;
  683. info.message_ = message;
  684. info.extra_ = extra;
  685. errors_.push_back( info );
  686. return false;
  687. }
  688. bool
  689. Reader::recoverFromError( TokenType skipUntilToken )
  690. {
  691. int errorCount = int(errors_.size());
  692. Token skip;
  693. while ( true )
  694. {
  695. if ( !readToken(skip) )
  696. errors_.resize( errorCount ); // discard errors caused by recovery
  697. if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
  698. break;
  699. }
  700. errors_.resize( errorCount );
  701. return false;
  702. }
  703. bool
  704. Reader::addErrorAndRecover( const std::string &message,
  705. Token &token,
  706. TokenType skipUntilToken )
  707. {
  708. addError( message, token );
  709. return recoverFromError( skipUntilToken );
  710. }
  711. Value &
  712. Reader::currentValue()
  713. {
  714. return *(nodes_.top());
  715. }
  716. Reader::Char
  717. Reader::getNextChar()
  718. {
  719. if ( current_ == end_ )
  720. return 0;
  721. return *current_++;
  722. }
  723. void
  724. Reader::getLocationLineAndColumn( Location location,
  725. int &line,
  726. int &column ) const
  727. {
  728. Location current = begin_;
  729. Location lastLineStart = current;
  730. line = 0;
  731. while ( current < location && current != end_ )
  732. {
  733. Char c = *current++;
  734. if ( c == '\r' )
  735. {
  736. if ( *current == '\n' )
  737. ++current;
  738. lastLineStart = current;
  739. ++line;
  740. }
  741. else if ( c == '\n' )
  742. {
  743. lastLineStart = current;
  744. ++line;
  745. }
  746. }
  747. // column & line start at 1
  748. column = int(location - lastLineStart) + 1;
  749. ++line;
  750. }
  751. std::string
  752. Reader::getLocationLineAndColumn( Location location ) const
  753. {
  754. int line, column;
  755. getLocationLineAndColumn( location, line, column );
  756. char buffer[18+16+16+1];
  757. sprintf( buffer, "Line %d, Column %d", line, column );
  758. return buffer;
  759. }
  760. std::string
  761. Reader::getFormatedErrorMessages() const
  762. {
  763. std::string formattedMessage;
  764. for ( Errors::const_iterator itError = errors_.begin();
  765. itError != errors_.end();
  766. ++itError )
  767. {
  768. const ErrorInfo &error = *itError;
  769. formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
  770. formattedMessage += " " + error.message_ + "\n";
  771. if ( error.extra_ )
  772. formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
  773. }
  774. return formattedMessage;
  775. }
  776. std::istream& operator>>( std::istream &sin, Value &root )
  777. {
  778. Json::Reader reader;
  779. bool ok = reader.parse(sin, root, true);
  780. //JSON_ASSERT( ok );
  781. if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
  782. return sin;
  783. }
  784. } // namespace Json