json: move tree parsing code to json::tree

This commit is contained in:
Danny Robson 2015-02-02 21:22:38 +11:00
parent ebd1087087
commit cfc0f8ecd0
11 changed files with 405 additions and 399 deletions

View File

@ -52,9 +52,9 @@ util::colour<T>::BLUE (0.f, 0.f, 1.f, 1.f);
//! Extract a colour object from a JSON node.
//!
//! Data must be an array or 3 or 4 numbers. Guarantees success, or throws a
//! json::type_error.
const json::node&
operator>> (const json::node &node, colour4f &c) {
//! json::tree::type_error.
const json::tree::node&
operator>> (const json::tree::node &node, colour4f &c) {
c.r = static_cast<float> (node[0].as_number ());
c.g = static_cast<float> (node[1].as_number ());
c.b = static_cast<float> (node[2].as_number ());

View File

@ -41,7 +41,7 @@ namespace util {
typedef colour<float> colour4f;
const json::node& operator>> (const json::node&, util::colour4f&);
const json::tree::node& operator>> (const json::tree::node&, util::colour4f&);
std::ostream& operator<< (std::ostream&, const util::colour4f&);
}

View File

@ -44,7 +44,7 @@ using namespace util;
// Parsing
struct parse_context {
parse_context(json::node *_root):
parse_context(json::tree::node *_root):
root (_root),
value (NULL),
key (NULL),
@ -52,7 +52,7 @@ struct parse_context {
stop (NULL)
{ ; }
json::node *root,
json::tree::node *root,
*value,
*key;
const char *start,
@ -76,8 +76,8 @@ struct parse_context {
}
action new_object { nodestack.push_back (parse_context(new json::object)); }
action new_array { nodestack.push_back (parse_context(new json::array)); }
action new_object { nodestack.push_back (parse_context(new json::tree::object)); }
action new_array { nodestack.push_back (parse_context(new json::tree::array)); }
action new_object_value {
CHECK (nodestack.back ().root->is_object ());
@ -87,9 +87,9 @@ struct parse_context {
if (!nodestack.back ().key->is_string ())
throw parse_error ("object keys must be strings");
json::object *object = (json::object*)nodestack.back ().root;
json::tree::object *object = (json::tree::object*)nodestack.back ().root;
object->insert (nodestack.back ().key->as_string (),
unique_ptr<json::node> (nodestack.back ().value));
unique_ptr<json::tree::node> (nodestack.back ().value));
nodestack.back ().key = NULL;
nodestack.back ().value = NULL;
}
@ -98,8 +98,8 @@ struct parse_context {
CHECK (nodestack.back ().root->is_array ());
CHECK (nodestack.back ().value);
json::array *array = (json::array *)nodestack.back ().root;
array->insert (unique_ptr<json::node> (nodestack.back ().value));
json::tree::array *array = (json::tree::array *)nodestack.back ().root;
array->insert (unique_ptr<json::tree::node> (nodestack.back ().value));
nodestack.back ().value = NULL;
}
@ -109,7 +109,7 @@ struct parse_context {
std::string value (std::string (nodestack.back ().start,
nodestack.back ().stop));
nodestack.back ().value = new json::string(value);
nodestack.back ().value = new json::tree::string(value);
}
action new_boolean {
@ -133,14 +133,14 @@ struct parse_context {
double value = strtod (back.start, &end);
if (end == back.start || errno)
throw parse_error ("unable to parse number");
back.value = new json::number (value);
back.value = new json::tree::number (value);
}
action new_null {
CHECK (!nodestack.empty ());
CHECK (!nodestack.back ().value);
nodestack.back().value = new json::null ();
nodestack.back().value = new json::tree::null ();
}
action new_object_key {
@ -199,8 +199,8 @@ struct parse_context {
## other
boolean =
'true' @{ nodestack.back ().value = new json::boolean ( true); }
| 'false' @{ nodestack.back ().value = new json::boolean (false); };
'true' @{ nodestack.back ().value = new json::tree::boolean ( true); }
| 'false' @{ nodestack.back ().value = new json::tree::boolean (false); };
## components
object = '{' @{ fhold; fcall _object; } '}';
@ -242,14 +242,14 @@ struct parse_context {
template <>
bool
is_integer (const json::number &node) {
is_integer (const json::tree::number &node) {
return is_integer (node.native ());
}
template <>
bool
is_integer (const json::node &node) {
is_integer (const json::tree::node &node) {
return node.is_number () &&
is_integer (node.as_number ());
}
@ -258,22 +258,22 @@ is_integer (const json::node &node) {
//-----------------------------------------------------------------------------
// Node
std::unique_ptr<json::node>
json::parse (const boost::filesystem::path &path) {
std::unique_ptr<json::tree::node>
json::tree::parse (const boost::filesystem::path &path) {
auto data = slurp (path);
return parse (static_cast <const char *> (data.get ()));
}
std::unique_ptr<json::node>
json::parse (const std::string &path)
std::unique_ptr<json::tree::node>
json::tree::parse (const std::string &path)
{ return parse (path.c_str (), path.c_str () + path.size ()); }
std::unique_ptr<json::node>
json::parse (const char *start,
std::unique_ptr<json::tree::node>
json::tree::parse (const char *start,
const char *stop) {
bool __success = true;
json::node *__root = nullptr;
json::tree::node *__root = nullptr;
size_t top = 0;
int cs;
deque <int> fsmstack;
@ -292,50 +292,50 @@ json::parse (const char *start,
throw parse_error (os.str ());
}
return std::unique_ptr<json::node> (__root);
return std::unique_ptr<json::tree::node> (__root);
}
std::unique_ptr<json::node>
json::parse (const char *start)
std::unique_ptr<json::tree::node>
json::tree::parse (const char *start)
{ return parse (start, start + strlen (start)); }
void
json::write (const json::node &node, std::ostream &os)
json::tree::write (const json::tree::node &node, std::ostream &os)
{ node.write (os); }
//-----------------------------------------------------------------------------
// Type conversion
const json::object&
json::node::as_object (void) const
const json::tree::object&
json::tree::node::as_object (void) const
{ throw type_error ("node is not an object"); }
const json::array&
json::node::as_array (void) const
const json::tree::array&
json::tree::node::as_array (void) const
{ throw type_error ("node is not an array"); }
const json::string&
json::node::as_string (void) const
const json::tree::string&
json::tree::node::as_string (void) const
{ throw type_error ("node is not a string"); }
const json::number&
json::node::as_number (void) const
const json::tree::number&
json::tree::node::as_number (void) const
{ throw type_error ("node is not a number"); }
const json::boolean&
json::node::as_boolean (void) const
const json::tree::boolean&
json::tree::node::as_boolean (void) const
{ throw type_error ("node is not a boolean"); }
const json::null&
json::node::as_null (void) const
const json::tree::null&
json::tree::node::as_null (void) const
{ throw type_error ("node is not a null"); }
@ -343,38 +343,38 @@ json::node::as_null (void) const
// Global operatoers
bool
json::node::operator!= (const node &rhs) const
json::tree::node::operator!= (const node &rhs) const
{ return !(*this == rhs); }
bool json::node::operator==(const char *rhs) const {
bool json::tree::node::operator==(const char *rhs) const {
try {
return as_string ().native () == rhs;
} catch (const json::type_error&) {
} catch (const json::tree::type_error&) {
return false;
}
}
const json::node&
json::node::operator[] (const std::string &key) const
const json::tree::node&
json::tree::node::operator[] (const std::string &key) const
{ return as_object ()[key]; }
const json::node&
json::node::operator[] (unsigned int idx) const
const json::tree::node&
json::tree::node::operator[] (unsigned int idx) const
{ return as_array()[idx]; }
//-----------------------------------------------------------------------------
// Object
json::object::~object ()
json::tree::object::~object ()
{ ; }
bool
json::object::operator ==(const json::object &rhs) const {
json::tree::object::operator ==(const json::tree::object &rhs) const {
for (auto i = rhs.m_values.begin (), j = m_values.begin ();
i != rhs.m_values.end () && j != m_values.end ();
++i, ++j)
@ -390,17 +390,17 @@ json::object::operator ==(const json::object &rhs) const {
void
json::object::insert (const std::string &_key, unique_ptr<json::node> &&value)
json::tree::object::insert (const std::string &_key, unique_ptr<json::tree::node> &&value)
{ m_values[_key] = move(value); }
const json::node&
json::object::operator[](const std::string &key) const {
const json::tree::node&
json::tree::object::operator[](const std::string &key) const {
auto value = m_values.find (key);
if (value == m_values.end ()) {
ostringstream ss;
ss << "no key: " << key;
throw json::error (ss.str());
throw json::tree::error (ss.str());
}
return *value->second;
@ -408,38 +408,38 @@ json::object::operator[](const std::string &key) const {
bool
json::object::has (const std::string &key) const {
json::tree::object::has (const std::string &key) const {
return m_values.find (key) != m_values.end ();
}
void
json::object::clear (void)
json::tree::object::clear (void)
{ m_values.clear (); }
void
json::object::erase (const std::string &key) {
json::tree::object::erase (const std::string &key) {
auto pos = m_values.find (key);
if (pos == m_values.end ())
throw json::error ("erasing invalid key");
throw json::tree::error ("erasing invalid key");
m_values.erase (key);
}
json::object::const_iterator
json::object::begin (void) const
json::tree::object::const_iterator
json::tree::object::begin (void) const
{ return m_values.begin (); }
json::object::const_iterator
json::object::end (void) const
json::tree::object::const_iterator
json::tree::object::end (void) const
{ return m_values.end (); }
std::ostream&
json::object::write (std::ostream &os) const {
json::tree::object::write (std::ostream &os) const {
os << "{\n";
{
indenter raii(os);
@ -460,17 +460,21 @@ json::object::write (std::ostream &os) const {
//-----------------------------------------------------------------------------
// Array
json::array::~array()
{ ; }
json::tree::array::~array()
{
m_values.clear ();
}
void
json::array::insert (unique_ptr<json::node> &&_value)
{ m_values.push_back (move (_value)); }
json::tree::array::insert (unique_ptr<json::tree::node> &&_value)
{
m_values.push_back (move (_value));
}
bool
json::array::operator ==(const json::array &rhs) const {
json::tree::array::operator ==(const json::tree::array &rhs) const {
for (auto i = rhs.m_values.begin (), j = m_values.begin ();
i != rhs.m_values.end () && j != m_values.end ();
++i, ++j)
@ -481,7 +485,7 @@ json::array::operator ==(const json::array &rhs) const {
std::ostream&
json::array::write (std::ostream &os) const {
json::tree::array::write (std::ostream &os) const {
os << "[\n";
{
indenter raii(os);
@ -502,19 +506,19 @@ json::array::write (std::ostream &os) const {
// String
std::ostream&
json::string::write (std::ostream &os) const {
json::tree::string::write (std::ostream &os) const {
os << '"' << m_value << '"';
return os;
}
bool
json::string::operator ==(const json::string &rhs) const
json::tree::string::operator ==(const json::tree::string &rhs) const
{ return rhs.m_value == m_value; }
bool
json::string::operator ==(const char *rhs) const
json::tree::string::operator ==(const char *rhs) const
{ return rhs == m_value; }
@ -522,14 +526,14 @@ json::string::operator ==(const char *rhs) const
// Number
std::ostream&
json::number::write (std::ostream &os) const {
json::tree::number::write (std::ostream &os) const {
os << setprecision (numeric_limits<double>::digits10) << m_value;
return os;
}
bool
json::number::operator ==(const json::number &rhs) const
json::tree::number::operator ==(const json::tree::number &rhs) const
{ return almost_equal (rhs.m_value, m_value); }
@ -537,13 +541,13 @@ json::number::operator ==(const json::number &rhs) const
// Boolean
std::ostream&
json::boolean::write (std::ostream &os) const {
json::tree::boolean::write (std::ostream &os) const {
os << (m_value ? "true" : "false");
return os;
}
bool
json::boolean::operator ==(const json::boolean &rhs) const
json::tree::boolean::operator ==(const json::tree::boolean &rhs) const
{ return rhs.m_value == m_value; }
@ -551,20 +555,20 @@ json::boolean::operator ==(const json::boolean &rhs) const
// Null
std::ostream&
json::null::write (std::ostream &os) const {
json::tree::null::write (std::ostream &os) const {
os << "null";
return os;
}
ostream&
json::operator <<(ostream &os, const json::node &n)
json::tree::operator <<(ostream &os, const json::tree::node &n)
{ return n.write (os); }
//-----------------------------------------------------------------------------
// to_json
namespace json {
namespace json { namespace tree {
template <>
std::unique_ptr<node>
io<bool>::serialise (const bool &b) {
@ -600,4 +604,4 @@ namespace json {
io<float>::serialise (const float &f) {
return std::unique_ptr<node> (new number (f));
}
}
} }

406
json.hpp
View File

@ -31,270 +31,272 @@
#include "iterator.hpp"
namespace json {
class node;
class object;
class array;
class string;
class number;
class boolean;
class null;
namespace tree {
class node;
class object;
class array;
class string;
class number;
class boolean;
class null;
/// Parse an encoded form of JSON into a tree structure
extern std::unique_ptr<node> parse (const boost::filesystem::path &path);
extern std::unique_ptr<node> parse (const char *start, const char *stop);
extern std::unique_ptr<node> parse (const char *start);
extern std::unique_ptr<node> parse (const std::string&);
/// Parse an encoded form of JSON into a tree structure
extern std::unique_ptr<node> parse (const boost::filesystem::path &path);
extern std::unique_ptr<node> parse (const char *start, const char *stop);
extern std::unique_ptr<node> parse (const char *start);
extern std::unique_ptr<node> parse (const std::string&);
extern void write (const json::node&, std::ostream&);
extern void write (const json::tree::node&, std::ostream&);
/// Abstract base for all JSON values
class node {
public:
virtual ~node () { ; }
/// Abstract base for all JSON values
class node {
public:
virtual ~node () { ; }
virtual const object& as_object (void) const;
virtual const array& as_array (void) const;
virtual const string& as_string (void) const;
virtual const number& as_number (void) const;
virtual const boolean& as_boolean (void) const;
virtual const null& as_null (void) const;
virtual const object& as_object (void) const;
virtual const array& as_array (void) const;
virtual const string& as_string (void) const;
virtual const number& as_number (void) const;
virtual const boolean& as_boolean (void) const;
virtual const null& as_null (void) const;
virtual bool is_object (void) const { return false; }
virtual bool is_array (void) const { return false; }
virtual bool is_string (void) const { return false; }
virtual bool is_number (void) const { return false; }
virtual bool is_boolean (void) const { return false; }
virtual bool is_null (void) const { return false; }
virtual bool is_object (void) const { return false; }
virtual bool is_array (void) const { return false; }
virtual bool is_string (void) const { return false; }
virtual bool is_number (void) const { return false; }
virtual bool is_boolean (void) const { return false; }
virtual bool is_null (void) const { return false; }
virtual bool operator==(const node &rhs) const = 0;
virtual bool operator!=(const node &rhs) const;
virtual bool operator==(const object &) const { return false; }
virtual bool operator==(const array &) const { return false; }
virtual bool operator==(const string &) const { return false; }
virtual bool operator==(const number &) const { return false; }
virtual bool operator==(const boolean &) const { return false; }
virtual bool operator==(const null &) const { return false; }
virtual bool operator==(const node &rhs) const = 0;
virtual bool operator!=(const node &rhs) const;
virtual bool operator==(const object &) const { return false; }
virtual bool operator==(const array &) const { return false; }
virtual bool operator==(const string &) const { return false; }
virtual bool operator==(const number &) const { return false; }
virtual bool operator==(const boolean &) const { return false; }
virtual bool operator==(const null &) const { return false; }
virtual bool operator==(const char *rhs) const;
virtual bool operator!=(const char *rhs) const { return !(*this == rhs); }
virtual bool operator==(const char *rhs) const;
virtual bool operator!=(const char *rhs) const { return !(*this == rhs); }
virtual const node& operator[] (const std::string&) const;
virtual const node& operator[] (unsigned int) const;
virtual const node& operator[] (const std::string&) const;
virtual const node& operator[] (unsigned int) const;
virtual std::ostream& write (std::ostream &os) const = 0;
};
virtual std::ostream& write (std::ostream &os) const = 0;
};
/// Represents a JSON object, and contains its children.
class object : public node {
protected:
typedef std::map<std::string, std::unique_ptr<node>> value_store;
public:
typedef value_store::iterator iterator;
typedef value_store::const_iterator const_iterator;
/// Represents a JSON object, and contains its children.
class object : public node {
protected:
typedef std::map<std::string, std::unique_ptr<node>> value_store;
public:
typedef value_store::iterator iterator;
typedef value_store::const_iterator const_iterator;
protected:
value_store m_values;
protected:
value_store m_values;
public:
virtual ~object ();
public:
virtual ~object ();
virtual const object& as_object (void) const { return *this; }
virtual bool is_object (void) const { return true; }
virtual bool operator==(const object &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual const object& as_object (void) const { return *this; }
virtual bool is_object (void) const { return true; }
virtual bool operator==(const object &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual void insert (const std::string &key, std::unique_ptr<node>&& value);
virtual const node& operator[](const std::string &key) const;
virtual bool has (const std::string&) const;
virtual void insert (const std::string &key, std::unique_ptr<node>&& value);
virtual const node& operator[](const std::string &key) const;
virtual bool has (const std::string&) const;
virtual void clear (void);
virtual void erase (const std::string &key);
virtual void clear (void);
virtual void erase (const std::string &key);
virtual const_iterator begin (void) const;
virtual const_iterator end (void) const;
virtual const_iterator begin (void) const;
virtual const_iterator end (void) const;
virtual std::ostream& write (std::ostream &os) const;
};
virtual std::ostream& write (std::ostream &os) const;
};
/// Represents a JSON array, and contains its children.
class array : public node {
protected:
typedef std::vector<std::unique_ptr<node>>::iterator pointer_array_iterator;
typedef std::vector<std::unique_ptr<node>>::const_iterator const_pointer_array_iterator;
/// Represents a JSON array, and contains its children.
class array : public node {
protected:
typedef std::vector<std::unique_ptr<node>>::iterator pointer_array_iterator;
typedef std::vector<std::unique_ptr<node>>::const_iterator const_pointer_array_iterator;
public:
typedef referencing_iterator<pointer_array_iterator> iterator;
typedef referencing_iterator<const_pointer_array_iterator> const_iterator;
public:
typedef referencing_iterator<pointer_array_iterator> iterator;
typedef referencing_iterator<const_pointer_array_iterator> const_iterator;
protected:
std::vector<std::unique_ptr<node>> m_values;
protected:
std::vector<std::unique_ptr<node>> m_values;
public:
virtual ~array();
public:
virtual ~array();
virtual const array& as_array (void) const { return *this; }
virtual bool is_array (void) const { return true; }
virtual bool operator==(const array &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual const array& as_array (void) const { return *this; }
virtual bool is_array (void) const { return true; }
virtual bool operator==(const array &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual size_t size (void) const
{ return m_values.size (); }
virtual node& operator [](unsigned int idx)
{ return *m_values[idx]; }
virtual const node& operator [](unsigned int idx) const
{ return *m_values[idx]; }
virtual size_t size (void) const
{ return m_values.size (); }
virtual node& operator [](unsigned int idx)
{ return *m_values[idx]; }
virtual const node& operator [](unsigned int idx) const
{ return *m_values[idx]; }
virtual const_iterator begin (void) const { return const_iterator (m_values.begin ()); }
virtual const_iterator end (void) const { return const_iterator (m_values.end ()); }
virtual const_iterator begin (void) const { return const_iterator (m_values.begin ()); }
virtual const_iterator end (void) const { return const_iterator (m_values.end ()); }
virtual void insert (std::unique_ptr<json::node> &&_value);
virtual void insert (std::unique_ptr<json::tree::node> &&_value);
virtual std::ostream& write (std::ostream &os) const;
};
virtual std::ostream& write (std::ostream &os) const;
};
/// Represents a JSON string literal.
class string : public node {
protected:
std::string m_value;
/// Represents a JSON string literal.
class string : public node {
protected:
std::string m_value;
public:
explicit string (const std::string &_value): m_value (_value) { ; }
explicit string (const char *_value): m_value (_value) { ; }
public:
explicit string (const std::string &_value): m_value (_value) { ; }
explicit string (const char *_value): m_value (_value) { ; }
string (const char *_first, const char *_last): m_value (_first, _last) { ; }
virtual const string& as_string (void) const { return *this; }
virtual bool is_string (void) const { return true; }
virtual bool operator==(const char *rhs) const;
virtual bool operator==(const string &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual const string& as_string (void) const { return *this; }
virtual bool is_string (void) const { return true; }
virtual bool operator==(const char *rhs) const;
virtual bool operator==(const string &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual size_t size (void) const { return m_value.size (); }
virtual size_t size (void) const { return m_value.size (); }
operator const std::string&(void) const { return m_value; }
const std::string& native (void) const { return m_value; }
operator const std::string&(void) const { return m_value; }
const std::string& native (void) const { return m_value; }
virtual std::ostream& write (std::ostream &os) const;
};
virtual std::ostream& write (std::ostream &os) const;
};
/// Represents a JSON integer/float literal.
class number : public node {
protected:
double m_value;
/// Represents a JSON integer/float literal.
class number : public node {
protected:
double m_value;
public:
explicit number (double _value): m_value (_value) { ; }
explicit number (int _value): m_value (_value) { ; }
explicit number (size_t _value): m_value (_value) { ; }
public:
explicit number (double _value): m_value (_value) { ; }
explicit number (int _value): m_value (_value) { ; }
explicit number (size_t _value): m_value (_value) { ; }
virtual const number& as_number (void) const { return *this; }
virtual bool is_number (void) const { return true; }
virtual bool operator==(const number &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual const number& as_number (void) const { return *this; }
virtual bool is_number (void) const { return true; }
virtual bool operator==(const number &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
operator double(void) const { return m_value; }
double native (void) const { return m_value; }
operator double(void) const { return m_value; }
double native (void) const { return m_value; }
virtual std::ostream& write (std::ostream &os) const;
};
virtual std::ostream& write (std::ostream &os) const;
};
/// Represents a JSON boolean literal.
class boolean : public node {
protected:
bool m_value;
/// Represents a JSON boolean literal.
class boolean : public node {
protected:
bool m_value;
public:
explicit boolean (bool _value): m_value (_value) { ; }
public:
explicit boolean (bool _value): m_value (_value) { ; }
virtual const boolean& as_boolean (void) const { return *this; }
virtual bool is_boolean (void) const { return true; }
virtual bool operator==(const boolean &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual const boolean& as_boolean (void) const { return *this; }
virtual bool is_boolean (void) const { return true; }
virtual bool operator==(const boolean &rhs) const;
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
operator bool (void) const { return m_value; }
bool native (void) const { return m_value; }
operator bool (void) const { return m_value; }
bool native (void) const { return m_value; }
virtual std::ostream& write (std::ostream &os) const;
};
virtual std::ostream& write (std::ostream &os) const;
};
/// Represents a JSON null value.
class null : public node {
public:
virtual bool operator==(const null&) const { return true; }
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
/// Represents a JSON null value.
class null : public node {
public:
virtual bool operator==(const null&) const { return true; }
virtual bool operator==(const node &rhs) const
{ return rhs == *this; }
virtual bool is_null (void) const { return true; }
virtual const null& as_null (void) const { return *this; }
virtual bool is_null (void) const { return true; }
virtual const null& as_null (void) const { return *this; }
virtual std::ostream& write (std::ostream &os) const;
};
virtual std::ostream& write (std::ostream &os) const;
};
/// The base class for all exceptions throw directly by the json namespace.
class error : public std::runtime_error {
public:
error (const std::string &_what):
std::runtime_error (_what)
{ ; }
};
/// The base class for all exceptions throw directly by the json namespace.
class error : public std::runtime_error {
public:
error (const std::string &_what):
std::runtime_error (_what)
{ ; }
};
/// Base class for all type conversion errors
class type_error : public error {
public:
type_error (const std::string &_what):
error (_what)
{ ; }
};
/// Base class for all type conversion errors
class type_error : public error {
public:
type_error (const std::string &_what):
error (_what)
{ ; }
};
/// Base class for errors thrown during parsing
class parse_error : public error {
public:
parse_error (const std::string &_what):
error (_what)
{ ; }
};
/// Base class for errors thrown during parsing
class parse_error : public error {
public:
parse_error (const std::string &_what):
error (_what)
{ ; }
};
/// Base class for errors thrown during schema validation
class schema_error : public error {
public:
schema_error (const std::string &_what):
error (_what)
{ ; }
};
/// Base class for errors thrown during schema validation
class schema_error : public error {
public:
schema_error (const std::string &_what):
error (_what)
{ ; }
};
std::ostream&
operator <<(std::ostream &os, const json::node &n);
std::ostream&
operator <<(std::ostream &os, const json::tree::node &n);
// Instantiate this template for the type you wish to output. We use a
// helper class here to avoid partial template specialisation of a
// function (eg, for templated types).
template <typename T>
struct io {
static std::unique_ptr<json::node> serialise (const T&);
static T deserialise (const json::node&);
};
}
template <typename T, class ...Args>
std::unique_ptr<json::node> to_json (const T &t, Args&&... args) {
return json::io<T>::serialise (t, std::forward<Args>(args)...);
// Instantiate this template for the type you wish to output. We use a
// helper class here to avoid partial template specialisation of a
// function (eg, for templated types).
template <typename T>
struct io {
static std::unique_ptr<json::tree::node> serialise (const T&);
static T deserialise (const json::tree::node&);
};
}
}
template <typename T, class ...Args>
T from_json (const json::node &n, Args&&... args) {
return json::io<T>::deserialise (n, std::forward<Args>(args)...);
std::unique_ptr<json::tree::node> to_json (const T &t, Args&&... args) {
return json::tree::io<T>::serialise (t, std::forward<Args>(args)...);
}
template <typename T, class ...Args>
T from_json (const json::tree::node &n, Args&&... args) {
return json::tree::io<T>::deserialise (n, std::forward<Args>(args)...);
}
#endif

View File

@ -186,10 +186,10 @@ namespace util {
//-----------------------------------------------------------------------------
namespace json {
namespace json { namespace tree {
template <>
util::range<double>
io<util::range<double>>::deserialise (const json::node &node) {
io<util::range<double>>::deserialise (const json::tree::node &node) {
if (node.is_string () && (node == "UNIT" ||
node == "unit")) {
return util::range<double>::UNIT;
@ -203,4 +203,4 @@ namespace json {
};
}
}
}
} }

View File

@ -24,10 +24,10 @@ main (int, char**) {
" ]"
"}";
std::unique_ptr<json::node> ptr = json::parse (TEST_STRING);
std::unique_ptr<json::tree::node> ptr = json::tree::parse (TEST_STRING);
CHECK (ptr->is_object ());
const json::node &ref = *ptr;
const json::tree::node &ref = *ptr;
CHECK ( ref["string"].is_string ());
CHECK (!ref["string"].is_array ());

View File

@ -48,8 +48,8 @@ main (int argc, char **argv) {
try {
boost::filesystem::path input (argv[ARG_INPUT]);
std::cout << *json::parse (input) << "\n";
} catch (const json::error& err) {
std::cout << *json::tree::parse (input) << "\n";
} catch (const json::tree::error& err) {
std::cerr << err.what () << "\n";
return EXIT_FAILURE;
}

View File

@ -55,7 +55,7 @@ print_usage (int argc, char **argv) {
const char*
type_to_string (const json::node &node) {
type_to_string (const json::tree::node &node) {
if (node.is_array ()) return "array";
if (node.is_boolean ()) return "boolean";
if (node.is_null ()) return "null";
@ -68,13 +68,13 @@ type_to_string (const json::node &node) {
bool
is_node_valid (const json::node &node,
const json::object &schema);
is_node_valid (const json::tree::node &node,
const json::tree::object &schema);
bool
is_type_valid (const json::node &node,
const json::node &type) {
is_type_valid (const json::tree::node &node,
const json::tree::node &type) {
if (type.is_array ()) {
return any_of (type.as_array ().begin (),
type.as_array ().end (),
@ -82,20 +82,20 @@ is_type_valid (const json::node &node,
}
if (!type.is_string ())
throw json::schema_error ("schema type requires array, string, or object");
throw json::tree::schema_error ("schema type requires array, string, or object");
static const auto ANY_VALIDATOR = [] (const json::node &) { return true; };
static const auto INT_VALIDATOR = [] (const json::node &n) {
static const auto ANY_VALIDATOR = [] (const json::tree::node &) { return true; };
static const auto INT_VALIDATOR = [] (const json::tree::node &n) {
return n.is_number () && is_integer (n.as_number ());
};
static const map<string, function<bool(const json::node&)>> TYPE_VALIDATORS ({
{ "array", bind (&json::node::is_array, _1) },
{ "boolean", bind (&json::node::is_boolean, _1) },
{ "null", bind (&json::node::is_null, _1) },
{ "number", bind (&json::node::is_number, _1) },
{ "object", bind (&json::node::is_object, _1) },
{ "string", bind (&json::node::is_string, _1) },
static const map<string, function<bool(const json::tree::node&)>> TYPE_VALIDATORS ({
{ "array", bind (&json::tree::node::is_array, _1) },
{ "boolean", bind (&json::tree::node::is_boolean, _1) },
{ "null", bind (&json::tree::node::is_null, _1) },
{ "number", bind (&json::tree::node::is_number, _1) },
{ "object", bind (&json::tree::node::is_object, _1) },
{ "string", bind (&json::tree::node::is_string, _1) },
{ "any", ANY_VALIDATOR },
{ "integer", INT_VALIDATOR },
});
@ -111,18 +111,18 @@ is_type_valid (const json::node &node,
bool
is_disallow_valid (const json::node &node,
const json::node &constraint)
is_disallow_valid (const json::tree::node &node,
const json::tree::node &constraint)
{ return !is_type_valid (node, constraint); }
bool
is_enum_valid (const json::node &node,
const json::node &constraint) {
is_enum_valid (const json::tree::node &node,
const json::tree::node &constraint) {
if (!constraint.is_array ())
throw json::schema_error ("enum validation requires an array");
throw json::tree::schema_error ("enum validation requires an array");
const json::array &valids = constraint.as_array ();
const json::tree::array &valids = constraint.as_array ();
return valids.end () != std::find (valids.begin (),
valids.end (),
node);
@ -130,15 +130,15 @@ is_enum_valid (const json::node &node,
bool
is_enum_valid (const json::string &node,
const json::node &constraint) {
return is_enum_valid (static_cast<const json::node&> (node), constraint);
is_enum_valid (const json::tree::string &node,
const json::tree::node &constraint) {
return is_enum_valid (static_cast<const json::tree::node&> (node), constraint);
}
bool
is_always_valid (const json::node &,
const json::node &)
is_always_valid (const json::tree::node &,
const json::tree::node &)
{ return true; }
@ -153,14 +153,14 @@ is_always_valid (const json::node &,
bool
is_boolean_valid (const json::node &node,
const json::object &)
is_boolean_valid (const json::tree::node &node,
const json::tree::object &)
{ return node.is_boolean (); }
bool
is_null_valid (const json::node &node,
const json::object &)
is_null_valid (const json::tree::node &node,
const json::tree::object &)
{ return node.is_null (); }
@ -169,36 +169,36 @@ is_null_valid (const json::node &node,
//
bool
is_minimum_valid (const json::number &node,
const json::node &constraint) {
is_minimum_valid (const json::tree::number &node,
const json::tree::node &constraint) {
return constraint["minimum"].as_number () <= node;
}
bool
is_maximum_valid (const json::number &node,
const json::node &constraint) {
is_maximum_valid (const json::tree::number &node,
const json::tree::node &constraint) {
return constraint["maximum"].as_number () >= node;
}
bool
is_exclusive_minimum_valid (const json::number &node,
const json::node &constraint) {
is_exclusive_minimum_valid (const json::tree::number &node,
const json::tree::node &constraint) {
return constraint["exclusiveMinimum"].as_number () < node;
}
bool
is_exclusive_maximum_valid (const json::number &node,
const json::node &constraint) {
is_exclusive_maximum_valid (const json::tree::number &node,
const json::tree::node &constraint) {
return constraint["exclusiveMaximum"].as_number () > node;
}
bool
is_divisible_by_valid (const json::number &node,
const json::node &constraint) {
is_divisible_by_valid (const json::tree::number &node,
const json::tree::node &constraint) {
return exactly_equal (fmod (node.native (),
constraint["divisibleBy"].as_number ()),
0.0);
@ -206,9 +206,9 @@ is_divisible_by_valid (const json::number &node,
bool
is_number_valid (const json::number &node,
const json::object &schema) {
typedef bool (*number_validator_t)(const json::number&, const json::node&);
is_number_valid (const json::tree::number &node,
const json::tree::object &schema) {
typedef bool (*number_validator_t)(const json::tree::number&, const json::tree::node&);
static const map<string, number_validator_t> VALIDATORS = {
{ "minimum", &is_minimum_valid },
{ "maximum", &is_maximum_valid },
@ -239,8 +239,8 @@ is_number_valid (const json::number &node,
bool
is_min_length_valid (const json::string &node,
const json::node &constraint) {
is_min_length_valid (const json::tree::string &node,
const json::tree::node &constraint) {
if (!is_integer (constraint))
return false;
@ -249,8 +249,8 @@ is_min_length_valid (const json::string &node,
bool
is_max_length_valid (const json::string &node,
const json::node &constraint) {
is_max_length_valid (const json::tree::string &node,
const json::tree::node &constraint) {
if (!is_integer (constraint))
return false;
@ -259,8 +259,8 @@ is_max_length_valid (const json::string &node,
bool
is_pattern_valid (const json::string &node,
const json::node &constraint) {
is_pattern_valid (const json::tree::string &node,
const json::tree::node &constraint) {
if (!constraint.is_string ())
return false;
@ -271,9 +271,9 @@ is_pattern_valid (const json::string &node,
bool
is_string_valid (const json::string &node,
const json::object &schema) {
typedef bool (*string_validator_t)(const json::string&, const json::node&);
is_string_valid (const json::tree::string &node,
const json::tree::object &schema) {
typedef bool (*string_validator_t)(const json::tree::string&, const json::tree::node&);
static const map<std::string, string_validator_t> VALIDATORS = {
{ "minLength", &is_min_length_valid },
{ "maxLength", &is_max_length_valid },
@ -281,9 +281,9 @@ is_string_valid (const json::string &node,
{ "enum", &is_enum_valid },
};
for (const json::object::const_iterator::value_type &i: schema) {
for (const json::tree::object::const_iterator::value_type &i: schema) {
const std::string &key = i.first;
const json::node &constraint = *i.second;
const json::tree::node &constraint = *i.second;
auto validator = VALIDATORS.find (key);
if (validator == VALIDATORS.end ()) {
@ -302,8 +302,8 @@ is_string_valid (const json::string &node,
bool
is_string_valid (const json::node &node,
const json::object &schema) {
is_string_valid (const json::tree::node &node,
const json::tree::object &schema) {
if (!node.is_string ())
return false;
return is_string_valid (node.as_string (), schema);
@ -315,36 +315,36 @@ is_string_valid (const json::node &node,
bool
is_max_items_valid (const json::array &node,
const json::node &constraint) {
is_max_items_valid (const json::tree::array &node,
const json::tree::node &constraint) {
if (!constraint.is_number () && is_integer (constraint.as_number ()))
throw json::schema_error ("max_items should be an integer");
throw json::tree::schema_error ("max_items should be an integer");
return node.size () <= constraint.as_number ();
}
bool
is_min_items_valid (const json::array &node,
const json::node &constraint) {
is_min_items_valid (const json::tree::array &node,
const json::tree::node &constraint) {
if (!constraint.is_number () && is_integer (constraint.as_number ()))
throw json::schema_error ("min_items should be an integer");
throw json::tree::schema_error ("min_items should be an integer");
return node.size () >= constraint.as_number ();
}
bool
is_unique_items_valid (const json::array &node,
const json::node &constraint) {
is_unique_items_valid (const json::tree::array &node,
const json::tree::node &constraint) {
if (!constraint.is_boolean ())
throw json::schema_error ("uniqueItems must be a boolean");
throw json::tree::schema_error ("uniqueItems must be a boolean");
if (node.size () < 2)
return true;
for (json::array::const_iterator i = node.begin (); i != node.end () - 1; ++i) {
for (json::tree::array::const_iterator i = node.begin (); i != node.end () - 1; ++i) {
if (find (i + 1, node.end (), *i) != node.end ())
return false;
}
@ -354,13 +354,13 @@ is_unique_items_valid (const json::array &node,
bool
is_items_valid (const json::array &node,
const json::node &_schema) {
is_items_valid (const json::tree::array &node,
const json::tree::node &_schema) {
if (!_schema.is_object ())
throw json::schema_error ("array_items constraint must be an object");
const json::object &schema = _schema.as_object ();
throw json::tree::schema_error ("array_items constraint must be an object");
const json::tree::object &schema = _schema.as_object ();
for (const json::node &i: node)
for (const json::tree::node &i: node)
if (!is_node_valid (i, schema))
return false;
@ -372,19 +372,19 @@ is_items_valid (const json::array &node,
bool
is_additional_items_valid (const json::array &,
const json::node &) {
is_additional_items_valid (const json::tree::array &,
const json::tree::node &) {
not_implemented ();
return false;
}
bool
is_array_valid (const json::array &node,
const json::object &schema) {
is_array_valid (const json::tree::array &node,
const json::tree::object &schema) {
CHECK (node.is_array ());
typedef bool (*array_validator_t)(const json::array&, const json::node&);
typedef bool (*array_validator_t)(const json::tree::array&, const json::tree::node&);
static const map<string, array_validator_t> VALIDATORS ({
{ "items", &is_items_valid },
{ "minItems", &is_min_items_valid },
@ -393,9 +393,9 @@ is_array_valid (const json::array &node,
{ "additionalItems", &is_additional_items_valid },
});
for (const json::object::const_iterator::value_type &i: schema) {
for (const json::tree::object::const_iterator::value_type &i: schema) {
const std::string &key = i.first;
const json::node &constraint = *i.second;
const json::tree::node &constraint = *i.second;
auto validator = VALIDATORS.find (key);
if (validator == VALIDATORS.end ()) {
@ -418,11 +418,11 @@ is_array_valid (const json::array &node,
//
bool
is_properties_valid (const json::object &node,
const json::object &schema) {
for (const json::object::const_iterator::value_type &element: node) {
is_properties_valid (const json::tree::object &node,
const json::tree::object &schema) {
for (const json::tree::object::const_iterator::value_type &element: node) {
const std::string &key = element.first;
const json::node &val = *element.second;
const json::tree::node &val = *element.second;
if (!schema.has (key)) {
std::cerr << "[warning] no constraint found for key: " << key << "\n";
@ -440,30 +440,30 @@ is_properties_valid (const json::object &node,
bool
is_properties_valid (const json::object &node,
const json::node &constraint) {
is_properties_valid (const json::tree::object &node,
const json::tree::node &constraint) {
CHECK (node.is_object ());
if (!constraint.is_object ())
throw json::schema_error ("properties needs an object");
throw json::tree::schema_error ("properties needs an object");
return is_properties_valid (node, constraint.as_object ());
}
bool
is_object_valid (const json::object &node,
const json::object &schema) {
typedef bool (*object_validator_t)(const json::object&, const json::node&);
is_object_valid (const json::tree::object &node,
const json::tree::object &schema) {
typedef bool (*object_validator_t)(const json::tree::object&, const json::tree::node&);
static const map<string, object_validator_t> VALIDATORS = {
{ "properties", &is_properties_valid },
//{ "patternProperties", &is_pattern_properties_valid },
//{ "additionalProperties", &is_additionaL_properties_valid },
};
for (const json::object::const_iterator::value_type &i: schema) {
for (const json::tree::object::const_iterator::value_type &i: schema) {
const std::string &name = i.first;
const json::node &constraint = *i.second;
const json::tree::node &constraint = *i.second;
auto validator = VALIDATORS.find (name);
if (validator == VALIDATORS.end ()) {
@ -482,8 +482,8 @@ is_object_valid (const json::object &node,
bool
is_object_valid (const json::node &node,
const json::object &schema) {
is_object_valid (const json::tree::node &node,
const json::tree::object &schema) {
if (!node.is_object ())
return false;
@ -496,8 +496,8 @@ is_object_valid (const json::node &node,
//
bool
is_node_valid (const json::node &node,
const json::object &schema) {
is_node_valid (const json::tree::node &node,
const json::tree::object &schema) {
if (schema.has ("$ref")) {
const std::string &uri = schema["$ref"].as_string ();
std::cerr << "loading referenced schema: " << uri << "\n";
@ -507,7 +507,7 @@ is_node_valid (const json::node &node,
return false;
}
auto referenced = json::parse (boost::filesystem::path (uri));
auto referenced = json::tree::parse (boost::filesystem::path (uri));
return is_node_valid (node, referenced->as_object ());
}
@ -558,8 +558,8 @@ is_node_valid (const json::node &node,
bool
is_root_valid (const json::node &node,
const json::object &schema) {
is_root_valid (const json::tree::node &node,
const json::tree::object &schema) {
if (!node.is_array () && !node.is_object ())
return false;
return is_node_valid (node, schema);
@ -579,11 +579,11 @@ main (int argc, char **argv) {
}
// Load the schema and input
unique_ptr<json::node> schema, input;
unique_ptr<json::tree::node> schema, input;
try {
schema = json::parse (boost::filesystem::path (argv[ARG_SCHEMA]));
input = json::parse (boost::filesystem::path (argv[ARG_INPUT]));
} catch (const json::parse_error &err) {
schema = json::tree::parse (boost::filesystem::path (argv[ARG_SCHEMA]));
input = json::tree::parse (boost::filesystem::path (argv[ARG_INPUT]));
} catch (const json::tree::parse_error &err) {
std::cerr << "malformed json for schema or input. " << err.what () << "\n";
return EXIT_FAILURE;
}
@ -594,7 +594,7 @@ main (int argc, char **argv) {
return EXIT_FAILURE;
}
const json::object &schema_object = schema->as_object ();
const json::tree::object &schema_object = schema->as_object ();
// Check input is valid
if (!is_node_valid (*input, schema_object)) {

View File

@ -23,8 +23,8 @@ main (int argc, char ** argv) {
}
try {
json::parse (boost::filesystem::path (argv[ARG_PATH]));
} catch (json::error &x) {
json::tree::parse (boost::filesystem::path (argv[ARG_PATH]));
} catch (json::tree::error &x) {
std::cerr << "Error: " << x.what () << std::endl;
return EXIT_FAILURE;
}

View File

@ -414,9 +414,9 @@ util::operator<< (std::ostream &os, const util::vector<S,T> &v) {
//-----------------------------------------------------------------------------
template <size_t S, typename T>
const json::node&
util::operator>> (const json::node &node, util::vector<S,T> &v) {
const json::array &array = node.as_array ();
const json::tree::node&
util::operator>> (const json::tree::node &node, util::vector<S,T> &v) {
const json::tree::array &array = node.as_array ();
if (array.size () != S)
throw std::runtime_error ("Invalid dimensionality for json-to-vector");
@ -440,7 +440,7 @@ template util::vector<S,T> util::operator* (float, const util::vector<S,T>&);
template util::vector<S,T> util::operator+ (T, const util::vector<S,T>&); \
template util::vector<S,T> util::operator- (T, const util::vector<S,T>&); \
template std::ostream& util::operator<< (std::ostream&, const util::vector<S,T> &v);\
template const json::node& util::operator>> (const json::node&, util::vector<S,T>&);
template const json::tree::node& util::operator>> (const json::tree::node&, util::vector<S,T>&);
#define INSTANTIATE(T) \

View File

@ -100,7 +100,7 @@ namespace util {
template <size_t S, typename T> std::ostream& operator<< (std::ostream&, const vector<S,T>&);
template <size_t S, typename T>
const json::node& operator>> (const json::node&, vector<S,T>&);
const json::tree::node& operator>> (const json::tree::node&, vector<S,T>&);
// convenience typedefs
typedef vector<2,size_t> vector2u;