Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81004 - in trunk/libs/spirit/example/qi/json: . build detail json json/detail json/parser parser src test
From: joel_at_[hidden]
Date: 2012-10-17 01:07:57


Author: djowel
Date: 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
New Revision: 81004
URL: http://svn.boost.org/trac/boost/changeset/81004

Log:
readding proper file structure
Added:
   trunk/libs/spirit/example/qi/json/build/
   trunk/libs/spirit/example/qi/json/build/Jamfile (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/
   trunk/libs/spirit/example/qi/json/json/detail/
   trunk/libs/spirit/example/qi/json/json/detail/io_impl.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/detail/util_impl.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/detail/value_impl.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/io.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/parser/
   trunk/libs/spirit/example/qi/json/json/parser/grammar.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/parser/grammar_def.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/util.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/json/value.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/src/
   trunk/libs/spirit/example/qi/json/src/io.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/src/value.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/ (props changed)
   trunk/libs/spirit/example/qi/json/test/Jamfile (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/get.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/get_as.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/test.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/value_array.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/value_basic.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/value_construct.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/value_non_container.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/test/value_object.cpp (contents, props changed)
Removed:
   trunk/libs/spirit/example/qi/json/detail/
   trunk/libs/spirit/example/qi/json/io.hpp
   trunk/libs/spirit/example/qi/json/parser/
   trunk/libs/spirit/example/qi/json/test.cpp
   trunk/libs/spirit/example/qi/json/util.hpp
   trunk/libs/spirit/example/qi/json/value.hpp
Properties modified:
   trunk/libs/spirit/example/qi/json/ (props changed)

Added: trunk/libs/spirit/example/qi/json/build/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/build/Jamfile 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2012 ciere consulting, ciere.com
+# Copyright (C) 2010, 2011 Object Modeling Designs
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+
+import os ;
+local BOOST_ROOT = [ os.environ BOOST_ROOT ] ;
+
+if $(BOOST_ROOT)
+{
+ use-project /boost : $(BOOST_ROOT) ;
+}
+
+project /ciere/json
+ : source-location ../src
+ : requirements <toolset>gcc:<cxxflags>-ftemplate-depth-300
+ : usage-requirements <include>..
+ : default-build <threading>multi
+ : build-dir ../lib
+ ;
+
+
+lib json
+ : [ glob ../src/*.cpp ]
+ /boost//headers
+ :
+ :
+ : <include>..
+ ;
+

Deleted: trunk/libs/spirit/example/qi/json/io.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/json/io.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
+++ (empty file)
@@ -1,45 +0,0 @@
-/**
- * Copyright (C) 2012 ciere consulting, ciere.com
- * Copyright (C) 2011, 2012 Object Modeling Designs
- *
- * Distributed under the Boost Software License, Version 1.0. (See accompanying
- * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- *
- *
- */
-
-#ifndef CIERE_JSON_IO_HPP
-#define CIERE_JSON_IO_HPP
-
-#include <iostream>
-#include <string>
-#include "value.hpp"
-
-namespace ciere { namespace json
-{
-
- std::ostream& operator<<(std::ostream& stream, value const & value);
-
- std::istream& operator>>( std::istream& stream, value& object );
-
- /**
- * Reads from filename and populates object with the contents of the filename.
- */
- bool read( std::string const & filename, value& object);
-
- /**
- * Read from stream and populate object with json contents
- */
- bool read( std::istream& stream, value& object);
-
- /**
- * construct a json value from the input string
- */
- value construct( std::string const & input );
-
-}}
-
-
-#include "detail/io_impl.hpp"
-
-#endif // CIERE_JSON_IO_HPP

Added: trunk/libs/spirit/example/qi/json/json/detail/io_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/detail/io_impl.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,208 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ *
+ */
+
+#ifndef CIERE_JSON_IO_IMPL_HPP
+#define CIERE_JSON_IO_IMPL_HPP
+
+#include <string>
+#include <fstream>
+#include <istream>
+#include <ios>
+#include <boost/foreach.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_istream_iterator.hpp>
+
+#include "../io.hpp"
+#include "../parser/grammar.hpp"
+
+namespace ciere { namespace json
+{
+ namespace spirit = boost::spirit;
+
+ namespace detail
+ {
+ struct printer : public boost::static_visitor<>
+ {
+ printer(std::ostream& s) : stream(s) {}
+
+ void operator()(string_t const & utf) const
+ {
+ stream << '"';
+
+ typedef ::boost::uint32_t ucs4_char;
+ typedef boost::u8_to_u32_iterator<std::string::const_iterator> iter_t;
+ iter_t f = utf.begin();
+ iter_t l = utf.end();
+
+ for (iter_t i = f; i != l; ++i)
+ {
+ ucs4_char c = *i;
+ switch (c)
+ {
+ case 0: stream << "\\0"; break;
+ case 0x7: stream << "\\a"; break;
+ case 0x8: stream << "\\b"; break;
+ case 0x9: stream << "\\t"; break;
+ case 0xA: stream << "\\n"; break;
+ case 0xB: stream << "\\v"; break;
+ case 0xC: stream << "\\f"; break;
+ case 0xD: stream << "\\r"; break;
+ case 0x1B: stream << "\\e"; break;
+ case '"': stream << "\\\""; break;
+ case '\\': stream << "\\\\"; break;
+ case 0xA0: stream << "\\_"; break;
+ case 0x85: stream << "\\N"; break;
+ case 0x2028: stream << "\\L"; break;
+ case 0x2029: stream << "\\P"; break;
+ default: stream << boost::spirit::to_utf8(c);
+ }
+ }
+
+ stream << '"';
+ }
+
+ template< typename T >
+ void operator()(T const & value) const
+ {
+ stream << value;
+ }
+
+ void operator()(double d) const
+ {
+ // javascript's handling of NaN and +/-Infinity
+ // isn't so great. JSON simply follows the javascript
+ // standard. We can output nan and infinity; however,
+ // we cannot actually parse it back in afaict because
+ // the javascript side is generating a null?
+ //
+ // TODO: clear this up with something definitive
+ if(boost::math::isnan(d))
+ {
+ stream << "NaN";
+ return;
+ }
+ if(boost::math::isinf(d))
+ {
+ if(d < 0.0) { stream << '-'; }
+ stream << "Infinity";
+ return;
+ }
+ stream << d;
+ }
+
+ void operator()(bool_t value) const
+ {
+ stream << (value?"true":"false");
+ }
+
+ void operator()(null_t value) const
+ {
+ stream << "null";
+ }
+
+ void operator()(object_t const & obj) const
+ {
+ stream << "{";
+ bool first = true;
+
+ BOOST_FOREACH( object_t::value_type const & v, obj )
+ {
+ if( first ) { first = false; }
+ else { stream << ", "; }
+
+ stream << '"' << v.first << "\":";
+ boost::apply_visitor( *this,v.second);
+ }
+
+ stream << "}";
+ }
+
+ void operator()(array_t const & arr) const
+ {
+ stream << "[";
+ bool first = true;
+
+ BOOST_FOREACH( value const & v, arr )
+ {
+ if( first ) { first = false; }
+ else { stream << ", "; }
+
+ boost::apply_visitor(*this,v);
+ }
+ stream << "]";
+ }
+
+ std::ostream& stream;
+ };
+ }
+
+ inline std::ostream& operator<<(std::ostream& stream, value const & v)
+ {
+ boost::apply_visitor(detail::printer(stream),v);
+ return stream;
+ }
+
+ inline std::istream& operator>>( std::istream& stream, value& object )
+ {
+ if( !json::read( stream, object ) )
+ {
+ stream.setstate( std::ios_base::failbit );
+ }
+
+ return stream;
+ }
+
+ inline bool read( std::istream& stream, value& object)
+ {
+ typedef parser::grammar< spirit::istream_iterator > grammar_t;
+
+ stream.unsetf( std::ios::skipws );
+ spirit::istream_iterator iter( stream );
+ spirit::istream_iterator end_iter;
+
+ grammar_t grammar;
+ return( spirit::qi::phrase_parse( iter, end_iter,
+ grammar,
+ spirit::ascii::space_type(),
+ object ) );
+ }
+
+ inline bool read( std::string const & filename, value& object)
+ {
+ std::ifstream stream( filename.c_str() );
+ if( !stream.is_open() )
+ {
+ return false;
+ }
+
+ return read( stream, object );
+ }
+
+ inline value construct( std::string const & input )
+ {
+ typedef std::string::const_iterator iter_t;
+ typedef parser::grammar<iter_t> grammar_t;
+
+ grammar_t grammar;
+ json::value value;
+
+ iter_t iter = input.begin();
+ iter_t end = input.end();
+
+ spirit::qi::phrase_parse( iter, end,
+ grammar,
+ spirit::ascii::space_type(),
+ value );
+
+ return value;
+ }
+}}
+
+#endif // CIERE_JSON_IO_IMPL_HPP

Added: trunk/libs/spirit/example/qi/json/json/detail/util_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/detail/util_impl.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ *
+ */
+
+#ifndef CIERE_JSON_UTIL_IMPL_HPP
+#define CIERE_JSON_UTIL_IMPL_HPP
+
+#include "../util.hpp"
+
+namespace ciere { namespace json
+{
+ namespace detail
+ {
+ }
+
+ /**
+ * Returns true if elements of m match those value.
+ */
+ bool match( value const & value, value const & m )
+ {
+ return false;
+ }
+
+ /**
+ * Results in : target = target + value
+ */
+ bool combine( value& target, value const & value )
+ {
+ return false;
+ }
+
+}}
+
+#endif // CIERE_JSON_UTIL_IMPL_HPP

Added: trunk/libs/spirit/example/qi/json/json/detail/value_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/detail/value_impl.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,280 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2012 Jeroen Habraken
+ * Copyright (c) 2011 Joel de Guzman
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef CIERE_JSON_VALUE_IMPL_HPP
+#define CIERE_JSON_VALUE_IMPL_HPP
+
+#include <iostream> //test
+
+#include "../value.hpp"
+#include <boost/lexical_cast.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/assert.hpp>
+
+namespace ciere { namespace json
+{
+ namespace detail
+ {
+ template< typename T >
+ struct extract
+ {
+ template<typename A>
+ static T get(A & v) { return boost::get<T>(v); }
+
+ template<typename A>
+ static const T get(const A & v) { return boost::get<T>(v); }
+ };
+
+
+ template<typename R>
+ struct convert
+ {
+ BOOST_MPL_ASSERT_MSG(
+ !(boost::is_same<R,null_t>::value)
+ , CANNOT_GET_AS_WITH_NULL_T
+ , (R)
+ );
+
+ template<typename T>
+ static R apply( T const & v
+ , typename boost::enable_if<boost::is_convertible<R,T> >::type* dummy=0 )
+ {
+ return v;
+ }
+
+
+ static R apply( string_t const & v )
+ {
+ return boost::lexical_cast<R>(v);
+ }
+
+ template<typename T>
+ static R apply( T const & v
+ , typename boost::disable_if<boost::is_convertible<R,T> >::type* dummy=0 )
+ {
+ throw get_as_error();
+ return R();
+ }
+ };
+
+ template<>
+ struct convert<string_t>
+ {
+ static string_t apply( string_t const & v)
+ {
+ return v;
+ }
+
+ static string_t apply( float_t const & v )
+ {
+ return boost::lexical_cast<std::string>(v);
+ }
+
+ static string_t apply( int_t const & v )
+ {
+ return boost::lexical_cast<std::string>(v);
+ }
+
+ static string_t apply( bool_t const & v)
+ {
+ return (v ? "true" : "false");
+ }
+
+ static string_t apply( null_t const & )
+ {
+ return "null";
+ }
+
+ template<typename T>
+ static string_t apply( T const & v )
+ {
+ throw get_as_error();
+ return "";
+ }
+ };
+
+
+ template<>
+ struct convert<bool_t>
+ {
+ template<typename T>
+ static bool_t apply( T const & v
+ , typename boost::enable_if<boost::is_convertible<bool_t,T> >::type* dummy=0 )
+ {
+ return v;
+ }
+
+ static bool_t apply( string_t const & v )
+ {
+ if( v == "true" ) return true;
+ else return false;
+ }
+
+ template<typename T>
+ static bool_t apply( T const & v
+ , typename boost::disable_if<boost::is_convertible<bool_t,T> >::type* dummy=0 )
+ {
+ throw get_as_error();
+ return false;
+ }
+ };
+
+
+
+ template<typename T>
+ struct convert_to : public boost::static_visitor<T>
+ {
+ template<typename V>
+ T operator()(V const & v) const
+ {
+ try
+ {
+ return convert<T>::apply(v);
+ }
+ catch(...)
+ {
+ throw get_as_error();
+ }
+ }
+
+ // if the types are the same, no conversion required
+ T operator()(T const & v) const
+ {
+ return v;
+ }
+ };
+ }
+
+
+ struct value::make_json_value
+ {
+ json::value& operator()(json::value& v) const { return v; }
+ const json::value& operator()(const json::value& v) const { return v; }
+ };
+
+ struct value::make_json_member
+ {
+ value::member operator()(object_t::value_type & v) const { return value::member(v); }
+ value::const_member operator()(const object_t::value_type & v) const { return value::const_member(v); }
+ };
+
+
+ // -------------------------------------------------------------------------------
+ // array handling
+ // -------------------------------------------------------------------------------
+
+ /**
+ * Add compatible type to the end of the array
+ */
+ template< typename T >
+ value& value::add( T v )
+ {
+ push_back(v);
+ return *this;
+ }
+
+
+ /**
+ * Add a compatible type to the end of the array, functor style.
+ */
+ template< typename T >
+ value& value::operator()( T v )
+ {
+ return add(v);
+ }
+
+ /**
+ * Add compatible type to the end of the array, stl style-ish
+ * Actually returns a reference the newly added value.
+ */
+ template< typename T >
+ value& value::push_back( T v )
+ {
+ array_t* p_array = boost::get<array_t>(&base_type::get());
+
+ // if we aren't an array, we need to be an array
+ if( !p_array )
+ {
+ base_type::get() = array_t();
+ p_array = boost::get<array_t>(&base_type::get());
+ }
+
+ p_array->push_back( (json::value(v)) );
+ return p_array->back();
+ }
+
+
+ // -------------------------------------------------------------------------------
+ // object handling
+ // -------------------------------------------------------------------------------
+
+ template< typename T >
+ value& value::set( string_t const & name, T v )
+ {
+ object_t* p_object = boost::get<object_t>(&base_type::get());
+
+ // if this isn't an object type ... it needs to be
+ if( !p_object )
+ {
+ base_type::get() = object_t();
+ p_object = boost::get<object_t>(&base_type::get());
+ }
+
+ (*p_object)[name] = v;
+ return *this;
+ }
+
+
+ template< typename T >
+ value& value::operator()( string_t const & name, T v )
+ {
+ return set(name,v);
+ }
+
+
+ // -------------------------------------------------------------------------------
+ // Extract based on type
+ // -------------------------------------------------------------------------------
+ template< typename T >
+ T value::get()
+ {
+ return detail::extract<T>::get(base_type::get());
+ }
+
+ template< typename T >
+ const T value::get() const
+ {
+ return detail::extract<T>::get(base_type::get());
+ }
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+ // -------------------------------------------------------------------------------
+ // Extract based on type and convert to requested type
+ // -------------------------------------------------------------------------------
+ template< typename T >
+ T value::get_as()
+ {
+ return boost::apply_visitor(detail::convert_to<T>(),base_type::get());
+ }
+
+ template< typename T >
+ const T value::get_as() const
+ {
+ return boost::apply_visitor(detail::convert_to<T>(),base_type::get());
+ }
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+}}
+
+#endif // CIERE_JSON_VALUE_IMPL_HPP

Added: trunk/libs/spirit/example/qi/json/json/io.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/io.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ *
+ */
+
+#ifndef CIERE_JSON_IO_HPP
+#define CIERE_JSON_IO_HPP
+
+#include <iostream>
+#include <string>
+#include "value.hpp"
+
+namespace ciere { namespace json
+{
+
+ std::ostream& operator<<(std::ostream& stream, value const & value);
+
+ std::istream& operator>>( std::istream& stream, value& object );
+
+ /**
+ * Reads from filename and populates object with the contents of the filename.
+ */
+ bool read( std::string const & filename, value& object);
+
+ /**
+ * Read from stream and populate object with json contents
+ */
+ bool read( std::istream& stream, value& object);
+
+ /**
+ * construct a json value from the input string
+ */
+ value construct( std::string const & input );
+
+}}
+
+
+#include "detail/io_impl.hpp"
+
+#endif // CIERE_JSON_IO_HPP

Added: trunk/libs/spirit/example/qi/json/json/parser/grammar.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/parser/grammar.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef CIERE_JSON_DETAIL_GRAMMAR_HPP
+#define CIERE_JSON_DETAIL_GRAMMAR_HPP
+
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <string>
+#include <boost/spirit/include/qi.hpp>
+#include "../value.hpp"
+
+
+namespace ciere { namespace json { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ namespace detail
+ {
+ template <typename Iterator>
+ struct unicode_string : qi::grammar<Iterator, std::string()>
+ {
+ unicode_string();
+ qi::rule<Iterator, void(std::string&)> escape;
+ qi::rule<Iterator, void(std::string&)> char_esc;
+ qi::rule<Iterator, std::string()> double_quoted;
+ };
+ }
+
+
+ template< typename Iterator >
+ struct grammar : qi::grammar< Iterator, json::value(), ascii::space_type >
+ {
+ grammar();
+ qi::rule< Iterator, json::value() , ascii::space_type > value;
+ qi::rule< Iterator, json::object_t() , ascii::space_type > object;
+ qi::rule< Iterator, json::object_member_t() , ascii::space_type > member_pair;
+ qi::rule< Iterator, json::array_t() , ascii::space_type > array;
+ detail::unicode_string< Iterator > string_value;
+ qi::rule< Iterator, json::null_t() , ascii::space_type > null_value;
+ };
+
+}}}
+
+#endif // CIERE_JSON_DETAIL_GRAMMAR_HPP

Added: trunk/libs/spirit/example/qi/json/json/parser/grammar_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/parser/grammar_def.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,174 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (c) 2011 Joel de Guzman
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef CIERE_JSON_DETAIL_GRAMMAR_DEF_HPP
+#define CIERE_JSON_DETAIL_GRAMMAR_DEF_HPP
+
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <string>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/fusion/adapted/std_pair.hpp>
+#include "grammar.hpp"
+
+
+namespace ciere { namespace json { namespace parser
+{
+
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ typedef boost::uint32_t uchar; // a unicode code point
+
+ namespace detail
+ {
+ struct push_utf8
+ {
+ template <typename S, typename C>
+ struct result { typedef void type; };
+
+ void operator()(std::string& utf8, uchar code_point) const
+ {
+ typedef std::back_insert_iterator<std::string> insert_iter;
+ insert_iter out_iter(utf8);
+ boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter);
+ *utf8_iter++ = code_point;
+ }
+ };
+
+ struct push_esc
+ {
+ template <typename S, typename C>
+ struct result { typedef void type; };
+
+ void operator()(std::string& utf8, uchar c) const
+ {
+ switch (c)
+ {
+ case ' ': utf8 += ' '; break;
+ case '\t': utf8 += '\t'; break;
+ case '0': utf8 += char(0); break;
+ case 'a': utf8 += 0x7; break;
+ case 'b': utf8 += 0x8; break;
+ case 't': utf8 += 0x9; break;
+ case 'n': utf8 += 0xA; break;
+ case 'v': utf8 += 0xB; break;
+ case 'f': utf8 += 0xC; break;
+ case 'r': utf8 += 0xD; break;
+ case 'e': utf8 += 0x1B; break;
+ case '"': utf8 += '"'; break;
+ case '/': utf8 += '/'; break;
+ case '\\': utf8 += '\\'; break;
+
+ case '_': push_utf8()(utf8, 0xA0); break;
+ case 'N': push_utf8()(utf8, 0x85); break;
+ case 'L': push_utf8()(utf8, 0x2028); break;
+ case 'P': push_utf8()(utf8, 0x2029); break;
+ }
+ }
+ };
+
+
+ template< typename Iterator >
+ unicode_string<Iterator>::unicode_string()
+ : unicode_string::base_type(double_quoted)
+ {
+ qi::char_type char_;
+ qi::_val_type _val;
+ qi::_r1_type _r1;
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::lit_type lit;
+ qi::eol_type eol;
+ qi::repeat_type repeat;
+ qi::hex_type hex;
+
+ using boost::spirit::qi::uint_parser;
+ using boost::phoenix::function;
+ using boost::phoenix::ref;
+
+ uint_parser<uchar, 16, 4, 4> hex4;
+ uint_parser<uchar, 16, 8, 8> hex8;
+ function<detail::push_utf8> push_utf8;
+ function<detail::push_esc> push_esc;
+
+ escape =
+ ('x' > hex) [push_utf8(_r1, _1)]
+ | ('u' > hex4) [push_utf8(_r1, _1)]
+ | ('U' > hex8) [push_utf8(_r1, _1)]
+ | char_("0abtnvfre\"/\\N_LP \t") [push_esc(_r1, _1)]
+ | eol // continue to next line
+ ;
+
+ char_esc =
+ '\\' > escape(_r1)
+ ;
+
+ double_quoted =
+ '"'
+ > *(char_esc(_val) | (~char_('"')) [_val += _1])
+ > '"'
+ ;
+ }
+
+ } // end detail
+
+
+ template< typename Iterator >
+ grammar<Iterator>::grammar()
+ : grammar::base_type( value )
+ {
+ qi::_val_type _val;
+ qi::lit_type lit;
+ ascii::char_type char_;
+ qi::double_type double_;
+ qi::int_parser<int64_t> int_;
+ qi::bool_type bool_value;
+ qi::attr_type attr;
+ qi::lexeme_type lexeme;
+
+ value =
+ null_value
+ | bool_value
+ | string_value
+ | lexeme[int_ >> !char_(".eE")]
+ | double_
+ | object
+ | array
+ ;
+
+ object =
+ lit('{')
+ >> -(member_pair % ',')
+ >> lit('}')
+ ;
+
+ member_pair =
+ string_value
+ >> ':'
+ >> value
+ ;
+
+ array =
+ lit('[')
+ >> -(value % ',')
+ >> lit(']')
+ ;
+
+ null_value =
+ lit("null")
+ >> attr(json::null_t())
+ ;
+ }
+
+}}}
+
+
+#endif // CIERE_JSON_DETAIL_GRAMMAR_DEF_HPP

Added: trunk/libs/spirit/example/qi/json/json/util.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/util.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ *
+ */
+
+#ifndef CIERE_JSON_UTIL_HPP
+#define CIERE_JSON_UTIL_HPP
+
+#include <iostream>
+#include <string>
+#include "value.hpp"
+
+namespace ciere { namespace json
+{
+ /**
+ * Returns true if elements of m match those value.
+ */
+ bool match( value const & value, value const & m );
+
+ /**
+ * Results in : target = target + value
+ */
+ bool combine( value& target, value const & value );
+}}
+
+
+#endif // CIERE_JSON_UTIL_HPP

Added: trunk/libs/spirit/example/qi/json/json/value.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/json/value.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,390 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2012 Jeroen Habraken
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef CIERE_JSON_VALUE_HPP
+#define CIERE_JSON_VALUE_HPP
+
+#include <string>
+#include <boost/variant.hpp>
+#include <boost/exception/all.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/spirit/include/support_extended_variant.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/utility/enable_if.hpp>
+
+
+namespace ciere { namespace json
+{
+
+ // ---------------------------------------------------
+ // exceptions
+ // ---------------------------------------------------
+
+ struct not_container_type : virtual boost::exception, virtual std::exception {};
+ struct not_object_type : virtual boost::exception, virtual std::exception {};
+ struct not_array_type : virtual boost::exception, virtual std::exception {};
+ struct not_number_type : virtual boost::exception, virtual std::exception {};
+ struct get_as_error : virtual boost::exception, virtual std::exception {};
+
+ // ---------------------------------------------------
+ // ---------------------------------------------------
+
+
+ // ------------------- ast types --------------------
+ //
+ typedef std::string string_t;
+ typedef double double_t;
+ typedef double float_t;
+ typedef int64_t int_t;
+ typedef bool bool_t;
+ struct null_t
+ {};
+ class value;
+ typedef std::map<std::string, value> object_t;
+ typedef std::pair<std::string, value> object_member_t;
+ typedef boost::container::stable_vector<value> array_t;
+
+
+ // nulls always compare
+ inline bool operator==(null_t,null_t) { return true; }
+ inline bool operator!=(null_t,null_t) { return false; }
+
+ inline std::ostream & operator<<(std::ostream & out, null_t)
+ { out << "null"; return out; }
+
+
+
+ /**
+ * possible types being stored in the json::value
+ */
+ enum value_types
+ {
+ string_type,
+ double_type,
+ int_type,
+ bool_type,
+ null_type,
+ value_type,
+ object_type,
+ array_type
+ };
+
+
+ /**
+ *
+ *
+ */
+ class value
+ : public boost::spirit::extended_variant<
+ null_t
+ , bool_t
+ , string_t
+ , int_t
+ , double_t
+ , object_t
+ , array_t >
+ {
+ public:
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+ value(null_t val = null_t()) : base_type(val) {}
+ value(bool_t val) : base_type(val) {}
+ value(string_t const & val) : base_type(val) {}
+ value(char const * val) : base_type((string_t(val))) {}
+ value(object_t const & val) : base_type(val) {}
+ value(array_t const & val) : base_type(val) {}
+ value(value const & rhs) : base_type(rhs.get_ast()) {}
+
+ template< typename T >
+ value(T val,
+ typename boost::enable_if<boost::is_floating_point<T> >::type* = 0)
+ : base_type( (double_t(val)) ) {}
+
+
+ template< typename T >
+ value(T val,
+ typename boost::enable_if<
+ boost::mpl::or_<
+ boost::is_integral<T>
+ , boost::is_enum<T>
+ >
+ >::type* = 0)
+ : base_type( (int_t(val)) ) {}
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+ /**
+ * Returns the type currently being stored
+ */
+ value_types type() const;
+
+
+ // -------------------------------------------------------------------------------
+ // iterator helpers
+ // -------------------------------------------------------------------------------
+ /**
+ * type returned from an object iterator
+ */
+ struct member
+ {
+ member(object_t::value_type & m) : member_pair(m) {}
+
+ std::string name() const { return member_pair.first; }
+ json::value & value() { return member_pair.second; }
+ json::value const & value() const { return member_pair.second; }
+
+ private:
+ object_t::value_type & member_pair;
+ };
+
+ struct const_member
+ {
+ const_member(object_t::value_type & m) : member_pair(m) {}
+ const_member(object_t::value_type const & m) : member_pair(m) {}
+
+ std::string name() const { return member_pair.first; }
+ const json::value & value() const { return member_pair.second; }
+
+ private:
+ object_t::value_type const & member_pair;
+ };
+
+
+ // -------------------------------------------------------------------------------
+ // iterator types
+ // -------------------------------------------------------------------------------
+
+ private:
+ struct make_json_value;
+ struct make_json_member;
+
+ public:
+ typedef boost::transform_iterator< make_json_member
+ , object_t::iterator
+ , member > object_iterator;
+
+ typedef boost::transform_iterator< make_json_member
+ , object_t::const_iterator
+ , const_member > const_object_iterator;
+
+ typedef boost::transform_iterator< make_json_value
+ , array_t::iterator
+ , value & > array_iterator;
+
+ typedef boost::transform_iterator< make_json_value
+ , array_t::const_iterator
+ , value const & > const_array_iterator;
+
+
+
+
+ // -------------------------------------------------------------------------------
+ // iterator access
+ // -------------------------------------------------------------------------------
+
+ /**
+ * Returns an iterator pointing to the fist member in the object if the value type
+ * is object_type. Otherwise, throw not_object_type.
+ */
+ object_iterator begin_object();
+ const_object_iterator begin_object() const;
+
+ /**
+ * Returns an iterator that can be compared to determine the end of members in an object. If
+ * the value type is not an object then throw not_object_type.
+ */
+ object_iterator end_object();
+ const_object_iterator end_object() const;
+
+ /**
+ * Returns an iterator pointing to the fist member in the array if the value type
+ * is array_type. Otherwise, throw not_array_type.
+ */
+ array_iterator begin_array();
+ const_array_iterator begin_array() const;
+
+ /**
+ * Returns an iterator that can be compared to determine the end of members in an array. If the
+ * value type is not array_type throw not_array_type.
+ */
+ array_iterator end_array();
+ const_array_iterator end_array() const;
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+
+ // -------------------------------------------------------------------------------
+ // array handling
+ // -------------------------------------------------------------------------------
+
+ /**
+ * Add compatible type to the end of the array
+ */
+ template< typename T >
+ value & add(T v);
+ value & add(char const * v);
+
+ /**
+ * Add a compatible type to the end of the array, functor style.
+ */
+ template< typename T >
+ value & operator()(T v);
+
+ /**
+ * Add compatible type to the end of the array, stl style-ish
+ * Actually returns a reference the newly added value.
+ */
+ template< typename T >
+ value & push_back(T v);
+ value & push_back(char const * v);
+
+ /**
+ * Access array element stored at index value. Will throw out_of_range exception
+ * if index is not a valid index for the container.
+ */
+ value & at(size_t index);
+ value const & at(size_t index) const;
+
+ /**
+ * Access array element stored at index value. If the array length is less than
+ * index, the array will be expanded to index + 1 length and additional
+ * locations will be filled with null_type.
+ */
+ value & operator[](int index);
+ value const & operator[](int index) const;
+
+ /**
+ * Erase removes the value at index.
+ */
+ value & erase(int index);
+
+
+ /**
+ * Returns the number of elements stored if the value is holding an array or
+ * object type. If it is not an array or object type the method throws
+ * ciere::json::not_array_type
+ */
+ std::size_t length() const;
+
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+ // -------------------------------------------------------------------------------
+ // object handling
+ // -------------------------------------------------------------------------------
+
+ /**
+ * Set the member name to value v.
+ * If member name already exists, its value will be replaced.
+ *
+ * If the value object is not an object type it will become one.
+ */
+ template< typename T >
+ value & set(string_t const & name, T v);
+
+ // template can be ambigous for some types ... lets get specific
+ value & set(string_t const & name, char const * v);
+
+ /**
+ * Functor style setting. The first value is the name of the member to add.
+ * the second value is the value to be set.
+ */
+ template< typename T >
+ value & operator()(string_t const & name, T v);
+
+ /**
+ * Tests if the object contains the specified named object.
+ */
+ bool has_key(std::string const & key) const;
+
+ /**
+ * Access the object's member with the specified name.
+ * If no member exists, one will be created with a default value
+ * of null_t.
+ */
+ value & operator[](char const * v);
+ value & operator[](string_t const & v);
+ value const & operator[](char const * v) const;
+ value const & operator[](string_t const & v) const;
+
+ value & erase(char const * v){ return erase( (string_t(v)) ); }
+ value & erase(string_t const & v);
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+ /**
+ * Extract the actual value based on the type T. If the json::value
+ * does not contain type T, the method will throw.
+ */
+ template< typename T >
+ T get();
+
+ template< typename T >
+ const T get() const;
+
+ /**
+ * Extract the contained value as if it is of type T. If the
+ * contained type is not of type T, the value will be converted
+ * if it can. If no conversion can be found, it will throw.
+ */
+ template< typename T >
+ T get_as();
+
+ template< typename T >
+ const T get_as() const;
+
+
+ // -------------------------------------------------------------------------------
+ // conversion
+ // -------------------------------------------------------------------------------
+
+ operator string_t() const;
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+ base_type::variant_type & get_ast() { return base_type::get(); }
+ base_type::variant_type const & get_ast() const { return base_type::get(); }
+ };
+
+
+ /**
+ * Constructs a value containing an array type
+ */
+ value array();
+
+ /**
+ * Constructs a value containing an object type
+ */
+ value object();
+
+ bool operator==(value const & a, value const & b);
+ bool operator!=(value const & a, value const & b);
+ bool operator<(value const & a, value const & b);
+
+}}
+
+#include "detail/value_impl.hpp"
+
+
+#endif // CIERE_JSON_VALUE_HPP

Added: trunk/libs/spirit/example/qi/json/src/io.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/src/io.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,17 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include <string>
+#include "../json/value.hpp"
+#include "../json/parser/grammar_def.hpp"
+#include <boost/spirit/include/support_istream_iterator.hpp>
+
+typedef std::string::const_iterator string_iter_t;
+
+template struct ciere::json::parser::grammar<string_iter_t>;
+template struct ciere::json::parser::grammar<boost::spirit::istream_iterator>;

Added: trunk/libs/spirit/example/qi/json/src/value.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/src/value.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,438 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2011, 2012 Object Modeling Designs
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ *
+ */
+
+#include "../json/value.hpp"
+#include <boost/variant.hpp>
+
+namespace ciere { namespace json
+{
+ namespace detail
+ {
+ struct value_compare
+ {
+ typedef bool result_type;
+
+ template <typename A, typename B>
+ bool operator()(A const& a, B const& b) const
+ {
+ return false;
+ }
+
+ template <typename T>
+ bool operator()(T const& a, T const& b) const
+ {
+ return a < b;
+ }
+
+ bool operator()(double_t const& a, int_t const& b) const
+ {
+ return a < b;
+ }
+
+ bool operator()(int_t const& a, double_t const& b) const
+ {
+ return a < b;
+ }
+
+ bool operator()(object_t const& a, object_t const& b)
+ {
+ return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+ }
+
+ bool operator()(array_t const& a, array_t const& b)
+ {
+ return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+ }
+ };
+
+
+ struct value_equal
+ {
+ typedef bool result_type;
+
+ template <typename A, typename B>
+ bool operator()(A const& a, B const& b) const
+ {
+ return false;
+ }
+
+ template <typename T>
+ bool operator()(T const& a, T const& b) const
+ {
+ return a == b;
+ }
+
+ bool operator()(double_t const& a, int_t const& b) const
+ {
+ return a == b;
+ }
+
+ bool operator()(int_t const& a, double_t const& b) const
+ {
+ return a == b;
+ }
+
+ bool operator()(object_t const& a, object_t const& b)
+ {
+ if(a.size() != b.size()) { return false; }
+
+ object_t::const_iterator ii = b.begin();
+ for( object_t::const_iterator i = a.begin(); i != a.end(); ++i )
+ {
+ if (*i != *ii++){ return false; }
+ }
+ return true;
+ }
+
+ bool operator()(array_t const& a, array_t const& b)
+ {
+ if(a.size() != b.size()) { return false; }
+
+ array_t::const_iterator ii = b.begin();
+ for( array_t::const_iterator i = a.begin(); i != a.end(); ++i )
+ {
+ if(*i != *ii++) { return false; }
+ }
+ return true;
+ }
+ };
+
+
+ struct get_type : public boost::static_visitor<value_types>
+ {
+ value_types operator()(string_t) const { return string_type; }
+ value_types operator()(int_t) const { return int_type; }
+ value_types operator()(double_t) const { return double_type; }
+ value_types operator()(bool_t) const { return bool_type; }
+ value_types operator()(null_t) const { return null_type; }
+ value_types operator()(object_t) const { return object_type; }
+ value_types operator()(array_t) const { return array_type; }
+ };
+
+
+
+ struct get_length : public boost::static_visitor<std::size_t>
+ {
+ std::size_t operator()(const object_t& v) const { return v.size() ; }
+ std::size_t operator()(const array_t& v) const { return v.size() ; }
+
+ template< typename T >
+ std::size_t operator()(const T&) const { boost::throw_exception( (not_container_type()) ); }
+ };
+
+
+ struct has_key_visitor : public boost::static_visitor<bool>
+ {
+ has_key_visitor(const object_t::key_type & key) : key_(key) {}
+
+ template< typename T >
+ bool operator()(const T&) const { return false; }
+
+ bool operator()(const object_t & v) const { return v.find(key_) != v.end(); }
+
+ const object_t::key_type & key_;
+ };
+
+
+ } // namespace detail
+
+
+ value_types value::type() const
+ {
+ return boost::apply_visitor(detail::get_type(),*this);
+ }
+
+ std::size_t value::length() const
+ {
+ return boost::apply_visitor(detail::get_length(),*this);
+ }
+
+ // -------------------------------------------------------------------------------
+ // iterator access
+ // -------------------------------------------------------------------------------
+
+ /**
+ * Returns an iterator pointing to the fist member in the object if the value type
+ * is object_type. Otherwise, throw not_object_type.
+ */
+ value::object_iterator value::begin_object()
+ {
+ object_t* p_object = boost::get<object_t>(&base_type::get());
+ if( !p_object ){ boost::throw_exception( (not_object_type()) ); }
+ return object_iterator(p_object->begin(),value::make_json_member());
+ }
+
+ value::const_object_iterator value::begin_object() const
+ {
+ const object_t* p_object = boost::get<object_t>(&base_type::get());
+ if( !p_object ){ boost::throw_exception( (not_object_type()) ); }
+ return const_object_iterator(p_object->begin(),value::make_json_member());
+ }
+
+ /**
+ * Returns an iterator that can be compared to determine the end of members in an object. If
+ * the value object_type is in an object then throw not_object_type.
+ */
+ value::object_iterator value::end_object()
+ {
+ object_t* p_object = boost::get<object_t>(&base_type::get());
+ if( !p_object ){ boost::throw_exception( not_object_type() ); }
+ return object_iterator(p_object->end(),value::make_json_member());
+ }
+
+ value::const_object_iterator value::end_object() const
+ {
+ const object_t* p_object = boost::get<object_t>(&base_type::get());
+ if( !p_object ){ boost::throw_exception( not_object_type() ); }
+ return const_object_iterator(p_object->end(),value::make_json_member());
+ }
+
+ /**
+ * Returns an iterator pointing to the fist member in the array if the value type
+ * is array_type. Otherwise, throw not_array_type.
+ */
+ value::array_iterator value::begin_array()
+ {
+ array_t* p_array = boost::get<array_t>(&base_type::get());
+ if( !p_array ){ boost::throw_exception( not_array_type() ); }
+ return array_iterator(p_array->begin(),value::make_json_value());
+ }
+
+ value::const_array_iterator value::begin_array() const
+ {
+ const array_t* p_array = boost::get<array_t>(&base_type::get());
+ if( !p_array ){ boost::throw_exception( not_array_type() ); }
+ return const_array_iterator(p_array->begin(),value::make_json_value());
+ }
+
+ /**
+ * Returns an iterator that can be compared to determine the end of the array. If
+ * the value type is in an array_type then throw not_array_type.
+ */
+ value::array_iterator value::end_array()
+ {
+ array_t* p_array = boost::get<array_t>(&base_type::get());
+ if( !p_array ){ boost::throw_exception( not_array_type() ); }
+ return array_iterator(p_array->end(),value::make_json_value());
+ }
+
+ value::const_array_iterator value::end_array() const
+ {
+ const array_t* p_array = boost::get<array_t>(&base_type::get());
+ if( !p_array ){ boost::throw_exception( not_array_type() ); }
+ return const_array_iterator(p_array->end(),value::make_json_value());
+ }
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+ // -------------------------------------------------------------------------------
+ // array handling
+ // -------------------------------------------------------------------------------
+
+
+ value& value::add( const char* v )
+ {
+ return add( string_t(v) );
+ }
+
+
+ value& value::push_back( const char* v )
+ {
+ return push_back( string_t(v) );
+ }
+
+
+ /**
+ * Access array element stored at index value. Will throw out_of_range exception
+ * if index is not a valid index for the container.
+ */
+ value& value::at( size_t index )
+ {
+ array_t* p_array = boost::get<array_t>(&base_type::get());
+
+ // if this isn't an array type ... throw bad type instead of the out_of_range
+ if( !p_array ){ boost::throw_exception( not_array_type() ); }
+
+ // container's at method will throw out_of_range if the index is out of range
+ return p_array->at(index);
+ }
+
+
+ const value& value::at( size_t index ) const
+ {
+ const array_t* p_array = boost::get<array_t>(&base_type::get());
+
+ // if this isn't an array type ... throw bad type instead of the out_of_range
+ if( !p_array ){ boost::throw_exception( not_array_type() ); }
+
+ // container's at method will throw out_of_range if the index is out of range
+ return p_array->at(index);
+ }
+
+
+ /**
+ * Access array element stored at index value. If the array length is less than
+ * index, the array will be expanded to index + 1 length and additional
+ * locations will be filled with null_type.
+ */
+ value& value::operator[](int index)
+ {
+ array_t* p_array = boost::get<array_t>(&base_type::get());
+
+ // if this isn't an array type ... it needs to be
+ if( !p_array )
+ {
+ base_type::get() = array_t();
+ p_array = boost::get<array_t>(&base_type::get());
+ }
+
+ // make sure that we are sized appropriately for the index being requested
+ if( p_array->size() < std::size_t(index+1) )
+ {
+ p_array->resize(index+1,null_t());
+ }
+
+ return (*p_array)[index];
+ }
+
+ const value& value::operator[](int index) const
+ {
+ const array_t* p_array = boost::get<array_t>(&base_type::get());
+
+ // if this isn't an array type or if the index is out of range ... we can't fix it (const)
+ if( !p_array ) { boost::throw_exception( not_array_type() ); }
+ if( p_array->size() < std::size_t(index+1) ){ throw std::out_of_range("json::value array index"); }
+
+ return (*p_array)[index];
+ }
+
+ value& value::erase(int index)
+ {
+ array_t* p_array = boost::get<array_t>(&base_type::get());
+
+ // if this isn't an array type or if the index is out of range then throw
+ if( !p_array ) { boost::throw_exception( not_array_type() ); }
+ if( p_array->size() < std::size_t(index+1) ){ throw std::out_of_range("json::value array index"); }
+ p_array->erase( p_array->begin() + index );
+
+ return *this;
+ }
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+ // -------------------------------------------------------------------------------
+ // object handling
+ // -------------------------------------------------------------------------------
+
+ value& value::set( string_t const & name, const char* v )
+ {
+ return set( name, string_t(v) );
+ }
+
+ bool value::has_key(const std::string & key) const
+ {
+ object_t::key_type key_(key);
+ return boost::apply_visitor(detail::has_key_visitor(key_),*this);
+ }
+
+ value& value::operator[]( const char* v )
+ {
+ return (*this)[string_t(v)];
+ }
+
+ value& value::operator[]( const string_t& v )
+ {
+ object_t* p_object = boost::get<object_t>(&base_type::get());
+
+ // if this isn't an object type ... it needs to be
+ if( !p_object )
+ {
+ base_type::get() = object_t();
+ p_object = boost::get<object_t>(&base_type::get());
+ }
+
+ return (*p_object)[v];
+ }
+
+
+ const value& value::operator[]( const char* v ) const
+ {
+ return (*this)[string_t(v)];
+ }
+
+
+ const value& value::operator[]( const string_t& v ) const
+ {
+ const object_t* p_object = boost::get<object_t>(&base_type::get());
+
+ if( !p_object ){ boost::throw_exception( not_object_type() ); }
+
+ object_t::const_iterator iter = p_object->find(v);
+
+ // if we don't have a member with the requested name we throw because it is const
+ if( iter == p_object->end() ){ throw std::out_of_range("json::value object member name"); }
+
+ return iter->second;
+ }
+
+ value& value::erase(string_t const & v)
+ {
+ object_t* p_object = boost::get<object_t>(&base_type::get());
+
+ if( !p_object ){ boost::throw_exception( (not_object_type()) ); }
+
+ p_object->erase(v);
+
+ return *this;
+ }
+
+ // -------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------------
+
+
+
+ // ----------------------------------------------------------------
+ // comparisons
+ // ----------------------------------------------------------------
+
+ bool operator==(value const& a, value const& b)
+ {
+ return boost::apply_visitor(detail::value_equal(), a.get_ast(), b.get_ast());
+ }
+
+ bool operator!=(value const& a, value const& b)
+ {
+ return !(a == b);
+ }
+
+ bool operator<(value const& a, value const& b)
+ {
+ return boost::apply_visitor(detail::value_compare(), a.get_ast(), b.get_ast());
+ }
+
+ // ----------------------------------------------------------------
+ // ----------------------------------------------------------------
+
+
+ value::operator string_t() const
+ {
+ return boost::get<string_t>(base_type::get());
+ }
+
+
+ value array() { return array_t(); }
+ value object(){ return object_t(); }
+
+}} // namespace ciere::json
+

Deleted: trunk/libs/spirit/example/qi/json/test.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/json/test.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
+++ (empty file)
@@ -1,78 +0,0 @@
-/**
- * Copyright (C) 2012 ciere consulting, ciere.com
- * Copyright (C) 2010, 2011 Object Modeling Designs
- */
-
-#include <boost/detail/lightweight_test.hpp>
-#include "value.hpp"
-#include "io.hpp"
-#include "parser/grammar.hpp"
-#include "parser/grammar_def.hpp"
-
-
-int main()
-{
- boost::spirit::ascii::space_type space;
-
- {
- typedef std::string::const_iterator iter_t;
- typedef ciere::json::parser::grammar<iter_t> grammar_t;
-
- std::string test_input(
- "{"
- " \"value\" : 12.34,"
- " \"on\" : false,"
- " \"jump\" : null,"
- " \"result\" : [1,34.5,{},\"Sosa did fine.\\u263A\",\"Snowman: \\u2603\"]"
- "}"
- );
-
- grammar_t grammar;
- ciere::json::value value;
-
- std::cout << "test input: " << test_input << std::endl;
-
- iter_t iter = test_input.begin();
- iter_t end = test_input.end();
-
- BOOST_TEST( boost::spirit::qi::phrase_parse( iter, end, grammar, space, value ) );
- BOOST_TEST( iter == end );
-
- std::cout << "ast : " << value << std::endl;
- }
-
- {
- typedef std::string::const_iterator iter_t;
- typedef ciere::json::parser::grammar<iter_t> grammar_t;
-
- std::string test_input(
- "{"
- " \"foo\":123.456,"
- " \"the_value\": 42,"
- " \"bar\":[1,\"some test \", {\"on\":false,\"object\":null}],"
- " \"gorp\":\"how about this mom\""
- "}"
- );
-
- grammar_t grammar;
- ciere::json::value value;
-
- std::cout << "test input: " << test_input << std::endl;
-
- iter_t iter = test_input.begin();
- iter_t end = test_input.end();
-
- BOOST_TEST( boost::spirit::qi::phrase_parse( iter, end, grammar, space, value ) );
- BOOST_TEST( iter == end );
-
- std::cout << "ast : " << value << std::endl;
- value["bar"].erase(1);
- std::cout << "ast post erase : " << value << std::endl;
- value.erase("bar");
- std::cout << "ast post erase : " << value << std::endl;
- }
-
- BOOST_TEST(0); // show some output
- return boost::report_errors();
-}
-

Added: trunk/libs/spirit/example/qi/json/test/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/Jamfile 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2012 ciere consulting, ciere.com
+# Copyright (C) 2010, 2011 Object Modeling Designs
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+import os ;
+import testing ;
+
+project /ciere/json/test
+ : requirements $(TARGET_REQUIREMENTS)
+ <toolset>gcc:<cxxflags>-std=c++0x
+ <toolset>clang:<cxxflags>-std=c++0x
+ <toolset>clang:<cxxflags>-stdlib=libc++
+ <define>BOOST_ALL_NO_LIB=1
+ : default-build <threading>multi
+ : build-dir bin
+ ;
+
+
+{
+ test-suite json_testing :
+
+ [ run test.cpp
+ ../build//json
+ : : : : ]
+
+ [ run value_basic.cpp
+ ../build//json
+ : : : : ]
+
+ [ run get.cpp
+ ../build//json
+ : : : : ]
+
+ [ run get_as.cpp
+ ../build//json
+ : : : : ]
+
+ [ run value_object.cpp
+ ../build//json
+ : : : : ]
+
+ [ run value_array.cpp
+ ../build//json
+ : : : : ]
+
+ [ run value_construct.cpp
+ ../build//json
+ : : : : ]
+
+ [ run value_non_container.cpp
+ ../build//json
+ : : : : ]
+
+ ;
+}
+
+

Added: trunk/libs/spirit/example/qi/json/test/get.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/get.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+#include <string>
+
+#define SHOULD_HAVE_THROWN 0
+
+namespace json = ciere::json;
+
+int main()
+{
+ json::value value;
+
+ {
+ value = "test";
+ std::string tmp = value.get<json::string_t>();
+ BOOST_TEST(tmp == "test");
+
+ try
+ {
+ value.get<json::int_t>();
+ BOOST_TEST(SHOULD_HAVE_THROWN);
+ }
+ catch(...){}
+ }
+
+
+ {
+ value = 42;
+ int tmp = value.get<json::int_t>();
+ BOOST_TEST(tmp == 42);
+
+ try
+ {
+ value.get<json::float_t>();
+ BOOST_TEST(SHOULD_HAVE_THROWN);
+ }
+ catch(...){}
+ }
+
+
+ {
+ value = 42.3;
+ double tmp = value.get<json::float_t>();
+ BOOST_TEST(tmp == 42.3);
+
+ try
+ {
+ value.get<json::int_t>();
+ BOOST_TEST(SHOULD_HAVE_THROWN);
+ }
+ catch(...){}
+ }
+
+
+
+ {
+ value = false;
+ bool tmp = value.get<json::bool_t>();
+ BOOST_TEST(tmp == false);
+
+ try
+ {
+ value.get<json::int_t>();
+ BOOST_TEST(SHOULD_HAVE_THROWN);
+ }
+ catch(...){}
+ }
+
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/spirit/example/qi/json/test/get_as.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/get_as.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,79 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+#include <string>
+
+#define SHOULD_HAVE_THROWN 0
+
+namespace json = ciere::json;
+
+int main()
+{
+ json::value value;
+
+ {
+ value = "test";
+ std::string tmp = value.get_as<json::string_t>();
+ BOOST_TEST(tmp == "test");
+ }
+
+
+ {
+ value = 42;
+ int tmp = value.get_as<json::int_t>();
+ BOOST_TEST(tmp == 42);
+ std::string tmp_str = value.get_as<json::string_t>();
+ BOOST_TEST(tmp_str == "42");
+ double tmp_dbl = value.get_as<json::float_t>();
+ BOOST_TEST(tmp_dbl == 42.0);
+ }
+
+
+ {
+ value = 42.5;
+ double tmp = value.get<json::float_t>();
+ BOOST_TEST(tmp == 42.5);
+ std::string tmp_str = value.get_as<json::string_t>();
+ BOOST_TEST(tmp_str == "42.5");
+ int tmp_int = value.get_as<json::int_t>();
+ BOOST_TEST(tmp_int == 42);
+ }
+
+
+ {
+ value = false;
+ bool tmp = value.get_as<json::bool_t>();
+ BOOST_TEST(tmp == false);
+ int tmp_int = value.get_as<int>();
+ BOOST_TEST(tmp_int == 0);
+ }
+
+ {
+ value = "true";
+ BOOST_TEST(true == value.get_as<json::bool_t>());
+ }
+
+ {
+ value = 42;
+ BOOST_TEST(true == value.get_as<json::bool_t>());
+ value = 0;
+ BOOST_TEST(false == value.get_as<json::bool_t>());
+ }
+
+ {
+ value = "42";
+ BOOST_TEST(42 == value.get_as<int>());
+ }
+
+
+ {
+ value = json::null_t();
+ }
+
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/spirit/example/qi/json/test/test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/test.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+#include "json/io.hpp"
+#include "json/parser/grammar.hpp"
+#include "json/parser/grammar_def.hpp"
+
+
+int main()
+{
+ boost::spirit::ascii::space_type space;
+
+ {
+ typedef std::string::const_iterator iter_t;
+ typedef ciere::json::parser::grammar<iter_t> grammar_t;
+
+ std::string test_input(
+ "{"
+ " \"value\" : 12.34,"
+ " \"on\" : false,"
+ " \"jump\" : null,"
+ " \"result\" : [1,34.5,{},\"Sosa did fine.\\u263A\",\"Snowman: \\u2603\"]"
+ "}"
+ );
+
+ grammar_t grammar;
+ ciere::json::value value;
+
+ std::cout << "test input: " << test_input << std::endl;
+
+ iter_t iter = test_input.begin();
+ iter_t end = test_input.end();
+
+ BOOST_TEST( boost::spirit::qi::phrase_parse( iter, end, grammar, space, value ) );
+ BOOST_TEST( iter == end );
+
+ std::cout << "ast : " << value << std::endl;
+ }
+
+ {
+ typedef std::string::const_iterator iter_t;
+ typedef ciere::json::parser::grammar<iter_t> grammar_t;
+
+ std::string test_input(
+ "{"
+ " \"foo\":123.456,"
+ " \"the_value\": 42,"
+ " \"bar\":[1,\"some test \", {\"on\":false,\"object\":null}],"
+ " \"gorp\":\"how about this mom\""
+ "}"
+ );
+
+ grammar_t grammar;
+ ciere::json::value value;
+
+ std::cout << "test input: " << test_input << std::endl;
+
+ iter_t iter = test_input.begin();
+ iter_t end = test_input.end();
+
+ BOOST_TEST( boost::spirit::qi::phrase_parse( iter, end, grammar, space, value ) );
+ BOOST_TEST( iter == end );
+
+ std::cout << "ast : " << value << std::endl;
+ value["bar"].erase(1);
+ std::cout << "ast post erase : " << value << std::endl;
+ value.erase("bar");
+ std::cout << "ast post erase : " << value << std::endl;
+ }
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/spirit/example/qi/json/test/value_array.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/value_array.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,130 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include <iostream>
+#include "json/value.hpp"
+
+namespace json = ciere::json;
+
+void const_test( json::value const & value );
+
+void basic_test()
+{
+ json::value v = json::array()(34)("foo")("bar")(1234.5);
+ BOOST_TEST(v.type() == json::array_type);
+ BOOST_TEST(v.length() == 4);
+ BOOST_TEST(v[1] == "foo");
+ v[1] = "gorp";
+ BOOST_TEST(v[1] == "gorp");
+ BOOST_TEST(v.at(1) == "gorp");
+ v.at(1) = "bar";
+ BOOST_TEST(v.at(1) == "bar");
+
+ v[8] = json::array()(0)(1)(2);
+ BOOST_TEST(v.length() == 9);
+ BOOST_TEST(v[8].length() == 3);
+ BOOST_TEST(v[8].type() == json::array_type);
+ BOOST_TEST(v[8][1] == 1);
+
+ v[8][1] = true;
+ BOOST_TEST(v[8][1] == true);
+ BOOST_TEST(v[8][1] != false);
+
+ try
+ {
+ v.at(10); // will throw
+ BOOST_TEST("didn't throw" == 0);
+ }
+ catch(std::out_of_range&){}
+ catch(...)
+ {
+ BOOST_TEST("wrong throw" == 0);
+ }
+}
+
+
+void reference_test()
+{
+ json::value v = json::array()
+ (123)("foo")(false)(json::array()
+ (0)(1)(2)(3)(1234.5))
+ ("bar")("gorp");
+
+ v[4] = v[3];
+
+ BOOST_TEST(v[4].type() == json::array_type);
+ BOOST_TEST(v[4][2] == 2 );
+
+ v[3][2] = "gorp";
+ BOOST_TEST(v[3][2] == "gorp");
+ BOOST_TEST(v[4][2] != "gorp");
+ BOOST_TEST(v[4][2] == 2);
+
+ v[3] = 8;
+ BOOST_TEST(v[4] == json::array()(0)(1)(2)(3)(1234.5) );
+}
+
+
+void iterator_test()
+{
+ json::value v = json::array()(0)(1)(2)(3)(4)(5);
+ json::value::array_iterator iter = v.begin_array();
+ json::value::array_iterator iter_end = v.end_array();
+ int count = 0;
+ while(iter != iter_end)
+ {
+ BOOST_TEST(*iter == count++);
+ *iter = count;
+ ++iter;
+ }
+ BOOST_TEST(count == 6);
+
+ iter = v.begin_array();
+ iter_end = v.end_array();
+ count = 1;
+ while(iter != iter_end)
+ {
+ BOOST_TEST(*iter == count++);
+ ++iter;
+ }
+}
+
+void const_test( json::value const & v )
+{
+ json::value::const_array_iterator iter = v.begin_array();
+ json::value::const_array_iterator iter_end = v.end_array();
+ int count = 0;
+ while(iter != iter_end)
+ {
+ BOOST_TEST(*iter == count++);
+#ifdef COMPILE_ERROR
+ *iter = count; // should create a compile error
+#endif
+ ++iter;
+ }
+ BOOST_TEST(count == 5);
+}
+
+void const_test()
+{
+ json::value v = json::array()(0)(1)(2)(3)(4);
+ const_test(v);
+}
+
+
+int main()
+{
+ basic_test();
+ reference_test();
+ iterator_test();
+ const_test();
+
+ return boost::report_errors();
+}
+
+
+
+

Added: trunk/libs/spirit/example/qi/json/test/value_basic.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/value_basic.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+
+int main()
+{
+ ciere::json::value value;
+
+ value = "test";
+ BOOST_TEST(value == "test");
+
+ value = 42;
+ BOOST_TEST(value == 42);
+
+ value = 42.3;
+ BOOST_TEST(value == 42.3);
+
+ value = false;
+ BOOST_TEST(value == false);
+
+ value = ciere::json::null_t();
+ BOOST_TEST(value == ciere::json::null_t());
+
+ value = ciere::json::array()(123)("foo")("bar")(42.5);
+ BOOST_TEST(value[1] == "foo");
+ BOOST_TEST(value[3] == 42.5);
+
+ value = ciere::json::object()
+ ("number" ,123)
+ ("foo" ,"bar")
+ ("meaning", 42);
+ BOOST_TEST(value["number"] == 123);
+ BOOST_TEST(value["foo"] == "bar");
+ BOOST_TEST(value["meaning"] == 42);
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/spirit/example/qi/json/test/value_construct.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/value_construct.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+#include "json/io.hpp"
+#include "json/parser/grammar_def.hpp"
+
+namespace json = ciere::json;
+
+int main()
+{
+ json::value value;
+
+ BOOST_TEST( value.type() == json::null_type );
+
+ value = json::construct(
+ "{"
+ " \"foo\" : 42 ,"
+ " \"bar\" : 498.5 ,"
+ " \"gorp\" : \"ciere\","
+ " \"bork\" : [\"ciere\",23,false]"
+ "}"
+ );
+
+ BOOST_TEST( value["foo"] == 42 );
+ BOOST_TEST( value["bar"] == 498.5 );
+ BOOST_TEST( value["gorp"] == "ciere" );
+ BOOST_TEST( value["bork"][2] == false );
+
+ return boost::report_errors();
+}
+

Added: trunk/libs/spirit/example/qi/json/test/value_non_container.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/value_non_container.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,232 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ */
+
+#include <string>
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+
+namespace json = ciere::json;
+
+void null_test()
+{
+ // default constructs to null
+ json::value v1;
+ json::value v2;
+ BOOST_TEST(v1 == v2);
+ BOOST_TEST(v1.type() == json::null_type);
+ BOOST_TEST(v1 == json::null_t());
+
+ // should throw with not a container
+ try
+ {
+ v1.length();
+ BOOST_TEST( "throw fail" == 0 );
+ }
+ catch( json::not_container_type & )
+ {}
+ catch(...)
+ {
+ BOOST_TEST( "throw wrong type" == 0 );
+ }
+}
+
+
+void bool_test()
+{
+ json::value v1(true);
+ BOOST_TEST(v1.type() == json::bool_type);
+
+ json::value v2(false);
+ BOOST_TEST(v1.type() == json::bool_type);
+
+ BOOST_TEST(v1 != v2);
+ BOOST_TEST(v1 == true);
+ BOOST_TEST(v2 == false);
+
+ v1 = false;
+ BOOST_TEST(v1 == v2);
+
+ v1 = true;
+ BOOST_TEST(v1 != false);
+
+
+ // should throw with not a container
+ try
+ {
+ v1.length();
+ BOOST_TEST( "throw fail" == 0 );
+ }
+ catch( json::not_container_type & )
+ {}
+ catch(...)
+ {
+ BOOST_TEST( "throw wrong type" == 0 );
+ }
+}
+
+
+void string_test()
+{
+ json::value v1("test");
+ BOOST_TEST(v1.type() == json::string_type);
+ BOOST_TEST(v1 == "test");
+
+ std::string s1("foo");
+ json::value v2(s1);
+ BOOST_TEST(v2 == s1);
+
+ v1 = s1;
+ BOOST_TEST(v1 == v2);
+
+ v1 = "foo";
+ BOOST_TEST(v1 == v2);
+
+ v2 = "gorp";
+ BOOST_TEST(v1 != v2);
+ BOOST_TEST(v1 != std::string("bar"));
+
+ // should throw with not a container
+ try
+ {
+ v1.length();
+ BOOST_TEST( "throw fail" == 0 );
+ }
+ catch( json::not_container_type & )
+ {}
+ catch(...)
+ {
+ BOOST_TEST( "throw wrong type" == 0 );
+ }
+}
+
+
+void int_test()
+{
+ json::value v1(12);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == 12);
+
+ v1 = uint8_t(8);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == 8);
+
+ v1 = int8_t(-10);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == -10);
+
+ v1 = uint16_t(923);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == 923);
+
+ v1 = int16_t(-234);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == -234);
+
+ v1 = uint32_t(98);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == 98);
+
+ v1 = int32_t(-8);
+ BOOST_TEST(v1.type() == json::int_type);
+ BOOST_TEST(v1 == -8);
+
+ json::value v2(-8);
+ BOOST_TEST(v1 == v2);
+ BOOST_TEST(v1 == -8.0);
+
+ // should throw with not a container
+ try
+ {
+ v1.length();
+ BOOST_TEST( "throw fail" == 0 );
+ }
+ catch( json::not_container_type & )
+ {}
+ catch(...)
+ {
+ BOOST_TEST( "throw wrong type" == 0 );
+ }
+}
+
+
+void float_test()
+{
+ json::value v1(1.0);
+ BOOST_TEST(v1.type() == json::double_type);
+ BOOST_TEST(v1 == 1.0);
+
+ v1 = 987.5;
+ BOOST_TEST(v1 == 987.5);
+ BOOST_TEST(v1 != 987.1);
+
+ json::value v2(987.5);
+ BOOST_TEST(v1 == v2);
+
+ double d1 = 4.56342124;
+ json::value v3(d1);
+ BOOST_TEST(v3.type() == json::double_type);
+ BOOST_TEST(v3 == d1);
+ BOOST_TEST(v3 != v1);
+
+ v1 = d1;
+ BOOST_TEST(v1 == v3);
+
+ float f1 = 123.4567;
+ json::value v4(f1);
+ BOOST_TEST(v4.type() == json::double_type);
+ BOOST_TEST(v4 == f1);
+ BOOST_TEST(v4 != v1);
+ v1 = f1;
+ BOOST_TEST(v1 == v4);
+
+ // should throw with not a container
+ try
+ {
+ v1.length();
+ BOOST_TEST( "throw fail" == 0 );
+ }
+ catch( json::not_container_type & )
+ {}
+ catch(...)
+ {
+ BOOST_TEST( "throw wrong type" == 0 );
+ }
+}
+
+
+
+void value_test()
+{
+ json::value v1(1234);
+ json::value v2(v1);
+ BOOST_TEST(v2.type() == json::int_type);
+ BOOST_TEST(v2 == 1234);
+
+ // should throw with not a container
+ try
+ {
+ v1.length();
+ BOOST_TEST( "throw fail" == 0 );
+ }
+ catch( json::not_container_type & )
+ {}
+ catch(...)
+ {
+ BOOST_TEST( "throw wrong type" == 0 );
+ }
+}
+
+
+
+
+int main()
+{
+ null_test();
+ bool_test();
+ int_test();
+ float_test();
+ value_test();
+ return boost::report_errors();
+}
+

