contrib-json_spirit:  adding library to reduce external dependencies

moreover, the current macports version is not usable due to a missing
header

Change-Id: I7cd80ecf17b1ca50e5c71badba56d0bf3d390f4f
diff --git a/contrib/json_spirit/json_spirit_writer_template.h b/contrib/json_spirit/json_spirit_writer_template.h
new file mode 100644
index 0000000..61a0e18
--- /dev/null
+++ b/contrib/json_spirit/json_spirit_writer_template.h
@@ -0,0 +1,385 @@
+#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 <cassert>

+#include <sstream>

+#include <iomanip>

+#include <boost/io/ios_state.hpp>

+

+namespace json_spirit

+{

+    inline char to_hex_char( unsigned int c )

+    {

+        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 )

+    {

+        typedef typename String_type::value_type Char_type;

+

+        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: 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