summaryrefslogtreecommitdiffstats
path: root/src/json_spirit/json_spirit_writer_template.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/json_spirit/json_spirit_writer_template.h
parentInitial commit. (diff)
downloadceph-upstream/16.2.11+ds.tar.xz
ceph-upstream/16.2.11+ds.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/json_spirit/json_spirit_writer_template.h')
-rw-r--r--src/json_spirit/json_spirit_writer_template.h384
1 files changed, 384 insertions, 0 deletions
diff --git a/src/json_spirit/json_spirit_writer_template.h b/src/json_spirit/json_spirit_writer_template.h
new file mode 100644
index 000000000..2e34268a2
--- /dev/null
+++ b/src/json_spirit/json_spirit_writer_template.h
@@ -0,0 +1,384 @@
+#ifndef JSON_SPIRIT_WRITER_TEMPLATE
+#define JSON_SPIRIT_WRITER_TEMPLATE
+
+// Copyright John W. Wilkinson 2007 - 2011
+// Distributed under the MIT License, see accompanying file LICENSE.txt
+
+// json spirit version 4.05
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include "json_spirit_value.h"
+#include "json_spirit_writer_options.h"
+
+#include <sstream>
+#include <iomanip>
+#include <boost/io/ios_state.hpp>
+
+#include "include/ceph_assert.h"
+
+namespace json_spirit
+{
+ inline char to_hex_char( unsigned int c )
+ {
+ ceph_assert( c <= 0xF );
+
+ const char ch = static_cast< char >( c );
+
+ if( ch < 10 ) return '0' + ch;
+
+ return 'A' - 10 + ch;
+ }
+
+ template< class String_type >
+ String_type non_printable_to_string( unsigned int c )
+ {
+ String_type result( 6, '\\' );
+
+ result[1] = 'u';
+
+ result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
+ result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
+ result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
+ result[ 2 ] = to_hex_char( c & 0x000F );
+
+ return result;
+ }
+
+ template< typename Char_type, class String_type >
+ bool add_esc_char( Char_type c, String_type& s )
+ {
+ switch( c )
+ {
+ case '"': s += to_str< String_type >( "\\\"" ); return true;
+ case '\\': s += to_str< String_type >( "\\\\" ); return true;
+ case '\b': s += to_str< String_type >( "\\b" ); return true;
+ case '\f': s += to_str< String_type >( "\\f" ); return true;
+ case '\n': s += to_str< String_type >( "\\n" ); return true;
+ case '\r': s += to_str< String_type >( "\\r" ); return true;
+ case '\t': s += to_str< String_type >( "\\t" ); return true;
+ }
+
+ return false;
+ }
+
+ template< class String_type >
+ String_type add_esc_chars( const String_type& s, bool raw_utf8 )
+ {
+ typedef typename String_type::const_iterator Iter_type;
+ typedef typename String_type::value_type Char_type;
+
+ String_type result;
+
+ const Iter_type end( s.end() );
+
+ for( Iter_type i = s.begin(); i != end; ++i )
+ {
+ const Char_type c( *i );
+
+ if( add_esc_char( c, result ) ) continue;
+
+ if( raw_utf8 )
+ {
+ result += c;
+ }
+ else
+ {
+ const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
+
+ if( iswprint( unsigned_c ) )
+ {
+ result += c;
+ }
+ else
+ {
+ result += non_printable_to_string< String_type >( unsigned_c );
+ }
+ }
+ }
+
+ return result;
+ }
+
+ template< class Ostream >
+ void append_double( Ostream& os, const double d, const int precision )
+ {
+ os << std::showpoint << std::setprecision( precision ) << d;
+ }
+
+ template< class String_type >
+ void erase_and_extract_exponent( String_type& str, String_type& exp )
+ {
+ const typename String_type::size_type exp_start= str.find( 'e' );
+
+ if( exp_start != String_type::npos )
+ {
+ exp = str.substr( exp_start );
+ str.erase( exp_start );
+ }
+ }
+
+ template< class String_type >
+ typename String_type::size_type find_first_non_zero( const String_type& str )
+ {
+ typename String_type::size_type result = str.size() - 1;
+
+ for( ; result != 0; --result )
+ {
+ if( str[ result ] != '0' )
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ template< class String_type >
+ void remove_trailing( String_type& str )
+ {
+ String_type exp;
+
+ erase_and_extract_exponent( str, exp );
+
+ const typename String_type::size_type first_non_zero = find_first_non_zero( str );
+
+ if( first_non_zero != 0 )
+ {
+ const int offset = str[first_non_zero] == '.' ? 2 : 1; // note zero digits following a decimal point is non standard
+ str.erase( first_non_zero + offset );
+ }
+
+ str += exp;
+ }
+
+ // this class generates the JSON text,
+ // it keeps track of the indentation level etc.
+ //
+ template< class Value_type, class Ostream_type >
+ class Generator
+ {
+ typedef typename Value_type::Config_type Config_type;
+ typedef typename Config_type::String_type String_type;
+ typedef typename Config_type::Object_type Object_type;
+ typedef typename Config_type::Array_type Array_type;
+ typedef typename String_type::value_type Char_type;
+ typedef typename Object_type::value_type Obj_member_type;
+
+ public:
+
+ Generator( const Value_type& value, Ostream_type& os, unsigned int options )
+ : os_( os )
+ , indentation_level_( 0 )
+ , pretty_( ( options & pretty_print ) != 0 || ( options & single_line_arrays ) != 0 )
+ , raw_utf8_( ( options & raw_utf8 ) != 0 )
+ , remove_trailing_zeros_( ( options & remove_trailing_zeros ) != 0 )
+ , single_line_arrays_( ( options & single_line_arrays ) != 0 )
+ , ios_saver_( os )
+ {
+ output( value );
+ }
+
+ private:
+
+ void output( const Value_type& value )
+ {
+ switch( value.type() )
+ {
+ case obj_type: output( value.get_obj() ); break;
+ case array_type: output( value.get_array() ); break;
+ case str_type: output( value.get_str() ); break;
+ case bool_type: output( value.get_bool() ); break;
+ case real_type: output( value.get_real() ); break;
+ case int_type: output_int( value ); break;
+ case null_type: os_ << "null"; break;
+ default: ceph_assert( false );
+ }
+ }
+
+ void output( const Object_type& obj )
+ {
+ output_array_or_obj( obj, '{', '}' );
+ }
+
+ void output( const Obj_member_type& member )
+ {
+ output( Config_type::get_name( member ) ); space();
+ os_ << ':'; space();
+ output( Config_type::get_value( member ) );
+ }
+
+ void output_int( const Value_type& value )
+ {
+ if( value.is_uint64() )
+ {
+ os_ << value.get_uint64();
+ }
+ else
+ {
+ os_ << value.get_int64();
+ }
+ }
+
+ void output( const String_type& s )
+ {
+ os_ << '"' << add_esc_chars( s, raw_utf8_ ) << '"';
+ }
+
+ void output( bool b )
+ {
+ os_ << to_str< String_type >( b ? "true" : "false" );
+ }
+
+ void output( double d )
+ {
+ if( remove_trailing_zeros_ )
+ {
+ std::basic_ostringstream< Char_type > os;
+
+ append_double( os, d, 16 ); // note precision is 16 so that we get some trailing space that we can remove,
+ // otherwise, 0.1234 gets converted to "0.12399999..."
+
+ String_type str = os.str();
+
+ remove_trailing( str );
+
+ os_ << str;
+ }
+ else
+ {
+ append_double( os_, d, 17 );
+ }
+ }
+
+ static bool contains_composite_elements( const Array_type& arr )
+ {
+ for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
+ {
+ const Value_type& val = *i;
+
+ if( val.type() == obj_type ||
+ val.type() == array_type )
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ template< class Iter >
+ void output_composite_item( Iter i, Iter last )
+ {
+ output( *i );
+
+ if( ++i != last )
+ {
+ os_ << ',';
+ }
+ }
+
+ void output( const Array_type& arr )
+ {
+ if( single_line_arrays_ && !contains_composite_elements( arr ) )
+ {
+ os_ << '['; space();
+
+ for( typename Array_type::const_iterator i = arr.begin(); i != arr.end(); ++i )
+ {
+ output_composite_item( i, arr.end() );
+
+ space();
+ }
+
+ os_ << ']';
+ }
+ else
+ {
+ output_array_or_obj( arr, '[', ']' );
+ }
+ }
+
+ template< class T >
+ void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
+ {
+ os_ << start_char; new_line();
+
+ ++indentation_level_;
+
+ for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
+ {
+ indent();
+
+ output_composite_item( i, t.end() );
+
+ new_line();
+ }
+
+ --indentation_level_;
+
+ indent(); os_ << end_char;
+ }
+
+ void indent()
+ {
+ if( !pretty_ ) return;
+
+ for( int i = 0; i < indentation_level_; ++i )
+ {
+ os_ << " ";
+ }
+ }
+
+ void space()
+ {
+ if( pretty_ ) os_ << ' ';
+ }
+
+ void new_line()
+ {
+ if( pretty_ ) os_ << '\n';
+ }
+
+ Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
+
+ Ostream_type& os_;
+ int indentation_level_;
+ bool pretty_;
+ bool raw_utf8_;
+ bool remove_trailing_zeros_;
+ bool single_line_arrays_;
+ boost::io::basic_ios_all_saver< Char_type > ios_saver_; // so that ostream state is reset after control is returned to the caller
+ };
+
+ // writes JSON Value to a stream, e.g.
+ //
+ // write_stream( value, os, pretty_print );
+ //
+ template< class Value_type, class Ostream_type >
+ void write_stream( const Value_type& value, Ostream_type& os, unsigned int options = 0 )
+ {
+ os << std::dec;
+ Generator< Value_type, Ostream_type >( value, os, options );
+ }
+
+ // writes JSON Value to a stream, e.g.
+ //
+ // const string json_str = write( value, pretty_print );
+ //
+ template< class Value_type >
+ typename Value_type::String_type write_string( const Value_type& value, unsigned int options = 0 )
+ {
+ typedef typename Value_type::String_type::value_type Char_type;
+
+ std::basic_ostringstream< Char_type > os;
+
+ write_stream( value, os, options );
+
+ return os.str();
+ }
+}
+
+#endif