JSON Spirit library from http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx,...
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Wed, 10 Feb 2010 19:41:22 +0000 (19:41 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Wed, 10 Feb 2010 19:41:22 +0000 (19:41 +0000)
13 files changed:
json/LICENSE.txt [new file with mode: 0644]
json/json_spirit.h [new file with mode: 0644]
json/json_spirit_error_position.h [new file with mode: 0644]
json/json_spirit_reader.cpp [new file with mode: 0644]
json/json_spirit_reader.h [new file with mode: 0644]
json/json_spirit_reader_template.h [new file with mode: 0644]
json/json_spirit_stream_reader.h [new file with mode: 0644]
json/json_spirit_utils.h [new file with mode: 0644]
json/json_spirit_value.cpp [new file with mode: 0644]
json/json_spirit_value.h [new file with mode: 0644]
json/json_spirit_writer.cpp [new file with mode: 0644]
json/json_spirit_writer.h [new file with mode: 0644]
json/json_spirit_writer_template.h [new file with mode: 0644]

diff --git a/json/LICENSE.txt b/json/LICENSE.txt
new file mode 100644 (file)
index 0000000..fa193fe
--- /dev/null
@@ -0,0 +1,24 @@
+The MIT License\r
+\r
+Copyright (c) 2007 - 2009 John W. Wilkinson\r
+\r
+Permission is hereby granted, free of charge, to any person\r
+obtaining a copy of this software and associated documentation\r
+files (the "Software"), to deal in the Software without\r
+restriction, including without limitation the rights to use,\r
+copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+copies of the Software, and to permit persons to whom the\r
+Software is furnished to do so, subject to the following\r
+conditions:\r
+\r
+The above copyright notice and this permission notice shall be\r
+included in all copies or substantial portions of the Software.\r
+\r
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\r
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\r
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\r
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
+OTHER DEALINGS IN THE SOFTWARE.\r
diff --git a/json/json_spirit.h b/json/json_spirit.h
new file mode 100644 (file)
index 0000000..7dac05c
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef JSON_SPIRIT\r
+#define JSON_SPIRIT\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include "json_spirit_value.h"\r
+#include "json_spirit_reader.h"\r
+#include "json_spirit_writer.h"\r
+#include "json_spirit_utils.h"\r
+\r
+#endif\r
diff --git a/json/json_spirit_error_position.h b/json/json_spirit_error_position.h
new file mode 100644 (file)
index 0000000..4a535ff
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef JSON_SPIRIT_ERROR_POSITION\r
+#define JSON_SPIRIT_ERROR_POSITION\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include <string>\r
+\r
+namespace json_spirit\r
+{\r
+    // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error.\r
+    // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read" \r
+    // functions that return a bool.\r
+    //\r
+    struct Error_position\r
+    {\r
+        Error_position();\r
+        Error_position( unsigned int line, unsigned int column, const std::string& reason );\r
+        bool operator==( const Error_position& lhs ) const;\r
+        unsigned int line_;\r
+        unsigned int column_;\r
+        std::string reason_;\r
+    };\r
+\r
+    inline Error_position::Error_position()\r
+    :   line_( 0 )\r
+    ,   column_( 0 )\r
+    {\r
+    }\r
+\r
+    inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason )\r
+    :   line_( line )\r
+    ,   column_( column )\r
+    ,   reason_( reason )\r
+    {\r
+    }\r
+\r
+    inline bool Error_position::operator==( const Error_position& lhs ) const\r
+    {\r
+        if( this == &lhs ) return true;\r
+\r
+        return ( reason_ == lhs.reason_ ) &&\r
+               ( line_   == lhs.line_ ) &&\r
+               ( column_ == lhs.column_ ); \r
+}\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_reader.cpp b/json/json_spirit_reader.cpp
new file mode 100644 (file)
index 0000000..8e2fb5e
--- /dev/null
@@ -0,0 +1,137 @@
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#include "json_spirit_reader.h"\r
+#include "json_spirit_reader_template.h"\r
+\r
+using namespace json_spirit;\r
+\r
+bool json_spirit::read( const std::string& s, Value& value )\r
+{\r
+    return read_string( s, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( const std::string& s, Value& value )\r
+{\r
+    read_string_or_throw( s, value );\r
+}\r
+\r
+bool json_spirit::read( std::istream& is, Value& value )\r
+{\r
+    return read_stream( is, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::istream& is, Value& value )\r
+{\r
+    read_stream_or_throw( is, value );\r
+}\r
+\r
+bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value )\r
+{\r
+    return read_range( begin, end, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value )\r
+{\r
+    begin = read_range_or_throw( begin, end, value );\r
+}\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+bool json_spirit::read( const std::wstring& s, wValue& value )\r
+{\r
+    return read_string( s, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( const std::wstring& s, wValue& value )\r
+{\r
+    read_string_or_throw( s, value );\r
+}\r
+\r
+bool json_spirit::read( std::wistream& is, wValue& value )\r
+{\r
+    return read_stream( is, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::wistream& is, wValue& value )\r
+{\r
+    read_stream_or_throw( is, value );\r
+}\r
+\r
+bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value )\r
+{\r
+    return read_range( begin, end, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value )\r
+{\r
+    begin = read_range_or_throw( begin, end, value );\r
+}\r
+\r
+#endif\r
+\r
+bool json_spirit::read( const std::string& s, mValue& value )\r
+{\r
+    return read_string( s, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( const std::string& s, mValue& value )\r
+{\r
+    read_string_or_throw( s, value );\r
+}\r
+\r
+bool json_spirit::read( std::istream& is, mValue& value )\r
+{\r
+    return read_stream( is, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::istream& is, mValue& value )\r
+{\r
+    read_stream_or_throw( is, value );\r
+}\r
+\r
+bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value )\r
+{\r
+    return read_range( begin, end, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value )\r
+{\r
+    begin = read_range_or_throw( begin, end, value );\r
+}\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+bool json_spirit::read( const std::wstring& s, wmValue& value )\r
+{\r
+    return read_string( s, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( const std::wstring& s, wmValue& value )\r
+{\r
+    read_string_or_throw( s, value );\r
+}\r
+\r
+bool json_spirit::read( std::wistream& is, wmValue& value )\r
+{\r
+    return read_stream( is, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::wistream& is, wmValue& value )\r
+{\r
+    read_stream_or_throw( is, value );\r
+}\r
+\r
+bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value )\r
+{\r
+    return read_range( begin, end, value );\r
+}\r
+\r
+void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value )\r
+{\r
+    begin = read_range_or_throw( begin, end, value );\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_reader.h b/json/json_spirit_reader.h
new file mode 100644 (file)
index 0000000..a58bfc1
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef JSON_SPIRIT_READER\r
+#define JSON_SPIRIT_READER\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include "json_spirit_value.h"\r
+#include "json_spirit_error_position.h"\r
+#include <iostream>\r
+\r
+namespace json_spirit\r
+{\r
+    // functions to reads a JSON values\r
+\r
+    bool read( const std::string& s, Value& value );\r
+    bool read( std::istream& is,     Value& value );\r
+    bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );\r
+\r
+    void read_or_throw( const std::string& s, Value& value );  \r
+    void read_or_throw( std::istream& is,     Value& value );\r
+    void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+    bool read( const std::wstring& s, wValue& value );\r
+    bool read( std::wistream&  is,    wValue& value );\r
+    bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );    \r
+\r
+    void read_or_throw( const std::wstring& s, wValue& value );\r
+    void read_or_throw( std::wistream& is,     wValue& value );\r
+    void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );\r
+\r
+#endif\r
+\r
+    bool read( const std::string& s, mValue& value );\r
+    bool read( std::istream& is,     mValue& value );\r
+    bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );\r
+\r
+    void read_or_throw( const std::string& s, mValue& value );  \r
+    void read_or_throw( std::istream& is,     mValue& value );\r
+    void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+    bool read( const std::wstring& s, wmValue& value );\r
+    bool read( std::wistream& is,     wmValue& value );\r
+    bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );    \r
+\r
+    void read_or_throw( const std::wstring& s, wmValue& value );\r
+    void read_or_throw( std::wistream& is,     wmValue& value );\r
+    void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );\r
+\r
+#endif\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_reader_template.h b/json/json_spirit_reader_template.h
new file mode 100644 (file)
index 0000000..81cded4
--- /dev/null
@@ -0,0 +1,612 @@
+#ifndef JSON_SPIRIT_READER_TEMPLATE\r
+#define JSON_SPIRIT_READER_TEMPLATE\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#include "json_spirit_value.h"\r
+#include "json_spirit_error_position.h"\r
+\r
+//#define BOOST_SPIRIT_THREADSAFE  // uncomment for multithreaded use, requires linking to boost.thread\r
+\r
+#include <boost/bind.hpp>\r
+#include <boost/function.hpp>\r
+#include <boost/version.hpp>\r
+\r
+#if BOOST_VERSION >= 103800\r
+    #include <boost/spirit/include/classic_core.hpp>\r
+    #include <boost/spirit/include/classic_confix.hpp>\r
+    #include <boost/spirit/include/classic_escape_char.hpp>\r
+    #include <boost/spirit/include/classic_multi_pass.hpp>\r
+    #include <boost/spirit/include/classic_position_iterator.hpp>\r
+    #define spirit_namespace boost::spirit::classic\r
+#else\r
+    #include <boost/spirit/core.hpp>\r
+    #include <boost/spirit/utility/confix.hpp>\r
+    #include <boost/spirit/utility/escape_char.hpp>\r
+    #include <boost/spirit/iterator/multi_pass.hpp>\r
+    #include <boost/spirit/iterator/position_iterator.hpp>\r
+    #define spirit_namespace boost::spirit\r
+#endif\r
+\r
+namespace json_spirit\r
+{\r
+    const spirit_namespace::int_parser < boost::int64_t >  int64_p  = spirit_namespace::int_parser < boost::int64_t  >();\r
+    const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >();\r
+\r
+    template< class Iter_type >\r
+    bool is_eq( Iter_type first, Iter_type last, const char* c_str )\r
+    {\r
+        for( Iter_type i = first; i != last; ++i, ++c_str )\r
+        {\r
+            if( *c_str == 0 ) return false;\r
+\r
+            if( *i != *c_str ) return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+    template< class Char_type >\r
+    Char_type hex_to_num( const Char_type c )\r
+    {\r
+        if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0';\r
+        if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10;\r
+        if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10;\r
+        return 0;\r
+    }\r
+\r
+    template< class Char_type, class Iter_type >\r
+    Char_type hex_str_to_char( Iter_type& begin )\r
+    {\r
+        const Char_type c1( *( ++begin ) );\r
+        const Char_type c2( *( ++begin ) );\r
+\r
+        return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 );\r
+    }       \r
+\r
+    template< class Char_type, class Iter_type >\r
+    Char_type unicode_str_to_char( Iter_type& begin )\r
+    {\r
+        const Char_type c1( *( ++begin ) );\r
+        const Char_type c2( *( ++begin ) );\r
+        const Char_type c3( *( ++begin ) );\r
+        const Char_type c4( *( ++begin ) );\r
+\r
+        return ( hex_to_num( c1 ) << 12 ) + \r
+               ( hex_to_num( c2 ) <<  8 ) + \r
+               ( hex_to_num( c3 ) <<  4 ) + \r
+               hex_to_num( c4 );\r
+    }\r
+\r
+    template< class String_type >\r
+    void append_esc_char_and_incr_iter( String_type& s, \r
+                                        typename String_type::const_iterator& begin, \r
+                                        typename String_type::const_iterator end )\r
+    {\r
+        typedef typename String_type::value_type Char_type;\r
+             \r
+        const Char_type c2( *begin );\r
+\r
+        switch( c2 )\r
+        {\r
+            case 't':  s += '\t'; break;\r
+            case 'b':  s += '\b'; break;\r
+            case 'f':  s += '\f'; break;\r
+            case 'n':  s += '\n'; break;\r
+            case 'r':  s += '\r'; break;\r
+            case '\\': s += '\\'; break;\r
+            case '/':  s += '/';  break;\r
+            case '"':  s += '"';  break;\r
+            case 'x':  \r
+            {\r
+                if( end - begin >= 3 )  //  expecting "xHH..."\r
+                {\r
+                    s += hex_str_to_char< Char_type >( begin );  \r
+                }\r
+                break;\r
+            }\r
+            case 'u':  \r
+            {\r
+                if( end - begin >= 5 )  //  expecting "uHHHH..."\r
+                {\r
+                    s += unicode_str_to_char< Char_type >( begin );  \r
+                }\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    template< class String_type >\r
+    String_type substitute_esc_chars( typename String_type::const_iterator begin, \r
+                                   typename String_type::const_iterator end )\r
+    {\r
+        typedef typename String_type::const_iterator Iter_type;\r
+\r
+        if( end - begin < 2 ) return String_type( begin, end );\r
+\r
+        String_type result;\r
+        \r
+        result.reserve( end - begin );\r
+\r
+        const Iter_type end_minus_1( end - 1 );\r
+\r
+        Iter_type substr_start = begin;\r
+        Iter_type i = begin;\r
+\r
+        for( ; i < end_minus_1; ++i )\r
+        {\r
+            if( *i == '\\' )\r
+            {\r
+                result.append( substr_start, i );\r
+\r
+                ++i;  // skip the '\'\r
+             \r
+                append_esc_char_and_incr_iter( result, i, end );\r
+\r
+                substr_start = i + 1;\r
+            }\r
+        }\r
+\r
+        result.append( substr_start, end );\r
+\r
+        return result;\r
+    }\r
+\r
+    template< class String_type >\r
+    String_type get_str_( typename String_type::const_iterator begin, \r
+                       typename String_type::const_iterator end )\r
+    {\r
+        assert( end - begin >= 2 );\r
+\r
+        typedef typename String_type::const_iterator Iter_type;\r
+\r
+        Iter_type str_without_quotes( ++begin );\r
+        Iter_type end_without_quotes( --end );\r
+\r
+        return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes );\r
+    }\r
+\r
+    inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end )\r
+    {\r
+        return get_str_< std::string >( begin, end );\r
+    }\r
+\r
+    inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end )\r
+    {\r
+        return get_str_< std::wstring >( begin, end );\r
+    }\r
+    \r
+    template< class String_type, class Iter_type >\r
+    String_type get_str( Iter_type begin, Iter_type end )\r
+    {\r
+        const String_type tmp( begin, end );  // convert multipass iterators to string iterators\r
+\r
+        return get_str( tmp.begin(), tmp.end() );\r
+    }\r
+\r
+    // this class's methods get called by the spirit parse resulting\r
+    // in the creation of a JSON object or array\r
+    //\r
+    // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator\r
+    //\r
+    template< class Value_type, class Iter_type >\r
+    class Semantic_actions \r
+    {\r
+    public:\r
+\r
+        typedef typename Value_type::Config_type Config_type;\r
+        typedef typename Config_type::String_type String_type;\r
+        typedef typename Config_type::Object_type Object_type;\r
+        typedef typename Config_type::Array_type Array_type;\r
+        typedef typename String_type::value_type Char_type;\r
+\r
+        Semantic_actions( Value_type& value )\r
+        :   value_( value )\r
+        ,   current_p_( 0 )\r
+        {\r
+        }\r
+\r
+        void begin_obj( Char_type c )\r
+        {\r
+            assert( c == '{' );\r
+\r
+            begin_compound< Object_type >();\r
+        }\r
+\r
+        void end_obj( Char_type c )\r
+        {\r
+            assert( c == '}' );\r
+\r
+            end_compound();\r
+        }\r
+\r
+        void begin_array( Char_type c )\r
+        {\r
+            assert( c == '[' );\r
+     \r
+            begin_compound< Array_type >();\r
+        }\r
+\r
+        void end_array( Char_type c )\r
+        {\r
+            assert( c == ']' );\r
+\r
+            end_compound();\r
+        }\r
+\r
+        void new_name( Iter_type begin, Iter_type end )\r
+        {\r
+            assert( current_p_->type() == obj_type );\r
+\r
+            name_ = get_str< String_type >( begin, end );\r
+        }\r
+\r
+        void new_str( Iter_type begin, Iter_type end )\r
+        {\r
+            add_to_current( get_str< String_type >( begin, end ) );\r
+        }\r
+\r
+        void new_true( Iter_type begin, Iter_type end )\r
+        {\r
+            assert( is_eq( begin, end, "true" ) );\r
+\r
+            add_to_current( true );\r
+        }\r
+\r
+        void new_false( Iter_type begin, Iter_type end )\r
+        {\r
+            assert( is_eq( begin, end, "false" ) );\r
+\r
+            add_to_current( false );\r
+        }\r
+\r
+        void new_null( Iter_type begin, Iter_type end )\r
+        {\r
+            assert( is_eq( begin, end, "null" ) );\r
+\r
+            add_to_current( Value_type() );\r
+        }\r
+\r
+        void new_int( boost::int64_t i )\r
+        {\r
+            add_to_current( i );\r
+        }\r
+\r
+        void new_uint64( boost::uint64_t ui )\r
+        {\r
+            add_to_current( ui );\r
+        }\r
+\r
+        void new_real( double d )\r
+        {\r
+            add_to_current( d );\r
+        }\r
+\r
+    private:\r
+\r
+        Semantic_actions& operator=( const Semantic_actions& ); \r
+                                    // to prevent "assignment operator could not be generated" warning\r
+\r
+        Value_type* add_first( const Value_type& value )\r
+        {\r
+            assert( current_p_ == 0 );\r
+\r
+            value_ = value;\r
+            current_p_ = &value_;\r
+            return current_p_;\r
+        }\r
+\r
+        template< class Array_or_obj >\r
+        void begin_compound()\r
+        {\r
+            if( current_p_ == 0 )\r
+            {\r
+                add_first( Array_or_obj() );\r
+            }\r
+            else\r
+            {\r
+                stack_.push_back( current_p_ );\r
+\r
+                Array_or_obj new_array_or_obj;   // avoid copy by building new array or object in place\r
+\r
+                current_p_ = add_to_current( new_array_or_obj );\r
+            }\r
+        }\r
+\r
+        void end_compound()\r
+        {\r
+            if( current_p_ != &value_ )\r
+            {\r
+                current_p_ = stack_.back();\r
+                \r
+                stack_.pop_back();\r
+            }    \r
+        }\r
+\r
+        Value_type* add_to_current( const Value_type& value )\r
+        {\r
+            if( current_p_ == 0 )\r
+            {\r
+                return add_first( value );\r
+            }\r
+            else if( current_p_->type() == array_type )\r
+            {\r
+                current_p_->get_array().push_back( value );\r
+\r
+                return &current_p_->get_array().back(); \r
+            }\r
+            \r
+            assert( current_p_->type() == obj_type );\r
+\r
+            return &Config_type::add( current_p_->get_obj(), name_, value );\r
+        }\r
+\r
+        Value_type& value_;             // this is the object or array that is being created\r
+        Value_type* current_p_;         // the child object or array that is currently being constructed\r
+\r
+        std::vector< Value_type* > stack_;   // previous child objects and arrays\r
+\r
+        String_type name_;              // of current name/value pair\r
+    };\r
+\r
+    template< typename Iter_type >\r
+    void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason )\r
+    {\r
+        throw Error_position( i.get_position().line, i.get_position().column, reason );\r
+    }\r
+\r
+    template< typename Iter_type >\r
+    void throw_error( Iter_type i, const std::string& reason )\r
+    {\r
+       throw reason;\r
+    }\r
+\r
+    // the spirit grammer \r
+    //\r
+    template< class Value_type, class Iter_type >\r
+    class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > >\r
+    {\r
+    public:\r
+\r
+        typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t;\r
+\r
+        Json_grammer( Semantic_actions_t& semantic_actions )\r
+        :   actions_( semantic_actions )\r
+        {\r
+        }\r
+\r
+        static void throw_not_value( Iter_type begin, Iter_type end )\r
+        {\r
+           throw_error( begin, "not a value" );\r
+        }\r
+\r
+        static void throw_not_array( Iter_type begin, Iter_type end )\r
+        {\r
+           throw_error( begin, "not an array" );\r
+        }\r
+\r
+        static void throw_not_object( Iter_type begin, Iter_type end )\r
+        {\r
+           throw_error( begin, "not an object" );\r
+        }\r
+\r
+        static void throw_not_pair( Iter_type begin, Iter_type end )\r
+        {\r
+           throw_error( begin, "not a pair" );\r
+        }\r
+\r
+        static void throw_not_colon( Iter_type begin, Iter_type end )\r
+        {\r
+           throw_error( begin, "no colon in pair" );\r
+        }\r
+\r
+        static void throw_not_string( Iter_type begin, Iter_type end )\r
+        {\r
+           throw_error( begin, "not a string" );\r
+        }\r
+\r
+        template< typename ScannerT >\r
+        class definition\r
+        {\r
+        public:\r
+\r
+            definition( const Json_grammer& self )\r
+            {\r
+                using namespace spirit_namespace;\r
+\r
+                typedef typename Value_type::String_type::value_type Char_type;\r
+\r
+                // first we convert the semantic action class methods to functors with the \r
+                // parameter signature expected by spirit\r
+\r
+                typedef boost::function< void( Char_type )            > Char_action;\r
+                typedef boost::function< void( Iter_type, Iter_type ) > Str_action;\r
+                typedef boost::function< void( double )               > Real_action;\r
+                typedef boost::function< void( boost::int64_t )       > Int_action;\r
+                typedef boost::function< void( boost::uint64_t )      > Uint64_action;\r
+\r
+                Char_action   begin_obj  ( boost::bind( &Semantic_actions_t::begin_obj,   &self.actions_, _1 ) );\r
+                Char_action   end_obj    ( boost::bind( &Semantic_actions_t::end_obj,     &self.actions_, _1 ) );\r
+                Char_action   begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) );\r
+                Char_action   end_array  ( boost::bind( &Semantic_actions_t::end_array,   &self.actions_, _1 ) );\r
+                Str_action    new_name   ( boost::bind( &Semantic_actions_t::new_name,    &self.actions_, _1, _2 ) );\r
+                Str_action    new_str    ( boost::bind( &Semantic_actions_t::new_str,     &self.actions_, _1, _2 ) );\r
+                Str_action    new_true   ( boost::bind( &Semantic_actions_t::new_true,    &self.actions_, _1, _2 ) );\r
+                Str_action    new_false  ( boost::bind( &Semantic_actions_t::new_false,   &self.actions_, _1, _2 ) );\r
+                Str_action    new_null   ( boost::bind( &Semantic_actions_t::new_null,    &self.actions_, _1, _2 ) );\r
+                Real_action   new_real   ( boost::bind( &Semantic_actions_t::new_real,    &self.actions_, _1 ) );\r
+                Int_action    new_int    ( boost::bind( &Semantic_actions_t::new_int,     &self.actions_, _1 ) );\r
+                Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64,  &self.actions_, _1 ) );\r
+\r
+                // actual grammer\r
+\r
+                json_\r
+                    = value_ | eps_p[ &throw_not_value ]\r
+                    ;\r
+\r
+                value_\r
+                    = string_[ new_str ] \r
+                    | number_ \r
+                    | object_ \r
+                    | array_ \r
+                    | str_p( "true" ) [ new_true  ] \r
+                    | str_p( "false" )[ new_false ] \r
+                    | str_p( "null" ) [ new_null  ]\r
+                    ;\r
+\r
+                object_ \r
+                    = ch_p('{')[ begin_obj ]\r
+                    >> !members_\r
+                    >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] )\r
+                    ;\r
+\r
+                members_\r
+                    = pair_ >> *( ',' >> pair_ )\r
+                    ;\r
+\r
+                pair_\r
+                    = string_[ new_name ]\r
+                    >> ( ':' | eps_p[ &throw_not_colon ] )\r
+                    >> ( value_ | eps_p[ &throw_not_value ] )\r
+                    ;\r
+\r
+                array_\r
+                    = ch_p('[')[ begin_array ]\r
+                    >> !elements_\r
+                    >> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] )\r
+                    ;\r
+\r
+                elements_\r
+                    = value_ >> *( ',' >> value_ )\r
+                    ;\r
+\r
+                string_ \r
+                    = lexeme_d // this causes white space inside a string to be retained\r
+                      [\r
+                          confix_p\r
+                          ( \r
+                              '"', \r
+                              *lex_escape_ch_p,\r
+                              '"'\r
+                          ) \r
+                      ]\r
+                    ;\r
+\r
+                number_\r
+                    = strict_real_p[ new_real   ] \r
+                    | int64_p      [ new_int    ]\r
+                    | uint64_p     [ new_uint64 ]\r
+                    ;\r
+            }\r
+\r
+            spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_;\r
+\r
+            const spirit_namespace::rule< ScannerT >& start() const { return json_; }\r
+        };\r
+\r
+    private:\r
+\r
+        Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning\r
+\r
+        Semantic_actions_t& actions_;\r
+    };\r
+\r
+    template< class Iter_type, class Value_type >\r
+    Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )\r
+    {\r
+        Semantic_actions< Value_type, Iter_type > semantic_actions( value );\r
+     \r
+        const spirit_namespace::parse_info< Iter_type > info = \r
+                            spirit_namespace::parse( begin, end, \r
+                                                    Json_grammer< Value_type, Iter_type >( semantic_actions ), \r
+                                                    spirit_namespace::space_p );\r
+\r
+        if( !info.hit )\r
+        {\r
+            assert( false ); // in theory exception should already have been thrown\r
+            throw_error( info.stop, "error" );\r
+        }\r
+\r
+        return info.stop;\r
+    }\r
+\r
+    template< class Iter_type, class Value_type >\r
+    void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )\r
+    {\r
+        typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t;\r
+\r
+        const Posn_iter_t posn_begin( begin, end );\r
+        const Posn_iter_t posn_end( end, end );\r
+     \r
+        read_range_or_throw( posn_begin, posn_end, value );\r
+    }\r
+\r
+    template< class Iter_type, class Value_type >\r
+    bool read_range( Iter_type& begin, Iter_type end, Value_type& value )\r
+    {\r
+        try\r
+        {\r
+            begin = read_range_or_throw( begin, end, value );\r
+\r
+            return true;\r
+        }\r
+        catch( ... )\r
+        {\r
+            return false;\r
+        }\r
+    }\r
+\r
+    template< class String_type, class Value_type >\r
+    void read_string_or_throw( const String_type& s, Value_type& value )\r
+    {\r
+        add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value );\r
+    }\r
+\r
+    template< class String_type, class Value_type >\r
+    bool read_string( const String_type& s, Value_type& value )\r
+    {\r
+        typename String_type::const_iterator begin = s.begin();\r
+\r
+        return read_range( begin, s.end(), value );\r
+    }\r
+\r
+    template< class Istream_type >\r
+    struct Multi_pass_iters\r
+    {\r
+        typedef typename Istream_type::char_type Char_type;\r
+        typedef std::istream_iterator< Char_type, Char_type > istream_iter;\r
+        typedef spirit_namespace::multi_pass< istream_iter > Mp_iter;\r
+\r
+        Multi_pass_iters( Istream_type& is )\r
+        {\r
+            is.unsetf( std::ios::skipws );\r
+\r
+            begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) );\r
+            end_   = spirit_namespace::make_multi_pass( istream_iter() );\r
+        }\r
+\r
+        Mp_iter begin_;\r
+        Mp_iter end_;\r
+    };\r
+\r
+    template< class Istream_type, class Value_type >\r
+    bool read_stream( Istream_type& is, Value_type& value )\r
+    {\r
+        Multi_pass_iters< Istream_type > mp_iters( is );\r
+\r
+        return read_range( mp_iters.begin_, mp_iters.end_, value );\r
+    }\r
+\r
+    template< class Istream_type, class Value_type >\r
+    void read_stream_or_throw( Istream_type& is, Value_type& value )\r
+    {\r
+        const Multi_pass_iters< Istream_type > mp_iters( is );\r
+\r
+        add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value );\r
+    }\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_stream_reader.h b/json/json_spirit_stream_reader.h
new file mode 100644 (file)
index 0000000..a9ceeac
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef JSON_SPIRIT_READ_STREAM\r
+#define JSON_SPIRIT_READ_STREAM\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include "json_spirit_reader_template.h"\r
+\r
+namespace json_spirit\r
+{\r
+    // these classes allows you to read multiple top level contiguous values from a stream,\r
+    // the normal stream read functions have a bug that prevent multiple top level values \r
+    // from being read unless they are separated by spaces\r
+\r
+    template< class Istream_type, class Value_type >\r
+    class Stream_reader\r
+    {\r
+    public:\r
+\r
+        Stream_reader( Istream_type& is )\r
+        :   iters_( is )\r
+        {\r
+        }\r
+\r
+        bool read_next( Value_type& value )\r
+        {\r
+            return read_range( iters_.begin_, iters_.end_, value );\r
+        }\r
+\r
+    private:\r
+\r
+        typedef Multi_pass_iters< Istream_type > Mp_iters;\r
+\r
+        Mp_iters iters_;\r
+    };\r
+\r
+    template< class Istream_type, class Value_type >\r
+    class Stream_reader_thrower\r
+    {\r
+    public:\r
+\r
+        Stream_reader_thrower( Istream_type& is )\r
+        :   iters_( is )\r
+        ,    posn_begin_( iters_.begin_, iters_.end_ )\r
+        ,    posn_end_( iters_.end_, iters_.end_ )\r
+        {\r
+        }\r
+\r
+        void read_next( Value_type& value )\r
+        {\r
+            posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value );\r
+        }\r
+\r
+    private:\r
+\r
+        typedef Multi_pass_iters< Istream_type > Mp_iters;\r
+        typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t;\r
+\r
+        Mp_iters iters_;\r
+        Posn_iter_t posn_begin_, posn_end_;\r
+    };\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_utils.h b/json/json_spirit_utils.h
new file mode 100644 (file)
index 0000000..7eb338e
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef JSON_SPIRIT_UTILS\r
+#define JSON_SPIRIT_UTILS\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include "json_spirit_value.h"\r
+#include <map>\r
+\r
+namespace json_spirit\r
+{ \r
+    template< class Obj_t, class Map_t >\r
+    void obj_to_map( const Obj_t& obj, Map_t& mp_obj )\r
+    {\r
+        mp_obj.clear();\r
+\r
+        for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i )\r
+        {\r
+            mp_obj[ i->name_ ] = i->value_;\r
+        }\r
+    }\r
+\r
+    template< class Obj_t, class Map_t >\r
+    void map_to_obj( const Map_t& mp_obj, Obj_t& obj )\r
+    {\r
+        obj.clear();\r
+\r
+        for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i )\r
+        {\r
+            obj.push_back( typename Obj_t::value_type( i->first, i->second ) );\r
+        }\r
+    }\r
+\r
+    typedef std::map< std::string, Value > Mapped_obj;\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+    typedef std::map< std::wstring, wValue > wMapped_obj;\r
+#endif\r
+\r
+    template< class Object_type, class String_type >\r
+    const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name )\r
+    {\r
+        for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i )\r
+        {\r
+            if( i->name_ == name )\r
+            {\r
+                return i->value_;\r
+            }\r
+        }\r
+\r
+        return Object_type::value_type::Value_type::null;\r
+    }\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_value.cpp b/json/json_spirit_value.cpp
new file mode 100644 (file)
index 0000000..dd5b50e
--- /dev/null
@@ -0,0 +1,8 @@
+/* Copyright (c) 2007 John W Wilkinson\r
+\r
+   This source code can be used for any purpose as long as\r
+   this comment is retained. */\r
+\r
+// json spirit version 2.00\r
+\r
+#include "json_spirit_value.h"\r
diff --git a/json/json_spirit_value.h b/json/json_spirit_value.h
new file mode 100644 (file)
index 0000000..e8be355
--- /dev/null
@@ -0,0 +1,532 @@
+#ifndef JSON_SPIRIT_VALUE\r
+#define JSON_SPIRIT_VALUE\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include <vector>\r
+#include <map>\r
+#include <string>\r
+#include <cassert>\r
+#include <sstream>\r
+#include <stdexcept>\r
+#include <boost/config.hpp> \r
+#include <boost/cstdint.hpp> \r
+#include <boost/shared_ptr.hpp> \r
+#include <boost/variant.hpp> \r
+\r
+namespace json_spirit\r
+{\r
+    enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };\r
+\r
+    template< class Config >    // Config determines whether the value uses std::string or std::wstring and\r
+                                // whether JSON Objects are represented as vectors or maps\r
+    class Value_impl\r
+    {\r
+    public:\r
+\r
+        typedef Config Config_type;\r
+        typedef typename Config::String_type String_type;\r
+        typedef typename Config::Object_type Object;\r
+        typedef typename Config::Array_type Array;\r
+        typedef typename String_type::const_pointer Const_str_ptr;  // eg const char*\r
+\r
+        Value_impl();  // creates null value\r
+        Value_impl( Const_str_ptr      value ); \r
+        Value_impl( const String_type& value );\r
+        Value_impl( const Object&      value );\r
+        Value_impl( const Array&       value );\r
+        Value_impl( bool               value );\r
+        Value_impl( int                value );\r
+        Value_impl( boost::int64_t     value );\r
+        Value_impl( boost::uint64_t    value );\r
+        Value_impl( double             value );\r
+\r
+        Value_impl( const Value_impl& other );\r
+\r
+        bool operator==( const Value_impl& lhs ) const;\r
+\r
+        Value_impl& operator=( const Value_impl& lhs );\r
+\r
+        Value_type type() const;\r
+\r
+        bool is_uint64() const;\r
+        bool is_null() const;\r
+\r
+        const String_type& get_str()    const;\r
+        const Object&      get_obj()    const;\r
+        const Array&       get_array()  const;\r
+        bool               get_bool()   const;\r
+        int                get_int()    const;\r
+        boost::int64_t     get_int64()  const;\r
+        boost::uint64_t    get_uint64() const;\r
+        double             get_real()   const;\r
+\r
+        Object& get_obj();\r
+        Array&  get_array();\r
+\r
+        template< typename T > T get_value() const;  // example usage: int    i = value.get_value< int >();\r
+                                                     // or             double d = value.get_value< double >();\r
+\r
+        static const Value_impl null;\r
+\r
+    private:\r
+\r
+        void check_type( const Value_type vtype ) const;\r
+\r
+        typedef boost::variant< String_type, \r
+                                boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, \r
+                                bool, boost::int64_t, double > Variant;\r
+\r
+        Value_type type_;\r
+        Variant v_;\r
+        bool is_uint64_;\r
+    };\r
+\r
+    // vector objects\r
+\r
+    template< class Config >\r
+    struct Pair_impl\r
+    {\r
+        typedef typename Config::String_type String_type;\r
+        typedef typename Config::Value_type Value_type;\r
+\r
+        Pair_impl( const String_type& name, const Value_type& value );\r
+\r
+        bool operator==( const Pair_impl& lhs ) const;\r
+\r
+        String_type name_;\r
+        Value_type value_;\r
+    };\r
+\r
+    template< class String >\r
+    struct Config_vector\r
+    {\r
+        typedef String String_type;\r
+        typedef Value_impl< Config_vector > Value_type;\r
+        typedef Pair_impl < Config_vector > Pair_type;\r
+        typedef std::vector< Value_type > Array_type;\r
+        typedef std::vector< Pair_type > Object_type;\r
+\r
+        static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )\r
+        {\r
+            obj.push_back( Pair_type( name , value ) );\r
+\r
+            return obj.back().value_;\r
+        }\r
+                \r
+        static String_type get_name( const Pair_type& pair )\r
+        {\r
+            return pair.name_;\r
+        }\r
+                \r
+        static Value_type get_value( const Pair_type& pair )\r
+        {\r
+            return pair.value_;\r
+        }\r
+    };\r
+\r
+    // typedefs for ASCII\r
+\r
+    typedef Config_vector< std::string > Config;\r
+\r
+    typedef Config::Value_type  Value;\r
+    typedef Config::Pair_type   Pair;\r
+    typedef Config::Object_type Object;\r
+    typedef Config::Array_type  Array;\r
+\r
+    // typedefs for Unicode\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+    typedef Config_vector< std::wstring > wConfig;\r
+\r
+    typedef wConfig::Value_type  wValue;\r
+    typedef wConfig::Pair_type   wPair;\r
+    typedef wConfig::Object_type wObject;\r
+    typedef wConfig::Array_type  wArray;\r
+#endif\r
+\r
+    // map objects\r
+\r
+    template< class String >\r
+    struct Config_map\r
+    {\r
+        typedef String String_type;\r
+        typedef Value_impl< Config_map > Value_type;\r
+        typedef std::vector< Value_type > Array_type;\r
+        typedef std::map< String_type, Value_type > Object_type;\r
+        typedef typename Object_type::value_type Pair_type;\r
+\r
+        static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )\r
+        {\r
+            return obj[ name ] = value;\r
+        }\r
+                \r
+        static String_type get_name( const Pair_type& pair )\r
+        {\r
+            return pair.first;\r
+        }\r
+                \r
+        static Value_type get_value( const Pair_type& pair )\r
+        {\r
+            return pair.second;\r
+        }\r
+    };\r
+\r
+    // typedefs for ASCII\r
+\r
+    typedef Config_map< std::string > mConfig;\r
+\r
+    typedef mConfig::Value_type  mValue;\r
+    typedef mConfig::Object_type mObject;\r
+    typedef mConfig::Array_type  mArray;\r
+\r
+    // typedefs for Unicode\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+    typedef Config_map< std::wstring > wmConfig;\r
+\r
+    typedef wmConfig::Value_type  wmValue;\r
+    typedef wmConfig::Object_type wmObject;\r
+    typedef wmConfig::Array_type  wmArray;\r
+\r
+#endif\r
+\r
+    ///////////////////////////////////////////////////////////////////////////////////////////////\r
+    //\r
+    // implementation\r
+\r
+    template< class Config >\r
+    const Value_impl< Config > Value_impl< Config >::null;\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl()\r
+    :   type_( null_type )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( const Const_str_ptr value )\r
+    :   type_( str_type )\r
+    ,   v_( String_type( value ) )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( const String_type& value )\r
+    :   type_( str_type )\r
+    ,   v_( value )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( const Object& value )\r
+    :   type_( obj_type )\r
+    ,   v_( value )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( const Array& value )\r
+    :   type_( array_type )\r
+    ,   v_( value )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( bool value )\r
+    :   type_( bool_type )\r
+    ,   v_( value )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( int value )\r
+    :   type_( int_type )\r
+    ,   v_( static_cast< boost::int64_t >( value ) )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( boost::int64_t value )\r
+    :   type_( int_type )\r
+    ,   v_( value )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( boost::uint64_t value )\r
+    :   type_( int_type )\r
+    ,   v_( static_cast< boost::int64_t >( value ) )\r
+    ,   is_uint64_( true )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( double value )\r
+    :   type_( real_type )\r
+    ,   v_( value )\r
+    ,   is_uint64_( false )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >::Value_impl( const Value_impl< Config >& other )\r
+    :   type_( other.type() )\r
+    ,   v_( other.v_ )\r
+    ,   is_uint64_( other.is_uint64_ )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs )\r
+    {\r
+        Value_impl tmp( lhs );\r
+\r
+        std::swap( type_, tmp.type_ );\r
+        std::swap( v_, tmp.v_ );\r
+        std::swap( is_uint64_, tmp.is_uint64_ );\r
+\r
+        return *this;\r
+    }\r
+\r
+    template< class Config >\r
+    bool Value_impl< Config >::operator==( const Value_impl& lhs ) const\r
+    {\r
+        if( this == &lhs ) return true;\r
+\r
+        if( type() != lhs.type() ) return false;\r
+\r
+        return v_ == lhs.v_; \r
+    }\r
+\r
+    template< class Config >\r
+    Value_type Value_impl< Config >::type() const\r
+    {\r
+        return type_;\r
+    }\r
+\r
+    template< class Config >\r
+    bool Value_impl< Config >::is_uint64() const\r
+    {\r
+        return is_uint64_;\r
+    }\r
+\r
+    template< class Config >\r
+    bool Value_impl< Config >::is_null() const\r
+    {\r
+        return type() == null_type;\r
+    }\r
+\r
+    template< class Config >\r
+    void Value_impl< Config >::check_type( const Value_type vtype ) const\r
+    {\r
+        if( type() != vtype ) \r
+        {\r
+            std::ostringstream os;\r
+\r
+            os << "value type is " << type() << " not " << vtype;\r
+\r
+            throw std::runtime_error( os.str() );\r
+        }\r
+    }\r
+\r
+    template< class Config >\r
+    const typename Config::String_type& Value_impl< Config >::get_str() const\r
+    {\r
+        check_type(  str_type );\r
+\r
+        return *boost::get< String_type >( &v_ );\r
+    }\r
+\r
+    template< class Config >\r
+    const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const\r
+    {\r
+        check_type( obj_type );\r
+\r
+        return *boost::get< Object >( &v_ );\r
+    }\r
+     \r
+    template< class Config >\r
+    const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const\r
+    {\r
+        check_type(  array_type );\r
+\r
+        return *boost::get< Array >( &v_ );\r
+    }\r
+     \r
+    template< class Config >\r
+    bool Value_impl< Config >::get_bool() const\r
+    {\r
+        check_type(  bool_type );\r
+\r
+        return boost::get< bool >( v_ );\r
+    }\r
+     \r
+    template< class Config >\r
+    int Value_impl< Config >::get_int() const\r
+    {\r
+        check_type(  int_type );\r
+\r
+        return static_cast< int >( get_int64() );\r
+    }\r
+    \r
+    template< class Config >\r
+    boost::int64_t Value_impl< Config >::get_int64() const\r
+    {\r
+        check_type(  int_type );\r
+\r
+        return boost::get< boost::int64_t >( v_ );\r
+    }\r
+    \r
+    template< class Config >\r
+    boost::uint64_t Value_impl< Config >::get_uint64() const\r
+    {\r
+        check_type(  int_type );\r
+\r
+        return static_cast< boost::uint64_t >( get_int64() );\r
+    }\r
+\r
+    template< class Config >\r
+    double Value_impl< Config >::get_real() const\r
+    {\r
+        if( type() == int_type )\r
+        {\r
+            return is_uint64() ? static_cast< double >( get_uint64() )\r
+                               : static_cast< double >( get_int64() );\r
+        }\r
+\r
+        check_type(  real_type );\r
+\r
+        return boost::get< double >( v_ );\r
+    }\r
+\r
+    template< class Config >\r
+    typename Value_impl< Config >::Object& Value_impl< Config >::get_obj()\r
+    {\r
+        check_type(  obj_type );\r
+\r
+        return *boost::get< Object >( &v_ );\r
+    }\r
+\r
+    template< class Config >\r
+    typename Value_impl< Config >::Array& Value_impl< Config >::get_array()\r
+    {\r
+        check_type(  array_type );\r
+\r
+        return *boost::get< Array >( &v_ );\r
+    }\r
+\r
+    template< class Config >\r
+    Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value )\r
+    :   name_( name )\r
+    ,   value_( value )\r
+    {\r
+    }\r
+\r
+    template< class Config >\r
+    bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const\r
+    {\r
+        if( this == &lhs ) return true;\r
+\r
+        return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ );\r
+    }\r
+\r
+    // converts a C string, ie. 8 bit char array, to a string object\r
+    //\r
+    template < class String_type >\r
+    String_type to_str( const char* c_str )\r
+    {\r
+        String_type result;\r
+\r
+        for( const char* p = c_str; *p != 0; ++p )\r
+        {\r
+            result += *p;\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    //\r
+\r
+    namespace internal_\r
+    {\r
+        template< typename T >\r
+        struct Type_to_type\r
+        {\r
+        };\r
+\r
+        template< class Value > \r
+        int get_value( const Value& value, Type_to_type< int > )\r
+        {\r
+            return value.get_int();\r
+        }\r
+       \r
+        template< class Value > \r
+        boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > )\r
+        {\r
+            return value.get_int64();\r
+        }\r
+       \r
+        template< class Value > \r
+        boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > )\r
+        {\r
+            return value.get_uint64();\r
+        }\r
+       \r
+        template< class Value > \r
+        double get_value( const Value& value, Type_to_type< double > )\r
+        {\r
+            return value.get_real();\r
+        }\r
+       \r
+        template< class Value > \r
+        typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > )\r
+        {\r
+            return value.get_str();\r
+        }\r
+       \r
+        template< class Value > \r
+        typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > )\r
+        {\r
+            return value.get_array();\r
+        }\r
+       \r
+        template< class Value > \r
+        typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > )\r
+        {\r
+            return value.get_obj();\r
+        }\r
+       \r
+        template< class Value > \r
+        bool get_value( const Value& value, Type_to_type< bool > )\r
+        {\r
+            return value.get_bool();\r
+        }\r
+    }\r
+\r
+    template< class Config >\r
+    template< typename T > \r
+    T Value_impl< Config >::get_value() const\r
+    {\r
+        return internal_::get_value( *this, internal_::Type_to_type< T >() );\r
+    }\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_writer.cpp b/json/json_spirit_writer.cpp
new file mode 100644 (file)
index 0000000..f3367b6
--- /dev/null
@@ -0,0 +1,95 @@
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#include "json_spirit_writer.h"\r
+#include "json_spirit_writer_template.h"\r
+\r
+void json_spirit::write( const Value& value, std::ostream& os )\r
+{\r
+    write_stream( value, os, false );\r
+}\r
+\r
+void json_spirit::write_formatted( const Value& value, std::ostream& os )\r
+{\r
+    write_stream( value, os, true );\r
+}\r
+\r
+std::string json_spirit::write( const Value& value )\r
+{\r
+    return write_string( value, false );\r
+}\r
+\r
+std::string json_spirit::write_formatted( const Value& value )\r
+{\r
+    return write_string( value, true );\r
+}\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+void json_spirit::write( const wValue& value, std::wostream& os )\r
+{\r
+    write_stream( value, os, false );\r
+}\r
+\r
+void json_spirit::write_formatted( const wValue& value, std::wostream& os )\r
+{\r
+    write_stream( value, os, true );\r
+}\r
+\r
+std::wstring json_spirit::write( const wValue&  value )\r
+{\r
+    return write_string( value, false );\r
+}\r
+\r
+std::wstring json_spirit::write_formatted( const wValue&  value )\r
+{\r
+    return write_string( value, true );\r
+}\r
+\r
+#endif\r
+\r
+void json_spirit::write( const mValue& value, std::ostream& os )\r
+{\r
+    write_stream( value, os, false );\r
+}\r
+\r
+void json_spirit::write_formatted( const mValue& value, std::ostream& os )\r
+{\r
+    write_stream( value, os, true );\r
+}\r
+\r
+std::string json_spirit::write( const mValue& value )\r
+{\r
+    return write_string( value, false );\r
+}\r
+\r
+std::string json_spirit::write_formatted( const mValue& value )\r
+{\r
+    return write_string( value, true );\r
+}\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+void json_spirit::write( const wmValue& value, std::wostream& os )\r
+{\r
+    write_stream( value, os, false );\r
+}\r
+\r
+void json_spirit::write_formatted( const wmValue& value, std::wostream& os )\r
+{\r
+    write_stream( value, os, true );\r
+}\r
+\r
+std::wstring json_spirit::write( const wmValue&  value )\r
+{\r
+    return write_string( value, false );\r
+}\r
+\r
+std::wstring json_spirit::write_formatted( const wmValue&  value )\r
+{\r
+    return write_string( value, true );\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_writer.h b/json/json_spirit_writer.h
new file mode 100644 (file)
index 0000000..1b67b51
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef JSON_SPIRIT_WRITER\r
+#define JSON_SPIRIT_WRITER\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r
+# pragma once\r
+#endif\r
+\r
+#include "json_spirit_value.h"\r
+#include <iostream>\r
+\r
+namespace json_spirit\r
+{\r
+    // functions to convert JSON Values to text, \r
+    // the "formatted" versions add whitespace to format the output nicely\r
+\r
+    void         write          ( const Value& value, std::ostream&  os );\r
+    void         write_formatted( const Value& value, std::ostream&  os );\r
+    std::string  write          ( const Value& value );\r
+    std::string  write_formatted( const Value& value );\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+    void         write          ( const wValue& value, std::wostream& os );\r
+    void         write_formatted( const wValue& value, std::wostream& os );\r
+    std::wstring write          ( const wValue& value );\r
+    std::wstring write_formatted( const wValue& value );\r
+\r
+#endif\r
+\r
+    void         write          ( const mValue& value, std::ostream&  os );\r
+    void         write_formatted( const mValue& value, std::ostream&  os );\r
+    std::string  write          ( const mValue& value );\r
+    std::string  write_formatted( const mValue& value );\r
+\r
+#ifndef BOOST_NO_STD_WSTRING\r
+\r
+    void         write          ( const wmValue& value, std::wostream& os );\r
+    void         write_formatted( const wmValue& value, std::wostream& os );\r
+    std::wstring write          ( const wmValue& value );\r
+    std::wstring write_formatted( const wmValue& value );\r
+\r
+#endif\r
+}\r
+\r
+#endif\r
diff --git a/json/json_spirit_writer_template.h b/json/json_spirit_writer_template.h
new file mode 100644 (file)
index 0000000..c993756
--- /dev/null
@@ -0,0 +1,245 @@
+#ifndef JSON_SPIRIT_WRITER_TEMPLATE\r
+#define JSON_SPIRIT_WRITER_TEMPLATE\r
+\r
+//          Copyright John W. Wilkinson 2007 - 2009.\r
+// Distributed under the MIT License, see accompanying file LICENSE.txt\r
+\r
+// json spirit version 4.03\r
+\r
+#include "json_spirit_value.h"\r
+\r
+#include <cassert>\r
+#include <sstream>\r
+#include <iomanip>\r
+\r
+namespace json_spirit\r
+{\r
+    inline char to_hex_char( unsigned int c )\r
+    {\r
+        assert( c <= 0xF );\r
+\r
+        const char ch = static_cast< char >( c );\r
+\r
+        if( ch < 10 ) return '0' + ch;\r
+\r
+        return 'A' - 10 + ch;\r
+    }\r
+\r
+    template< class String_type >\r
+    String_type non_printable_to_string( unsigned int c )\r
+    {\r
+        typedef typename String_type::value_type Char_type;\r
+\r
+        String_type result( 6, '\\' );\r
+\r
+        result[1] = 'u';\r
+\r
+        result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;\r
+        result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;\r
+        result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;\r
+        result[ 2 ] = to_hex_char( c & 0x000F );\r
+\r
+        return result;\r
+    }\r
+\r
+    template< typename Char_type, class String_type >\r
+    bool add_esc_char( Char_type c, String_type& s )\r
+    {\r
+        switch( c )\r
+        {\r
+            case '"':  s += to_str< String_type >( "\\\"" ); return true;\r
+            case '\\': s += to_str< String_type >( "\\\\" ); return true;\r
+            case '\b': s += to_str< String_type >( "\\b"  ); return true;\r
+            case '\f': s += to_str< String_type >( "\\f"  ); return true;\r
+            case '\n': s += to_str< String_type >( "\\n"  ); return true;\r
+            case '\r': s += to_str< String_type >( "\\r"  ); return true;\r
+            case '\t': s += to_str< String_type >( "\\t"  ); return true;\r
+        }\r
+\r
+        return false;\r
+    }\r
+\r
+    template< class String_type >\r
+    String_type add_esc_chars( const String_type& s )\r
+    {\r
+        typedef typename String_type::const_iterator Iter_type;\r
+        typedef typename String_type::value_type     Char_type;\r
+\r
+        String_type result;\r
+\r
+        const Iter_type end( s.end() );\r
+\r
+        for( Iter_type i = s.begin(); i != end; ++i )\r
+        {\r
+            const Char_type c( *i );\r
+\r
+            if( add_esc_char( c, result ) ) continue;\r
+\r
+            const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );\r
+\r
+            if( iswprint( unsigned_c ) )\r
+            {\r
+                result += c;\r
+            }\r
+            else\r
+            {\r
+                result += non_printable_to_string< String_type >( unsigned_c );\r
+            }\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    // this class generates the JSON text,\r
+    // it keeps track of the indentation level etc.\r
+    //\r
+    template< class Value_type, class Ostream_type >\r
+    class Generator\r
+    {\r
+        typedef typename Value_type::Config_type Config_type;\r
+        typedef typename Config_type::String_type String_type;\r
+        typedef typename Config_type::Object_type Object_type;\r
+        typedef typename Config_type::Array_type Array_type;\r
+        typedef typename String_type::value_type Char_type;\r
+        typedef typename Object_type::value_type Obj_member_type;\r
+\r
+    public:\r
+\r
+        Generator( const Value_type& value, Ostream_type& os, bool pretty )\r
+        :   os_( os )\r
+        ,   indentation_level_( 0 )\r
+        ,   pretty_( pretty )\r
+        {\r
+            output( value );\r
+        }\r
+\r
+    private:\r
+\r
+        void output( const Value_type& value )\r
+        {\r
+            switch( value.type() )\r
+            {\r
+                case obj_type:   output( value.get_obj() );   break;\r
+                case array_type: output( value.get_array() ); break;\r
+                case str_type:   output( value.get_str() );   break;\r
+                case bool_type:  output( value.get_bool() );  break;\r
+                case int_type:   output_int( value );         break;\r
+                case real_type:  os_ << std::showpoint << std::setprecision( 16 ) \r
+                                     << value.get_real();     break;\r
+                case null_type:  os_ << "null";               break;\r
+                default: assert( false );\r
+            }\r
+        }\r
+\r
+        void output( const Object_type& obj )\r
+        {\r
+            output_array_or_obj( obj, '{', '}' );\r
+        }\r
+\r
+        void output( const Array_type& arr )\r
+        {\r
+            output_array_or_obj( arr, '[', ']' );\r
+        }\r
+\r
+        void output( const Obj_member_type& member )\r
+        {\r
+            output( Config_type::get_name( member ) ); space(); \r
+            os_ << ':'; space(); \r
+            output( Config_type::get_value( member ) );\r
+        }\r
+\r
+        void output_int( const Value_type& value )\r
+        {\r
+            if( value.is_uint64() )\r
+            {\r
+                os_ << value.get_uint64();\r
+            }\r
+            else\r
+            {\r
+               os_ << value.get_int64();\r
+            }\r
+        }\r
+\r
+        void output( const String_type& s )\r
+        {\r
+            os_ << '"' << add_esc_chars( s ) << '"';\r
+        }\r
+\r
+        void output( bool b )\r
+        {\r
+            os_ << to_str< String_type >( b ? "true" : "false" );\r
+        }\r
+\r
+        template< class T >\r
+        void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )\r
+        {\r
+            os_ << start_char; new_line();\r
+\r
+            ++indentation_level_;\r
+            \r
+            for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )\r
+            {\r
+                indent(); output( *i );\r
+\r
+                typename T::const_iterator next = i;\r
+\r
+                if( ++next != t.end())\r
+                {\r
+                    os_ << ',';\r
+                }\r
+\r
+                new_line();\r
+            }\r
+\r
+            --indentation_level_;\r
+\r
+            indent(); os_ << end_char;\r
+        }\r
+        \r
+        void indent()\r
+        {\r
+            if( !pretty_ ) return;\r
+\r
+            for( int i = 0; i < indentation_level_; ++i )\r
+            { \r
+                os_ << "    ";\r
+            }\r
+        }\r
+\r
+        void space()\r
+        {\r
+            if( pretty_ ) os_ << ' ';\r
+        }\r
+\r
+        void new_line()\r
+        {\r
+            if( pretty_ ) os_ << '\n';\r
+        }\r
+\r
+        Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning\r
+\r
+        Ostream_type& os_;\r
+        int indentation_level_;\r
+        bool pretty_;\r
+    };\r
+\r
+    template< class Value_type, class Ostream_type >\r
+    void write_stream( const Value_type& value, Ostream_type& os, bool pretty )\r
+    {\r
+        Generator< Value_type, Ostream_type >( value, os, pretty );\r
+    }\r
+\r
+    template< class Value_type >\r
+    typename Value_type::String_type write_string( const Value_type& value, bool pretty )\r
+    {\r
+        typedef typename Value_type::String_type::value_type Char_type;\r
+\r
+        std::basic_ostringstream< Char_type > os;\r
+\r
+        write_stream( value, os, pretty );\r
+\r
+        return os.str();\r
+    }\r
+}\r
+\r
+#endif\r