Added: trunk/libs/spirit/example/qi/json/test/value_object.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/test/value_object.cpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2012 ciere consulting, ciere.com
+ * Copyright (C) 2010, 2011 Object Modeling Designs
+ */
+
+#include <boost/detail/lightweight_test.hpp>
+#include "json/value.hpp"
+#include "json/io.hpp"
+
+namespace json = ciere::json;
+
+void const_test( json::value const & value );
+
+int main()
+{
+ json::value value;
+
+ BOOST_TEST( value.type() == json::null_type );
+
+ value = ciere::json::object()
+ ("number" ,123)
+ ("foo" ,"bar")
+ ("meaning", 42)
+ ;
+
+ BOOST_TEST( value.type() == json::object_type );
+
+
+ BOOST_TEST(value["number"] == 123);
+ BOOST_TEST(value["foo"] == "bar");
+ BOOST_TEST(value["meaning"] == 42);
+
+ value["number"] = 78.3;
+ BOOST_TEST(value["number"] == 78.3);
+
+ value["foo"] = ciere::json::object()
+ ( "color", "black" )
+ ( "size" , 93 )
+ ( "tone" , ciere::json::null_t() )
+ ;
+
+ BOOST_TEST(value["foo"]["size"] == 93);
+ BOOST_TEST(value["foo"]["color"] == "black");
+
+ value["foo"]["color"] = "blue";
+ BOOST_TEST(value["foo"]["color"] != "black");
+ BOOST_TEST(value["foo"]["color"] == "blue");
+
+ BOOST_TEST(value["foo"].length() == 3);
+
+ json::value::object_iterator iter = value["foo"].begin_object();
+ json::value::object_iterator iter_end = value["foo"].end_object();
+ BOOST_TEST( iter->name() == "color" );
+ BOOST_TEST( iter->value() == "blue" );
+ ++iter;
+ BOOST_TEST( iter->name() == "size" );
+ BOOST_TEST( iter->value() == 93 );
+ ++iter;
+ BOOST_TEST( iter->name() == "tone" );
+ BOOST_TEST( iter->value() == json::null_t() );
+ ++iter;
+ BOOST_TEST( iter == iter_end );
+
+ value.set("bar", json::array()(42)("top")(1234.5) );
+ BOOST_TEST( value.has_key("bar") );
+ BOOST_TEST( !value.has_key("cafe") );
+ BOOST_TEST( value["bar"][2] == 1234.5 );
+
+ value.set("cafe", "open");
+ BOOST_TEST(value["cafe"] == "open" );
+
+ const_test(value);
+
+ return boost::report_errors();
+}
+
+
+
+void const_test( json::value const & value )
+{
+ BOOST_TEST( value.has_key("cafe") );
+
+ try
+ {
+ value["sam"];
+ int should_have_thrown = 1;
+ BOOST_TEST( should_have_thrown == 0 );
+ }
+ catch( std::out_of_range & e )
+ {}
+
+ BOOST_TEST( value["cafe"] == "open" );
+ BOOST_TEST( value["bar"][2] == 1234.5 );
+}
+

