Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81002 - in trunk/libs/spirit/example/qi/json: . detail parser
From: joel_at_[hidden]
Date: 2012-10-16 23:57:44


Author: djowel
Date: 2012-10-16 23:57:41 EDT (Tue, 16 Oct 2012)
New Revision: 81002
URL: http://svn.boost.org/trac/boost/changeset/81002

Log:
added json parser contributed by Michael Caisse
Added:
   trunk/libs/spirit/example/qi/json/
   trunk/libs/spirit/example/qi/json/detail/
   trunk/libs/spirit/example/qi/json/detail/io_impl.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/detail/util_impl.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/detail/value_impl.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/io.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/parser/
   trunk/libs/spirit/example/qi/json/parser/grammar.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/parser/grammar_def.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/util.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/json/value.hpp (contents, props changed)

Added: trunk/libs/spirit/example/qi/json/detail/io_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/detail/io_impl.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/detail/util_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/detail/util_impl.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/detail/value_impl.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/detail/value_impl.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/io.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/io.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/parser/grammar.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/parser/grammar.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/parser/grammar_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/parser/grammar_def.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/util.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/util.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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/value.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/json/value.hpp 2012-10-16 23:57:41 EDT (Tue, 16 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


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