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

995 lines
24 KiB

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