Deleted: trunk/libs/spirit/example/qi/json/util.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/json/util.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
+++ (empty file)
@@ -1,32 +0,0 @@
-/**
- * Copyright (C) 2012 ciere consulting, ciere.com
- * Copyright (C) 2011, 2012 Object Modeling Designs
- *
- * Distributed under the Boost Software License, Version 1.0. (See accompanying
- * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- *
- *
- */
-
-#ifndef CIERE_JSON_UTIL_HPP
-#define CIERE_JSON_UTIL_HPP
-
-#include <iostream>
-#include <string>
-#include "value.hpp"
-
-namespace ciere { namespace json
-{
- /**
- * Returns true if elements of m match those value.
- */
- bool match( value const & value, value const & m );
-
- /**
- * Results in : target = target + value
- */
- bool combine( value& target, value const & value );
-}}
-
-
-#endif // CIERE_JSON_UTIL_HPP

Deleted: trunk/libs/spirit/example/qi/json/value.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/json/value.hpp 2012-10-17 01:07:54 EDT (Wed, 17 Oct 2012)
+++ (empty file)
@@ -1,390 +0,0 @@
-/**
- * Copyright (C) 2012 ciere consulting, ciere.com
- * Copyright (C) 2012 Jeroen Habraken
- * Copyright (C) 2011, 2012 Object Modeling Designs
- *
- * Distributed under the Boost Software License, Version 1.0. (See accompanying
- * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-
-#ifndef CIERE_JSON_VALUE_HPP
-#define CIERE_JSON_VALUE_HPP
-
-#include <string>
-#include <boost/variant.hpp>
-#include <boost/exception/all.hpp>
-#include <boost/iterator/transform_iterator.hpp>
-#include <boost/iterator/iterator_facade.hpp>
-#include <boost/container/stable_vector.hpp>
-#include <boost/spirit/include/support_extended_variant.hpp>
-#include <boost/mpl/or.hpp>
-#include <boost/type_traits/is_enum.hpp>
-#include <boost/type_traits/is_floating_point.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/utility/enable_if.hpp>
-
-
-namespace ciere { namespace json
-{
-
- // ---------------------------------------------------
- // exceptions
- // ---------------------------------------------------
-
- struct not_container_type : virtual boost::exception, virtual std::exception {};
- struct not_object_type : virtual boost::exception, virtual std::exception {};
- struct not_array_type : virtual boost::exception, virtual std::exception {};
- struct not_number_type : virtual boost::exception, virtual std::exception {};
- struct get_as_error : virtual boost::exception, virtual std::exception {};
-
- // ---------------------------------------------------
- // ---------------------------------------------------
-
-
- // ------------------- ast types --------------------
- //
- typedef std::string string_t;
- typedef double double_t;
- typedef double float_t;
- typedef int64_t int_t;
- typedef bool bool_t;
- struct null_t
- {};
- class value;
- typedef std::map<std::string, value> object_t;
- typedef std::pair<std::string, value> object_member_t;
- typedef boost::container::stable_vector<value> array_t;
-
-
- // nulls always compare
- inline bool operator==(null_t,null_t) { return true; }
- inline bool operator!=(null_t,null_t) { return false; }
-
- inline std::ostream & operator<<(std::ostream & out, null_t)
- { out << "null"; return out; }
-
-
-
- /**
- * possible types being stored in the json::value
- */
- enum value_types
- {
- string_type,
- double_type,
- int_type,
- bool_type,
- null_type,
- value_type,
- object_type,
- array_type
- };
-
-
- /**
- *
- *
- */
- class value
- : public boost::spirit::extended_variant<
- null_t
- , bool_t
- , string_t
- , int_t
- , double_t
- , object_t
- , array_t >
- {
- public:
- // -------------------------------------------------------------------------------
- // -------------------------------------------------------------------------------
- value(null_t val = null_t()) : base_type(val) {}
- value(bool_t val) : base_type(val) {}
- value(string_t const & val) : base_type(val) {}
- value(char const * val) : base_type((string_t(val))) {}
- value(object_t const & val) : base_type(val) {}
- value(array_t const & val) : base_type(val) {}
- value(value const & rhs) : base_type(rhs.get_ast()) {}
-
- template< typename T >
- value(T val,
- typename boost::enable_if<boost::is_floating_point<T> >::type* = 0)
- : base_type( (double_t(val)) ) {}
-
-
- template< typename T >
- value(T val,
- typename boost::enable_if<
- boost::mpl::or_<
- boost::is_integral<T>
- , boost::is_enum<T>
- >
- >::type* = 0)
- : base_type( (int_t(val)) ) {}
-
- // -------------------------------------------------------------------------------
- // -------------------------------------------------------------------------------
-
- /**
- * Returns the type currently being stored
- */
- value_types type() const;
-
-
- // -------------------------------------------------------------------------------
- // iterator helpers
- // -------------------------------------------------------------------------------
- /**
- * type returned from an object iterator
- */
- struct member
- {
- member(object_t::value_type & m) : member_pair(m) {}
-
- std::string name() const { return member_pair.first; }
- json::value & value() { return member_pair.second; }
- json::value const & value() const { return member_pair.second; }
-
- private:
- object_t::value_type & member_pair;
- };
-
- struct const_member
- {
- const_member(object_t::value_type & m) : member_pair(m) {}
- const_member(object_t::value_type const & m) : member_pair(m) {}
-
- std::string name() const { return member_pair.first; }
- const json::value & value() const { return member_pair.second; }
-
- private:
- object_t::value_type const & member_pair;
- };
-
-
- // -------------------------------------------------------------------------------
- // iterator types
- // -------------------------------------------------------------------------------
-
- private:
- struct make_json_value;
- struct make_json_member;
-
- public:
- typedef boost::transform_iterator< make_json_member
- , object_t::iterator
- , member > object_iterator;
-
- typedef boost::transform_iterator< make_json_member
- , object_t::const_iterator
- , const_member > const_object_iterator;
-
- typedef boost::transform_iterator< make_json_value
- , array_t::iterator
- , value & > array_iterator;
-
- typedef boost::transform_iterator< make_json_value
- , array_t::const_iterator
- , value const & > const_array_iterator;
-
-
-
-
- // -------------------------------------------------------------------------------
- // iterator access
- // -------------------------------------------------------------------------------
-
- /**
- * Returns an iterator pointing to the fist member in the object if the value type
- * is object_type. Otherwise, throw not_object_type.
- */
- object_iterator begin_object();
- const_object_iterator begin_object() const;
-
- /**
- * Returns an iterator that can be compared to determine the end of members in an object. If
- * the value type is not an object then throw not_object_type.
- */
- object_iterator end_object();
- const_object_iterator end_object() const;
-
- /**
- * Returns an iterator pointing to the fist member in the array if the value type
- * is array_type. Otherwise, throw not_array_type.
- */
- array_iterator begin_array();
- const_array_iterator begin_array() const;
-
- /**
- * Returns an iterator that can be compared to determine the end of members in an array. If the
- * value type is not array_type throw not_array_type.
- */
- array_iterator end_array();
- const_array_iterator end_array() const;
-
- // -------------------------------------------------------------------------------
- // -------------------------------------------------------------------------------
-
-
-
- // -------------------------------------------------------------------------------
- // array handling
- // -------------------------------------------------------------------------------
-
- /**
- * Add compatible type to the end of the array
- */
- template< typename T >
- value & add(T v);
- value & add(char const * v);
-
- /**
- * Add a compatible type to the end of the array, functor style.
- */
- template< typename T >
- value & operator()(T v);
-
- /**
- * Add compatible type to the end of the array, stl style-ish
- * Actually returns a reference the newly added value.
- */
- template< typename T >
- value & push_back(T v);
- value & push_back(char const * v);
-
- /**
- * Access array element stored at index value. Will throw out_of_range exception
- * if index is not a valid index for the container.
- */
- value & at(size_t index);
- value const & at(size_t index) const;
-
- /**
- * Access array element stored at index value. If the array length is less than
- * index, the array will be expanded to index + 1 length and additional
- * locations will be filled with null_type.
- */
- value & operator[](int index);
- value const & operator[](int index) const;
-
- /**
- * Erase removes the value at index.
- */
- value & erase(int index);
-
-
- /**
- * Returns the number of elements stored if the value is holding an array or
- * object type. If it is not an array or object type the method throws
- * ciere::json::not_array_type
- */
- std::size_t length() const;
-
-
- // -------------------------------------------------------------------------------
- // -------------------------------------------------------------------------------
-
-
- // -------------------------------------------------------------------------------
- // object handling
- // -------------------------------------------------------------------------------
-
- /**
- * Set the member name to value v.
- * If member name already exists, its value will be replaced.
- *
- * If the value object is not an object type it will become one.
- */
- template< typename T >
- value & set(string_t const & name, T v);
-
- // template can be ambigous for some types ... lets get specific
- value & set(string_t const & name, char const * v);
-
- /**
- * Functor style setting. The first value is the name of the member to add.
- * the second value is the value to be set.
- */
- template< typename T >
- value & operator()(string_t const & name, T v);
-
- /**
- * Tests if the object contains the specified named object.
- */
- bool has_key(std::string const & key) const;
-
- /**
- * Access the object's member with the specified name.
- * If no member exists, one will be created with a default value
- * of null_t.
- */
- value & operator[](char const * v);
- value & operator[](string_t const & v);
- value const & operator[](char const * v) const;
- value const & operator[](string_t const & v) const;
-
- value & erase(char const * v){ return erase( (string_t(v)) ); }
- value & erase(string_t const & v);
-
- // -------------------------------------------------------------------------------
- // -------------------------------------------------------------------------------
-
-
- /**
- * Extract the actual value based on the type T. If the json::value
- * does not contain type T, the method will throw.
- */
- template< typename T >
- T get();
-
- template< typename T >
- const T get() const;
-
- /**
- * Extract the contained value as if it is of type T. If the
- * contained type is not of type T, the value will be converted
- * if it can. If no conversion can be found, it will throw.
- */
- template< typename T >
- T get_as();
-
- template< typename T >
- const T get_as() const;
-
-
- // -------------------------------------------------------------------------------
- // conversion
- // -------------------------------------------------------------------------------
-
- operator string_t() const;
-
- // -------------------------------------------------------------------------------
- // -------------------------------------------------------------------------------
-
-
- base_type::variant_type & get_ast() { return base_type::get(); }
- base_type::variant_type const & get_ast() const { return base_type::get(); }
- };
-
-
- /**
- * Constructs a value containing an array type
- */
- value array();
-
- /**
- * Constructs a value containing an object type
- */
- value object();
-
- bool operator==(value const & a, value const & b);
- bool operator!=(value const & a, value const & b);
- bool operator<(value const & a, value const & b);
-
-}}
-
-#include "detail/value_impl.hpp"
-
-
-#endif // CIERE_JSON_VALUE_HPP


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk