诸暨麻将添加redis
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

831 行
20 KiB

  1. # include "stdafx.h"
  2. #include "writer.h"
  3. #include <utility>
  4. #include <assert.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <iostream>
  8. #include <sstream>
  9. #include <iomanip>
  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. static bool isControlCharacter(char ch)
  15. {
  16. return ch > 0 && ch <= 0x1F;
  17. }
  18. static bool containsControlCharacter( const char* str )
  19. {
  20. while ( *str )
  21. {
  22. if ( isControlCharacter( *(str++) ) )
  23. return true;
  24. }
  25. return false;
  26. }
  27. static void uintToString( unsigned int value,
  28. char *&current )
  29. {
  30. *--current = 0;
  31. do
  32. {
  33. *--current = (value % 10) + '0';
  34. value /= 10;
  35. }
  36. while ( value != 0 );
  37. }
  38. std::string valueToString( Int value )
  39. {
  40. char buffer[32];
  41. char *current = buffer + sizeof(buffer);
  42. bool isNegative = value < 0;
  43. if ( isNegative )
  44. value = -value;
  45. uintToString( UInt(value), current );
  46. if ( isNegative )
  47. *--current = '-';
  48. assert( current >= buffer );
  49. return current;
  50. }
  51. std::string valueToString( UInt value )
  52. {
  53. char buffer[32];
  54. char *current = buffer + sizeof(buffer);
  55. uintToString( value, current );
  56. assert( current >= buffer );
  57. return current;
  58. }
  59. std::string valueToString( double value )
  60. {
  61. char buffer[32];
  62. #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
  63. sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
  64. #else
  65. sprintf(buffer, "%#.16g", value);
  66. #endif
  67. char* ch = buffer + strlen(buffer) - 1;
  68. if (*ch != '0') return buffer; // nothing to truncate, so save time
  69. while(ch > buffer && *ch == '0'){
  70. --ch;
  71. }
  72. char* last_nonzero = ch;
  73. while(ch >= buffer){
  74. switch(*ch){
  75. case '0':
  76. case '1':
  77. case '2':
  78. case '3':
  79. case '4':
  80. case '5':
  81. case '6':
  82. case '7':
  83. case '8':
  84. case '9':
  85. --ch;
  86. continue;
  87. case '.':
  88. // Truncate zeroes to save bytes in output, but keep one.
  89. *(last_nonzero+2) = '\0';
  90. return buffer;
  91. default:
  92. return buffer;
  93. }
  94. }
  95. return buffer;
  96. }
  97. std::string valueToString( bool value )
  98. {
  99. return value ? "true" : "false";
  100. }
  101. std::string valueToQuotedString( const char *value )
  102. {
  103. // Not sure how to handle unicode...
  104. if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
  105. return std::string("\"") + value + "\"";
  106. // We have to walk value and escape any special characters.
  107. // Appending to std::string is not efficient, but this should be rare.
  108. // (Note: forward slashes are *not* rare, but I am not escaping them.)
  109. unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
  110. std::string result;
  111. result.reserve(maxsize); // to avoid lots of mallocs
  112. result += "\"";
  113. for (const char* c=value; *c != 0; ++c)
  114. {
  115. switch(*c)
  116. {
  117. case '\"':
  118. result += "\\\"";
  119. break;
  120. case '\\':
  121. result += "\\\\";
  122. break;
  123. case '\b':
  124. result += "\\b";
  125. break;
  126. case '\f':
  127. result += "\\f";
  128. break;
  129. case '\n':
  130. result += "\\n";
  131. break;
  132. case '\r':
  133. result += "\\r";
  134. break;
  135. case '\t':
  136. result += "\\t";
  137. break;
  138. //case '/':
  139. // Even though \/ is considered a legal escape in JSON, a bare
  140. // slash is also legal, so I see no reason to escape it.
  141. // (I hope I am not misunderstanding something.
  142. // blep notes: actually escaping \/ may be useful in javascript to avoid </
  143. // sequence.
  144. // Should add a flag to allow this compatibility mode and prevent this
  145. // sequence from occurring.
  146. default:
  147. if ( isControlCharacter( *c ) )
  148. {
  149. std::ostringstream oss;
  150. oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
  151. result += oss.str();
  152. }
  153. else
  154. {
  155. result += *c;
  156. }
  157. break;
  158. }
  159. }
  160. result += "\"";
  161. return result;
  162. }
  163. // Class Writer
  164. // //////////////////////////////////////////////////////////////////
  165. Writer::~Writer()
  166. {
  167. }
  168. // Class FastWriter
  169. // //////////////////////////////////////////////////////////////////
  170. FastWriter::FastWriter()
  171. : yamlCompatiblityEnabled_( false )
  172. {
  173. }
  174. void
  175. FastWriter::enableYAMLCompatibility()
  176. {
  177. yamlCompatiblityEnabled_ = true;
  178. }
  179. std::string
  180. FastWriter::write( const Value &root )
  181. {
  182. document_ = "";
  183. writeValue( root );
  184. document_ += "\n";
  185. return document_;
  186. }
  187. void
  188. FastWriter::writeValue( const Value &value )
  189. {
  190. switch ( value.type() )
  191. {
  192. case nullValue:
  193. document_ += "null";
  194. break;
  195. case intValue:
  196. document_ += valueToString( value.asInt() );
  197. break;
  198. case uintValue:
  199. document_ += valueToString( value.asUInt() );
  200. break;
  201. case realValue:
  202. document_ += valueToString( value.asDouble() );
  203. break;
  204. case stringValue:
  205. document_ += valueToQuotedString( value.asCString() );
  206. break;
  207. case booleanValue:
  208. document_ += valueToString( value.asBool() );
  209. break;
  210. case arrayValue:
  211. {
  212. document_ += "[";
  213. int size = value.size();
  214. for ( int index =0; index < size; ++index )
  215. {
  216. if ( index > 0 )
  217. document_ += ",";
  218. writeValue( value[index] );
  219. }
  220. document_ += "]";
  221. }
  222. break;
  223. case objectValue:
  224. {
  225. Value::Members members( value.getMemberNames() );
  226. document_ += "{";
  227. for ( Value::Members::iterator it = members.begin();
  228. it != members.end();
  229. ++it )
  230. {
  231. const std::string &name = *it;
  232. if ( it != members.begin() )
  233. document_ += ",";
  234. document_ += valueToQuotedString( name.c_str() );
  235. document_ += yamlCompatiblityEnabled_ ? ": "
  236. : ":";
  237. writeValue( value[name] );
  238. }
  239. document_ += "}";
  240. }
  241. break;
  242. }
  243. }
  244. // Class StyledWriter
  245. // //////////////////////////////////////////////////////////////////
  246. StyledWriter::StyledWriter()
  247. : rightMargin_( 74 )
  248. , indentSize_( 3 )
  249. {
  250. }
  251. std::string
  252. StyledWriter::write( const Value &root )
  253. {
  254. document_ = "";
  255. addChildValues_ = false;
  256. indentString_ = "";
  257. writeCommentBeforeValue( root );
  258. writeValue( root );
  259. writeCommentAfterValueOnSameLine( root );
  260. document_ += "\n";
  261. return document_;
  262. }
  263. void
  264. StyledWriter::writeValue( const Value &value )
  265. {
  266. switch ( value.type() )
  267. {
  268. case nullValue:
  269. pushValue( "null" );
  270. break;
  271. case intValue:
  272. pushValue( valueToString( value.asInt() ) );
  273. break;
  274. case uintValue:
  275. pushValue( valueToString( value.asUInt() ) );
  276. break;
  277. case realValue:
  278. pushValue( valueToString( value.asDouble() ) );
  279. break;
  280. case stringValue:
  281. pushValue( valueToQuotedString( value.asCString() ) );
  282. break;
  283. case booleanValue:
  284. pushValue( valueToString( value.asBool() ) );
  285. break;
  286. case arrayValue:
  287. writeArrayValue( value);
  288. break;
  289. case objectValue:
  290. {
  291. Value::Members members( value.getMemberNames() );
  292. if ( members.empty() )
  293. pushValue( "{}" );
  294. else
  295. {
  296. writeWithIndent( "{" );
  297. indent();
  298. Value::Members::iterator it = members.begin();
  299. while ( true )
  300. {
  301. const std::string &name = *it;
  302. const Value &childValue = value[name];
  303. writeCommentBeforeValue( childValue );
  304. writeWithIndent( valueToQuotedString( name.c_str() ) );
  305. document_ += " : ";
  306. writeValue( childValue );
  307. if ( ++it == members.end() )
  308. {
  309. writeCommentAfterValueOnSameLine( childValue );
  310. break;
  311. }
  312. document_ += ",";
  313. writeCommentAfterValueOnSameLine( childValue );
  314. }
  315. unindent();
  316. writeWithIndent( "}" );
  317. }
  318. }
  319. break;
  320. }
  321. }
  322. void
  323. StyledWriter::writeArrayValue( const Value &value )
  324. {
  325. unsigned size = value.size();
  326. if ( size == 0 )
  327. pushValue( "[]" );
  328. else
  329. {
  330. bool isArrayMultiLine = isMultineArray( value );
  331. if ( isArrayMultiLine )
  332. {
  333. writeWithIndent( "[" );
  334. indent();
  335. bool hasChildValue = !childValues_.empty();
  336. unsigned index =0;
  337. while ( true )
  338. {
  339. const Value &childValue = value[index];
  340. writeCommentBeforeValue( childValue );
  341. if ( hasChildValue )
  342. writeWithIndent( childValues_[index] );
  343. else
  344. {
  345. writeIndent();
  346. writeValue( childValue );
  347. }
  348. if ( ++index == size )
  349. {
  350. writeCommentAfterValueOnSameLine( childValue );
  351. break;
  352. }
  353. document_ += ",";
  354. writeCommentAfterValueOnSameLine( childValue );
  355. }
  356. unindent();
  357. writeWithIndent( "]" );
  358. }
  359. else // output on a single line
  360. {
  361. assert( childValues_.size() == size );
  362. document_ += "[ ";
  363. for ( unsigned index =0; index < size; ++index )
  364. {
  365. if ( index > 0 )
  366. document_ += ", ";
  367. document_ += childValues_[index];
  368. }
  369. document_ += " ]";
  370. }
  371. }
  372. }
  373. bool
  374. StyledWriter::isMultineArray( const Value &value )
  375. {
  376. int size = value.size();
  377. bool isMultiLine = size*3 >= rightMargin_ ;
  378. childValues_.clear();
  379. for ( int index =0; index < size && !isMultiLine; ++index )
  380. {
  381. const Value &childValue = value[index];
  382. isMultiLine = isMultiLine ||
  383. ( (childValue.isArray() || childValue.isObject()) &&
  384. childValue.size() > 0 );
  385. }
  386. if ( !isMultiLine ) // check if line length > max line length
  387. {
  388. childValues_.reserve( size );
  389. addChildValues_ = true;
  390. int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
  391. for ( int index =0; index < size && !isMultiLine; ++index )
  392. {
  393. writeValue( value[index] );
  394. lineLength += int( childValues_[index].length() );
  395. isMultiLine = isMultiLine && hasCommentForValue( value[index] );
  396. }
  397. addChildValues_ = false;
  398. isMultiLine = isMultiLine || lineLength >= rightMargin_;
  399. }
  400. return isMultiLine;
  401. }
  402. void
  403. StyledWriter::pushValue( const std::string &value )
  404. {
  405. if ( addChildValues_ )
  406. childValues_.push_back( value );
  407. else
  408. document_ += value;
  409. }
  410. void
  411. StyledWriter::writeIndent()
  412. {
  413. if ( !document_.empty() )
  414. {
  415. char last = document_[document_.length()-1];
  416. if ( last == ' ' ) // already indented
  417. return;
  418. if ( last != '\n' ) // Comments may add new-line
  419. document_ += '\n';
  420. }
  421. document_ += indentString_;
  422. }
  423. void
  424. StyledWriter::writeWithIndent( const std::string &value )
  425. {
  426. writeIndent();
  427. document_ += value;
  428. }
  429. void
  430. StyledWriter::indent()
  431. {
  432. indentString_ += std::string( indentSize_, ' ' );
  433. }
  434. void
  435. StyledWriter::unindent()
  436. {
  437. assert( int(indentString_.size()) >= indentSize_ );
  438. indentString_.resize( indentString_.size() - indentSize_ );
  439. }
  440. void
  441. StyledWriter::writeCommentBeforeValue( const Value &root )
  442. {
  443. if ( !root.hasComment( commentBefore ) )
  444. return;
  445. document_ += normalizeEOL( root.getComment( commentBefore ) );
  446. document_ += "\n";
  447. }
  448. void
  449. StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
  450. {
  451. if ( root.hasComment( commentAfterOnSameLine ) )
  452. document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
  453. if ( root.hasComment( commentAfter ) )
  454. {
  455. document_ += "\n";
  456. document_ += normalizeEOL( root.getComment( commentAfter ) );
  457. document_ += "\n";
  458. }
  459. }
  460. bool
  461. StyledWriter::hasCommentForValue( const Value &value )
  462. {
  463. return value.hasComment( commentBefore )
  464. || value.hasComment( commentAfterOnSameLine )
  465. || value.hasComment( commentAfter );
  466. }
  467. std::string
  468. StyledWriter::normalizeEOL( const std::string &text )
  469. {
  470. std::string normalized;
  471. normalized.reserve( text.length() );
  472. const char *begin = text.c_str();
  473. const char *end = begin + text.length();
  474. const char *current = begin;
  475. while ( current != end )
  476. {
  477. char c = *current++;
  478. if ( c == '\r' ) // mac or dos EOL
  479. {
  480. if ( *current == '\n' ) // convert dos EOL
  481. ++current;
  482. normalized += '\n';
  483. }
  484. else // handle unix EOL & other char
  485. normalized += c;
  486. }
  487. return normalized;
  488. }
  489. // Class StyledStreamWriter
  490. // //////////////////////////////////////////////////////////////////
  491. StyledStreamWriter::StyledStreamWriter( std::string indentation )
  492. : document_(NULL)
  493. , rightMargin_( 74 )
  494. , indentation_( indentation )
  495. {
  496. }
  497. void
  498. StyledStreamWriter::write( std::ostream &out, const Value &root )
  499. {
  500. document_ = &out;
  501. addChildValues_ = false;
  502. indentString_ = "";
  503. writeCommentBeforeValue( root );
  504. writeValue( root );
  505. writeCommentAfterValueOnSameLine( root );
  506. *document_ << "\n";
  507. document_ = NULL; // Forget the stream, for safety.
  508. }
  509. void
  510. StyledStreamWriter::writeValue( const Value &value )
  511. {
  512. switch ( value.type() )
  513. {
  514. case nullValue:
  515. pushValue( "null" );
  516. break;
  517. case intValue:
  518. pushValue( valueToString( value.asInt() ) );
  519. break;
  520. case uintValue:
  521. pushValue( valueToString( value.asUInt() ) );
  522. break;
  523. case realValue:
  524. pushValue( valueToString( value.asDouble() ) );
  525. break;
  526. case stringValue:
  527. pushValue( valueToQuotedString( value.asCString() ) );
  528. break;
  529. case booleanValue:
  530. pushValue( valueToString( value.asBool() ) );
  531. break;
  532. case arrayValue:
  533. writeArrayValue( value);
  534. break;
  535. case objectValue:
  536. {
  537. Value::Members members( value.getMemberNames() );
  538. if ( members.empty() )
  539. pushValue( "{}" );
  540. else
  541. {
  542. writeWithIndent( "{" );
  543. indent();
  544. Value::Members::iterator it = members.begin();
  545. while ( true )
  546. {
  547. const std::string &name = *it;
  548. const Value &childValue = value[name];
  549. writeCommentBeforeValue( childValue );
  550. writeWithIndent( valueToQuotedString( name.c_str() ) );
  551. *document_ << " : ";
  552. writeValue( childValue );
  553. if ( ++it == members.end() )
  554. {
  555. writeCommentAfterValueOnSameLine( childValue );
  556. break;
  557. }
  558. *document_ << ",";
  559. writeCommentAfterValueOnSameLine( childValue );
  560. }
  561. unindent();
  562. writeWithIndent( "}" );
  563. }
  564. }
  565. break;
  566. }
  567. }
  568. void
  569. StyledStreamWriter::writeArrayValue( const Value &value )
  570. {
  571. unsigned size = value.size();
  572. if ( size == 0 )
  573. pushValue( "[]" );
  574. else
  575. {
  576. bool isArrayMultiLine = isMultineArray( value );
  577. if ( isArrayMultiLine )
  578. {
  579. writeWithIndent( "[" );
  580. indent();
  581. bool hasChildValue = !childValues_.empty();
  582. unsigned index =0;
  583. while ( true )
  584. {
  585. const Value &childValue = value[index];
  586. writeCommentBeforeValue( childValue );
  587. if ( hasChildValue )
  588. writeWithIndent( childValues_[index] );
  589. else
  590. {
  591. writeIndent();
  592. writeValue( childValue );
  593. }
  594. if ( ++index == size )
  595. {
  596. writeCommentAfterValueOnSameLine( childValue );
  597. break;
  598. }
  599. *document_ << ",";
  600. writeCommentAfterValueOnSameLine( childValue );
  601. }
  602. unindent();
  603. writeWithIndent( "]" );
  604. }
  605. else // output on a single line
  606. {
  607. assert( childValues_.size() == size );
  608. *document_ << "[ ";
  609. for ( unsigned index =0; index < size; ++index )
  610. {
  611. if ( index > 0 )
  612. *document_ << ", ";
  613. *document_ << childValues_[index];
  614. }
  615. *document_ << " ]";
  616. }
  617. }
  618. }
  619. bool
  620. StyledStreamWriter::isMultineArray( const Value &value )
  621. {
  622. int size = value.size();
  623. bool isMultiLine = size*3 >= rightMargin_ ;
  624. childValues_.clear();
  625. for ( int index =0; index < size && !isMultiLine; ++index )
  626. {
  627. const Value &childValue = value[index];
  628. isMultiLine = isMultiLine ||
  629. ( (childValue.isArray() || childValue.isObject()) &&
  630. childValue.size() > 0 );
  631. }
  632. if ( !isMultiLine ) // check if line length > max line length
  633. {
  634. childValues_.reserve( size );
  635. addChildValues_ = true;
  636. int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
  637. for ( int index =0; index < size && !isMultiLine; ++index )
  638. {
  639. writeValue( value[index] );
  640. lineLength += int( childValues_[index].length() );
  641. isMultiLine = isMultiLine && hasCommentForValue( value[index] );
  642. }
  643. addChildValues_ = false;
  644. isMultiLine = isMultiLine || lineLength >= rightMargin_;
  645. }
  646. return isMultiLine;
  647. }
  648. void
  649. StyledStreamWriter::pushValue( const std::string &value )
  650. {
  651. if ( addChildValues_ )
  652. childValues_.push_back( value );
  653. else
  654. *document_ << value;
  655. }
  656. void
  657. StyledStreamWriter::writeIndent()
  658. {
  659. /*
  660. Some comments in this method would have been nice. ;-)
  661. if ( !document_.empty() )
  662. {
  663. char last = document_[document_.length()-1];
  664. if ( last == ' ' ) // already indented
  665. return;
  666. if ( last != '\n' ) // Comments may add new-line
  667. *document_ << '\n';
  668. }
  669. */
  670. *document_ << '\n' << indentString_;
  671. }
  672. void
  673. StyledStreamWriter::writeWithIndent( const std::string &value )
  674. {
  675. writeIndent();
  676. *document_ << value;
  677. }
  678. void
  679. StyledStreamWriter::indent()
  680. {
  681. indentString_ += indentation_;
  682. }
  683. void
  684. StyledStreamWriter::unindent()
  685. {
  686. assert( indentString_.size() >= indentation_.size() );
  687. indentString_.resize( indentString_.size() - indentation_.size() );
  688. }
  689. void
  690. StyledStreamWriter::writeCommentBeforeValue( const Value &root )
  691. {
  692. if ( !root.hasComment( commentBefore ) )
  693. return;
  694. *document_ << normalizeEOL( root.getComment( commentBefore ) );
  695. *document_ << "\n";
  696. }
  697. void
  698. StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
  699. {
  700. if ( root.hasComment( commentAfterOnSameLine ) )
  701. *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
  702. if ( root.hasComment( commentAfter ) )
  703. {
  704. *document_ << "\n";
  705. *document_ << normalizeEOL( root.getComment( commentAfter ) );
  706. *document_ << "\n";
  707. }
  708. }
  709. bool
  710. StyledStreamWriter::hasCommentForValue( const Value &value )
  711. {
  712. return value.hasComment( commentBefore )
  713. || value.hasComment( commentAfterOnSameLine )
  714. || value.hasComment( commentAfter );
  715. }
  716. std::string
  717. StyledStreamWriter::normalizeEOL( const std::string &text )
  718. {
  719. std::string normalized;
  720. normalized.reserve( text.length() );
  721. const char *begin = text.c_str();
  722. const char *end = begin + text.length();
  723. const char *current = begin;
  724. while ( current != end )
  725. {
  726. char c = *current++;
  727. if ( c == '\r' ) // mac or dos EOL
  728. {
  729. if ( *current == '\n' ) // convert dos EOL
  730. ++current;
  731. normalized += '\n';
  732. }
  733. else // handle unix EOL & other char
  734. normalized += c;
  735. }
  736. return normalized;
  737. }
  738. std::ostream& operator<<( std::ostream &sout, const Value &root )
  739. {
  740. Json::StyledStreamWriter writer;
  741. writer.write(sout, root);
  742. return sout;
  743. }
  744. } // namespace Json