json_spirit_writer_template.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #ifndef JSON_SPIRIT_WRITER_TEMPLATE
  3. #define JSON_SPIRIT_WRITER_TEMPLATE
  4. #include "json_spirit_value.h"
  5. #include <cassert>
  6. #include <sstream>
  7. #include <iomanip>
  8. namespace json_spirit
  9. {
  10. inline char to_hex_char( unsigned int c )
  11. {
  12. assert( c <= 0xF );
  13. const char ch = static_cast< char >( c );
  14. if( ch < 10 ) return '0' + ch;
  15. return 'A' - 10 + ch;
  16. }
  17. template< class String_type >
  18. String_type non_printable_to_string( unsigned int c )
  19. {
  20. typedef typename String_type::value_type Char_type;
  21. String_type result( 6, '\\' );
  22. result[1] = 'u';
  23. result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
  24. result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
  25. result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
  26. result[ 2 ] = to_hex_char( c & 0x000F );
  27. return result;
  28. }
  29. template< typename Char_type, class String_type >
  30. bool add_esc_char( Char_type c, String_type& s )
  31. {
  32. switch( c )
  33. {
  34. case '"': s += to_str< String_type >( "\\\"" ); return true;
  35. case '\\': s += to_str< String_type >( "\\\\" ); return true;
  36. case '\b': s += to_str< String_type >( "\\b" ); return true;
  37. case '\f': s += to_str< String_type >( "\\f" ); return true;
  38. case '\n': s += to_str< String_type >( "\\n" ); return true;
  39. case '\r': s += to_str< String_type >( "\\r" ); return true;
  40. case '\t': s += to_str< String_type >( "\\t" ); return true;
  41. }
  42. return false;
  43. }
  44. template< class String_type >
  45. String_type add_esc_chars( const String_type& s )
  46. {
  47. typedef typename String_type::const_iterator Iter_type;
  48. typedef typename String_type::value_type Char_type;
  49. String_type result;
  50. const Iter_type end( s.end() );
  51. for( Iter_type i = s.begin(); i != end; ++i )
  52. {
  53. const Char_type c( *i );
  54. if( add_esc_char( c, result ) ) continue;
  55. const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
  56. if( iswprint( unsigned_c ) )
  57. {
  58. result += c;
  59. }
  60. else
  61. {
  62. result += non_printable_to_string< String_type >( unsigned_c );
  63. }
  64. }
  65. return result;
  66. }
  67. template< class Value_type, class Ostream_type >
  68. class Generator
  69. {
  70. typedef typename Value_type::Config_type Config_type;
  71. typedef typename Config_type::String_type String_type;
  72. typedef typename Config_type::Object_type Object_type;
  73. typedef typename Config_type::Array_type Array_type;
  74. typedef typename String_type::value_type Char_type;
  75. typedef typename Object_type::value_type Obj_member_type;
  76. public:
  77. Generator( const Value_type& value, Ostream_type& os, bool pretty )
  78. : os_( os )
  79. , indentation_level_( 0 )
  80. , pretty_( pretty )
  81. {
  82. output( value );
  83. }
  84. private:
  85. void output( const Value_type& value )
  86. {
  87. switch( value.type() )
  88. {
  89. case obj_type: output( value.get_obj() ); break;
  90. case array_type: output( value.get_array() ); break;
  91. case str_type: output( value.get_str() ); break;
  92. case bool_type: output( value.get_bool() ); break;
  93. case int_type: output_int( value ); break;
  94. case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8)
  95. << value.get_real(); break;
  96. case null_type: os_ << "null"; break;
  97. default: assert( false );
  98. }
  99. }
  100. void output( const Object_type& obj )
  101. {
  102. output_array_or_obj( obj, '{', '}' );
  103. }
  104. void output( const Array_type& arr )
  105. {
  106. output_array_or_obj( arr, '[', ']' );
  107. }
  108. void output( const Obj_member_type& member )
  109. {
  110. output( Config_type::get_name( member ) ); space();
  111. os_ << ':'; space();
  112. output( Config_type::get_value( member ) );
  113. }
  114. void output_int( const Value_type& value )
  115. {
  116. if( value.is_uint64() )
  117. {
  118. os_ << value.get_uint64();
  119. }
  120. else
  121. {
  122. os_ << value.get_int64();
  123. }
  124. }
  125. void output( const String_type& s )
  126. {
  127. os_ << '"' << add_esc_chars( s ) << '"';
  128. }
  129. void output( bool b )
  130. {
  131. os_ << to_str< String_type >( b ? "true" : "false" );
  132. }
  133. template< class T >
  134. void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
  135. {
  136. os_ << start_char; new_line();
  137. ++indentation_level_;
  138. for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
  139. {
  140. indent(); output( *i );
  141. typename T::const_iterator next = i;
  142. if( ++next != t.end())
  143. {
  144. os_ << ',';
  145. }
  146. new_line();
  147. }
  148. --indentation_level_;
  149. indent(); os_ << end_char;
  150. }
  151. void indent()
  152. {
  153. if( !pretty_ ) return;
  154. for( int i = 0; i < indentation_level_; ++i )
  155. {
  156. os_ << " ";
  157. }
  158. }
  159. void space()
  160. {
  161. if( pretty_ ) os_ << ' ';
  162. }
  163. void new_line()
  164. {
  165. if( pretty_ ) os_ << '\n';
  166. }
  167. Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
  168. Ostream_type& os_;
  169. int indentation_level_;
  170. bool pretty_;
  171. };
  172. template< class Value_type, class Ostream_type >
  173. void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
  174. {
  175. Generator< Value_type, Ostream_type >( value, os, pretty );
  176. }
  177. template< class Value_type >
  178. typename Value_type::String_type write_string( const Value_type& value, bool pretty )
  179. {
  180. typedef typename Value_type::String_type::value_type Char_type;
  181. std::basic_ostringstream< Char_type > os;
  182. write_stream( value, os, pretty );
  183. return os.str();
  184. }
  185. }
  186. #endif