json: move tree parsing code to json::tree
This commit is contained in:
parent
ebd1087087
commit
cfc0f8ecd0
@ -52,9 +52,9 @@ util::colour<T>::BLUE (0.f, 0.f, 1.f, 1.f);
|
|||||||
//! Extract a colour object from a JSON node.
|
//! Extract a colour object from a JSON node.
|
||||||
//!
|
//!
|
||||||
//! Data must be an array or 3 or 4 numbers. Guarantees success, or throws a
|
//! Data must be an array or 3 or 4 numbers. Guarantees success, or throws a
|
||||||
//! json::type_error.
|
//! json::tree::type_error.
|
||||||
const json::node&
|
const json::tree::node&
|
||||||
operator>> (const json::node &node, colour4f &c) {
|
operator>> (const json::tree::node &node, colour4f &c) {
|
||||||
c.r = static_cast<float> (node[0].as_number ());
|
c.r = static_cast<float> (node[0].as_number ());
|
||||||
c.g = static_cast<float> (node[1].as_number ());
|
c.g = static_cast<float> (node[1].as_number ());
|
||||||
c.b = static_cast<float> (node[2].as_number ());
|
c.b = static_cast<float> (node[2].as_number ());
|
||||||
|
@ -41,7 +41,7 @@ namespace util {
|
|||||||
|
|
||||||
typedef colour<float> colour4f;
|
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&);
|
std::ostream& operator<< (std::ostream&, const util::colour4f&);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
158
json.cpp.rl
158
json.cpp.rl
@ -44,7 +44,7 @@ using namespace util;
|
|||||||
// Parsing
|
// Parsing
|
||||||
|
|
||||||
struct parse_context {
|
struct parse_context {
|
||||||
parse_context(json::node *_root):
|
parse_context(json::tree::node *_root):
|
||||||
root (_root),
|
root (_root),
|
||||||
value (NULL),
|
value (NULL),
|
||||||
key (NULL),
|
key (NULL),
|
||||||
@ -52,7 +52,7 @@ struct parse_context {
|
|||||||
stop (NULL)
|
stop (NULL)
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
json::node *root,
|
json::tree::node *root,
|
||||||
*value,
|
*value,
|
||||||
*key;
|
*key;
|
||||||
const char *start,
|
const char *start,
|
||||||
@ -76,8 +76,8 @@ struct parse_context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
action new_object { nodestack.push_back (parse_context(new json::object)); }
|
action new_object { nodestack.push_back (parse_context(new json::tree::object)); }
|
||||||
action new_array { nodestack.push_back (parse_context(new json::array)); }
|
action new_array { nodestack.push_back (parse_context(new json::tree::array)); }
|
||||||
|
|
||||||
action new_object_value {
|
action new_object_value {
|
||||||
CHECK (nodestack.back ().root->is_object ());
|
CHECK (nodestack.back ().root->is_object ());
|
||||||
@ -87,9 +87,9 @@ struct parse_context {
|
|||||||
if (!nodestack.back ().key->is_string ())
|
if (!nodestack.back ().key->is_string ())
|
||||||
throw parse_error ("object keys must be strings");
|
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 (),
|
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 ().key = NULL;
|
||||||
nodestack.back ().value = NULL;
|
nodestack.back ().value = NULL;
|
||||||
}
|
}
|
||||||
@ -98,8 +98,8 @@ struct parse_context {
|
|||||||
CHECK (nodestack.back ().root->is_array ());
|
CHECK (nodestack.back ().root->is_array ());
|
||||||
CHECK (nodestack.back ().value);
|
CHECK (nodestack.back ().value);
|
||||||
|
|
||||||
json::array *array = (json::array *)nodestack.back ().root;
|
json::tree::array *array = (json::tree::array *)nodestack.back ().root;
|
||||||
array->insert (unique_ptr<json::node> (nodestack.back ().value));
|
array->insert (unique_ptr<json::tree::node> (nodestack.back ().value));
|
||||||
nodestack.back ().value = NULL;
|
nodestack.back ().value = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ struct parse_context {
|
|||||||
|
|
||||||
std::string value (std::string (nodestack.back ().start,
|
std::string value (std::string (nodestack.back ().start,
|
||||||
nodestack.back ().stop));
|
nodestack.back ().stop));
|
||||||
nodestack.back ().value = new json::string(value);
|
nodestack.back ().value = new json::tree::string(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
action new_boolean {
|
action new_boolean {
|
||||||
@ -133,14 +133,14 @@ struct parse_context {
|
|||||||
double value = strtod (back.start, &end);
|
double value = strtod (back.start, &end);
|
||||||
if (end == back.start || errno)
|
if (end == back.start || errno)
|
||||||
throw parse_error ("unable to parse number");
|
throw parse_error ("unable to parse number");
|
||||||
back.value = new json::number (value);
|
back.value = new json::tree::number (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
action new_null {
|
action new_null {
|
||||||
CHECK (!nodestack.empty ());
|
CHECK (!nodestack.empty ());
|
||||||
CHECK (!nodestack.back ().value);
|
CHECK (!nodestack.back ().value);
|
||||||
|
|
||||||
nodestack.back().value = new json::null ();
|
nodestack.back().value = new json::tree::null ();
|
||||||
}
|
}
|
||||||
|
|
||||||
action new_object_key {
|
action new_object_key {
|
||||||
@ -199,8 +199,8 @@ struct parse_context {
|
|||||||
|
|
||||||
## other
|
## other
|
||||||
boolean =
|
boolean =
|
||||||
'true' @{ nodestack.back ().value = new json::boolean ( true); }
|
'true' @{ nodestack.back ().value = new json::tree::boolean ( true); }
|
||||||
| 'false' @{ nodestack.back ().value = new json::boolean (false); };
|
| 'false' @{ nodestack.back ().value = new json::tree::boolean (false); };
|
||||||
|
|
||||||
## components
|
## components
|
||||||
object = '{' @{ fhold; fcall _object; } '}';
|
object = '{' @{ fhold; fcall _object; } '}';
|
||||||
@ -242,14 +242,14 @@ struct parse_context {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool
|
bool
|
||||||
is_integer (const json::number &node) {
|
is_integer (const json::tree::number &node) {
|
||||||
return is_integer (node.native ());
|
return is_integer (node.native ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool
|
bool
|
||||||
is_integer (const json::node &node) {
|
is_integer (const json::tree::node &node) {
|
||||||
return node.is_number () &&
|
return node.is_number () &&
|
||||||
is_integer (node.as_number ());
|
is_integer (node.as_number ());
|
||||||
}
|
}
|
||||||
@ -258,22 +258,22 @@ is_integer (const json::node &node) {
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Node
|
// Node
|
||||||
|
|
||||||
std::unique_ptr<json::node>
|
std::unique_ptr<json::tree::node>
|
||||||
json::parse (const boost::filesystem::path &path) {
|
json::tree::parse (const boost::filesystem::path &path) {
|
||||||
auto data = slurp (path);
|
auto data = slurp (path);
|
||||||
return parse (static_cast <const char *> (data.get ()));
|
return parse (static_cast <const char *> (data.get ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<json::node>
|
std::unique_ptr<json::tree::node>
|
||||||
json::parse (const std::string &path)
|
json::tree::parse (const std::string &path)
|
||||||
{ return parse (path.c_str (), path.c_str () + path.size ()); }
|
{ return parse (path.c_str (), path.c_str () + path.size ()); }
|
||||||
|
|
||||||
std::unique_ptr<json::node>
|
std::unique_ptr<json::tree::node>
|
||||||
json::parse (const char *start,
|
json::tree::parse (const char *start,
|
||||||
const char *stop) {
|
const char *stop) {
|
||||||
bool __success = true;
|
bool __success = true;
|
||||||
json::node *__root = nullptr;
|
json::tree::node *__root = nullptr;
|
||||||
size_t top = 0;
|
size_t top = 0;
|
||||||
int cs;
|
int cs;
|
||||||
deque <int> fsmstack;
|
deque <int> fsmstack;
|
||||||
@ -292,50 +292,50 @@ json::parse (const char *start,
|
|||||||
throw parse_error (os.str ());
|
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>
|
std::unique_ptr<json::tree::node>
|
||||||
json::parse (const char *start)
|
json::tree::parse (const char *start)
|
||||||
{ return parse (start, start + strlen (start)); }
|
{ return parse (start, start + strlen (start)); }
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
json::write (const json::node &node, std::ostream &os)
|
json::tree::write (const json::tree::node &node, std::ostream &os)
|
||||||
{ node.write (os); }
|
{ node.write (os); }
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Type conversion
|
// Type conversion
|
||||||
|
|
||||||
const json::object&
|
const json::tree::object&
|
||||||
json::node::as_object (void) const
|
json::tree::node::as_object (void) const
|
||||||
{ throw type_error ("node is not an object"); }
|
{ throw type_error ("node is not an object"); }
|
||||||
|
|
||||||
|
|
||||||
const json::array&
|
const json::tree::array&
|
||||||
json::node::as_array (void) const
|
json::tree::node::as_array (void) const
|
||||||
{ throw type_error ("node is not an array"); }
|
{ throw type_error ("node is not an array"); }
|
||||||
|
|
||||||
|
|
||||||
const json::string&
|
const json::tree::string&
|
||||||
json::node::as_string (void) const
|
json::tree::node::as_string (void) const
|
||||||
{ throw type_error ("node is not a string"); }
|
{ throw type_error ("node is not a string"); }
|
||||||
|
|
||||||
|
|
||||||
const json::number&
|
const json::tree::number&
|
||||||
json::node::as_number (void) const
|
json::tree::node::as_number (void) const
|
||||||
{ throw type_error ("node is not a number"); }
|
{ throw type_error ("node is not a number"); }
|
||||||
|
|
||||||
|
|
||||||
const json::boolean&
|
const json::tree::boolean&
|
||||||
json::node::as_boolean (void) const
|
json::tree::node::as_boolean (void) const
|
||||||
{ throw type_error ("node is not a boolean"); }
|
{ throw type_error ("node is not a boolean"); }
|
||||||
|
|
||||||
|
|
||||||
const json::null&
|
const json::tree::null&
|
||||||
json::node::as_null (void) const
|
json::tree::node::as_null (void) const
|
||||||
{ throw type_error ("node is not a null"); }
|
{ throw type_error ("node is not a null"); }
|
||||||
|
|
||||||
|
|
||||||
@ -343,38 +343,38 @@ json::node::as_null (void) const
|
|||||||
// Global operatoers
|
// Global operatoers
|
||||||
|
|
||||||
bool
|
bool
|
||||||
json::node::operator!= (const node &rhs) const
|
json::tree::node::operator!= (const node &rhs) const
|
||||||
{ return !(*this == rhs); }
|
{ return !(*this == rhs); }
|
||||||
|
|
||||||
|
|
||||||
bool json::node::operator==(const char *rhs) const {
|
bool json::tree::node::operator==(const char *rhs) const {
|
||||||
try {
|
try {
|
||||||
return as_string ().native () == rhs;
|
return as_string ().native () == rhs;
|
||||||
} catch (const json::type_error&) {
|
} catch (const json::tree::type_error&) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const json::node&
|
const json::tree::node&
|
||||||
json::node::operator[] (const std::string &key) const
|
json::tree::node::operator[] (const std::string &key) const
|
||||||
{ return as_object ()[key]; }
|
{ return as_object ()[key]; }
|
||||||
|
|
||||||
|
|
||||||
const json::node&
|
const json::tree::node&
|
||||||
json::node::operator[] (unsigned int idx) const
|
json::tree::node::operator[] (unsigned int idx) const
|
||||||
{ return as_array()[idx]; }
|
{ return as_array()[idx]; }
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Object
|
// Object
|
||||||
|
|
||||||
json::object::~object ()
|
json::tree::object::~object ()
|
||||||
{ ; }
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
bool
|
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 ();
|
for (auto i = rhs.m_values.begin (), j = m_values.begin ();
|
||||||
i != rhs.m_values.end () && j != m_values.end ();
|
i != rhs.m_values.end () && j != m_values.end ();
|
||||||
++i, ++j)
|
++i, ++j)
|
||||||
@ -390,17 +390,17 @@ json::object::operator ==(const json::object &rhs) const {
|
|||||||
|
|
||||||
|
|
||||||
void
|
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); }
|
{ m_values[_key] = move(value); }
|
||||||
|
|
||||||
|
|
||||||
const json::node&
|
const json::tree::node&
|
||||||
json::object::operator[](const std::string &key) const {
|
json::tree::object::operator[](const std::string &key) const {
|
||||||
auto value = m_values.find (key);
|
auto value = m_values.find (key);
|
||||||
if (value == m_values.end ()) {
|
if (value == m_values.end ()) {
|
||||||
ostringstream ss;
|
ostringstream ss;
|
||||||
ss << "no key: " << key;
|
ss << "no key: " << key;
|
||||||
throw json::error (ss.str());
|
throw json::tree::error (ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return *value->second;
|
return *value->second;
|
||||||
@ -408,38 +408,38 @@ json::object::operator[](const std::string &key) const {
|
|||||||
|
|
||||||
|
|
||||||
bool
|
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 ();
|
return m_values.find (key) != m_values.end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
json::object::clear (void)
|
json::tree::object::clear (void)
|
||||||
{ m_values.clear (); }
|
{ m_values.clear (); }
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
json::object::erase (const std::string &key) {
|
json::tree::object::erase (const std::string &key) {
|
||||||
auto pos = m_values.find (key);
|
auto pos = m_values.find (key);
|
||||||
if (pos == m_values.end ())
|
if (pos == m_values.end ())
|
||||||
throw json::error ("erasing invalid key");
|
throw json::tree::error ("erasing invalid key");
|
||||||
|
|
||||||
m_values.erase (key);
|
m_values.erase (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
json::object::const_iterator
|
json::tree::object::const_iterator
|
||||||
json::object::begin (void) const
|
json::tree::object::begin (void) const
|
||||||
{ return m_values.begin (); }
|
{ return m_values.begin (); }
|
||||||
|
|
||||||
|
|
||||||
json::object::const_iterator
|
json::tree::object::const_iterator
|
||||||
json::object::end (void) const
|
json::tree::object::end (void) const
|
||||||
{ return m_values.end (); }
|
{ return m_values.end (); }
|
||||||
|
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
json::object::write (std::ostream &os) const {
|
json::tree::object::write (std::ostream &os) const {
|
||||||
os << "{\n";
|
os << "{\n";
|
||||||
{
|
{
|
||||||
indenter raii(os);
|
indenter raii(os);
|
||||||
@ -460,17 +460,21 @@ json::object::write (std::ostream &os) const {
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Array
|
// Array
|
||||||
|
|
||||||
json::array::~array()
|
json::tree::array::~array()
|
||||||
{ ; }
|
{
|
||||||
|
m_values.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
json::array::insert (unique_ptr<json::node> &&_value)
|
json::tree::array::insert (unique_ptr<json::tree::node> &&_value)
|
||||||
{ m_values.push_back (move (_value)); }
|
{
|
||||||
|
m_values.push_back (move (_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
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 ();
|
for (auto i = rhs.m_values.begin (), j = m_values.begin ();
|
||||||
i != rhs.m_values.end () && j != m_values.end ();
|
i != rhs.m_values.end () && j != m_values.end ();
|
||||||
++i, ++j)
|
++i, ++j)
|
||||||
@ -481,7 +485,7 @@ json::array::operator ==(const json::array &rhs) const {
|
|||||||
|
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
json::array::write (std::ostream &os) const {
|
json::tree::array::write (std::ostream &os) const {
|
||||||
os << "[\n";
|
os << "[\n";
|
||||||
{
|
{
|
||||||
indenter raii(os);
|
indenter raii(os);
|
||||||
@ -502,19 +506,19 @@ json::array::write (std::ostream &os) const {
|
|||||||
// String
|
// String
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
json::string::write (std::ostream &os) const {
|
json::tree::string::write (std::ostream &os) const {
|
||||||
os << '"' << m_value << '"';
|
os << '"' << m_value << '"';
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
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; }
|
{ return rhs.m_value == m_value; }
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
json::string::operator ==(const char *rhs) const
|
json::tree::string::operator ==(const char *rhs) const
|
||||||
{ return rhs == m_value; }
|
{ return rhs == m_value; }
|
||||||
|
|
||||||
|
|
||||||
@ -522,14 +526,14 @@ json::string::operator ==(const char *rhs) const
|
|||||||
// Number
|
// Number
|
||||||
|
|
||||||
std::ostream&
|
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;
|
os << setprecision (numeric_limits<double>::digits10) << m_value;
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
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); }
|
{ return almost_equal (rhs.m_value, m_value); }
|
||||||
|
|
||||||
|
|
||||||
@ -537,13 +541,13 @@ json::number::operator ==(const json::number &rhs) const
|
|||||||
// Boolean
|
// Boolean
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
json::boolean::write (std::ostream &os) const {
|
json::tree::boolean::write (std::ostream &os) const {
|
||||||
os << (m_value ? "true" : "false");
|
os << (m_value ? "true" : "false");
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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; }
|
{ return rhs.m_value == m_value; }
|
||||||
|
|
||||||
|
|
||||||
@ -551,20 +555,20 @@ json::boolean::operator ==(const json::boolean &rhs) const
|
|||||||
// Null
|
// Null
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
json::null::write (std::ostream &os) const {
|
json::tree::null::write (std::ostream &os) const {
|
||||||
os << "null";
|
os << "null";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream&
|
ostream&
|
||||||
json::operator <<(ostream &os, const json::node &n)
|
json::tree::operator <<(ostream &os, const json::tree::node &n)
|
||||||
{ return n.write (os); }
|
{ return n.write (os); }
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// to_json
|
// to_json
|
||||||
|
|
||||||
namespace json {
|
namespace json { namespace tree {
|
||||||
template <>
|
template <>
|
||||||
std::unique_ptr<node>
|
std::unique_ptr<node>
|
||||||
io<bool>::serialise (const bool &b) {
|
io<bool>::serialise (const bool &b) {
|
||||||
@ -600,4 +604,4 @@ namespace json {
|
|||||||
io<float>::serialise (const float &f) {
|
io<float>::serialise (const float &f) {
|
||||||
return std::unique_ptr<node> (new number (f));
|
return std::unique_ptr<node> (new number (f));
|
||||||
}
|
}
|
||||||
}
|
} }
|
||||||
|
406
json.hpp
406
json.hpp
@ -31,270 +31,272 @@
|
|||||||
#include "iterator.hpp"
|
#include "iterator.hpp"
|
||||||
|
|
||||||
namespace json {
|
namespace json {
|
||||||
class node;
|
namespace tree {
|
||||||
class object;
|
class node;
|
||||||
class array;
|
class object;
|
||||||
class string;
|
class array;
|
||||||
class number;
|
class string;
|
||||||
class boolean;
|
class number;
|
||||||
class null;
|
class boolean;
|
||||||
|
class null;
|
||||||
|
|
||||||
/// Parse an encoded form of JSON into a tree structure
|
/// 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 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, const char *stop);
|
||||||
extern std::unique_ptr<node> parse (const char *start);
|
extern std::unique_ptr<node> parse (const char *start);
|
||||||
extern std::unique_ptr<node> parse (const std::string&);
|
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
|
/// Abstract base for all JSON values
|
||||||
class node {
|
class node {
|
||||||
public:
|
public:
|
||||||
virtual ~node () { ; }
|
virtual ~node () { ; }
|
||||||
|
|
||||||
virtual const object& as_object (void) const;
|
virtual const object& as_object (void) const;
|
||||||
virtual const array& as_array (void) const;
|
virtual const array& as_array (void) const;
|
||||||
virtual const string& as_string (void) const;
|
virtual const string& as_string (void) const;
|
||||||
virtual const number& as_number (void) const;
|
virtual const number& as_number (void) const;
|
||||||
virtual const boolean& as_boolean (void) const;
|
virtual const boolean& as_boolean (void) const;
|
||||||
virtual const null& as_null (void) const;
|
virtual const null& as_null (void) const;
|
||||||
|
|
||||||
virtual bool is_object (void) const { return false; }
|
virtual bool is_object (void) const { return false; }
|
||||||
virtual bool is_array (void) const { return false; }
|
virtual bool is_array (void) const { return false; }
|
||||||
virtual bool is_string (void) const { return false; }
|
virtual bool is_string (void) const { return false; }
|
||||||
virtual bool is_number (void) const { return false; }
|
virtual bool is_number (void) const { return false; }
|
||||||
virtual bool is_boolean (void) const { return false; }
|
virtual bool is_boolean (void) const { return false; }
|
||||||
virtual bool is_null (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 = 0;
|
||||||
virtual bool operator!=(const node &rhs) const;
|
virtual bool operator!=(const node &rhs) const;
|
||||||
virtual bool operator==(const object &) const { return false; }
|
virtual bool operator==(const object &) const { return false; }
|
||||||
virtual bool operator==(const array &) const { return false; }
|
virtual bool operator==(const array &) const { return false; }
|
||||||
virtual bool operator==(const string &) const { return false; }
|
virtual bool operator==(const string &) const { return false; }
|
||||||
virtual bool operator==(const number &) const { return false; }
|
virtual bool operator==(const number &) const { return false; }
|
||||||
virtual bool operator==(const boolean &) const { return false; }
|
virtual bool operator==(const boolean &) const { return false; }
|
||||||
virtual bool operator==(const null &) 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;
|
||||||
virtual bool operator!=(const char *rhs) const { return !(*this == rhs); }
|
virtual bool operator!=(const char *rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
virtual const node& operator[] (const std::string&) const;
|
virtual const node& operator[] (const std::string&) const;
|
||||||
virtual const node& operator[] (unsigned int) 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.
|
/// Represents a JSON object, and contains its children.
|
||||||
class object : public node {
|
class object : public node {
|
||||||
protected:
|
protected:
|
||||||
typedef std::map<std::string, std::unique_ptr<node>> value_store;
|
typedef std::map<std::string, std::unique_ptr<node>> value_store;
|
||||||
public:
|
public:
|
||||||
typedef value_store::iterator iterator;
|
typedef value_store::iterator iterator;
|
||||||
typedef value_store::const_iterator const_iterator;
|
typedef value_store::const_iterator const_iterator;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
value_store m_values;
|
value_store m_values;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~object ();
|
virtual ~object ();
|
||||||
|
|
||||||
virtual const object& as_object (void) const { return *this; }
|
virtual const object& as_object (void) const { return *this; }
|
||||||
virtual bool is_object (void) const { return true; }
|
virtual bool is_object (void) const { return true; }
|
||||||
virtual bool operator==(const object &rhs) const;
|
virtual bool operator==(const object &rhs) const;
|
||||||
virtual bool operator==(const node &rhs) const
|
virtual bool operator==(const node &rhs) const
|
||||||
{ return rhs == *this; }
|
{ return rhs == *this; }
|
||||||
|
|
||||||
virtual void insert (const std::string &key, std::unique_ptr<node>&& value);
|
virtual void insert (const std::string &key, std::unique_ptr<node>&& value);
|
||||||
virtual const node& operator[](const std::string &key) const;
|
virtual const node& operator[](const std::string &key) const;
|
||||||
virtual bool has (const std::string&) const;
|
virtual bool has (const std::string&) const;
|
||||||
|
|
||||||
virtual void clear (void);
|
virtual void clear (void);
|
||||||
virtual void erase (const std::string &key);
|
virtual void erase (const std::string &key);
|
||||||
|
|
||||||
virtual const_iterator begin (void) const;
|
virtual const_iterator begin (void) const;
|
||||||
virtual const_iterator end (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.
|
/// Represents a JSON array, and contains its children.
|
||||||
class array : public node {
|
class array : public node {
|
||||||
protected:
|
protected:
|
||||||
typedef std::vector<std::unique_ptr<node>>::iterator pointer_array_iterator;
|
typedef std::vector<std::unique_ptr<node>>::iterator pointer_array_iterator;
|
||||||
typedef std::vector<std::unique_ptr<node>>::const_iterator const_pointer_array_iterator;
|
typedef std::vector<std::unique_ptr<node>>::const_iterator const_pointer_array_iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef referencing_iterator<pointer_array_iterator> iterator;
|
typedef referencing_iterator<pointer_array_iterator> iterator;
|
||||||
typedef referencing_iterator<const_pointer_array_iterator> const_iterator;
|
typedef referencing_iterator<const_pointer_array_iterator> const_iterator;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::unique_ptr<node>> m_values;
|
std::vector<std::unique_ptr<node>> m_values;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~array();
|
virtual ~array();
|
||||||
|
|
||||||
virtual const array& as_array (void) const { return *this; }
|
virtual const array& as_array (void) const { return *this; }
|
||||||
virtual bool is_array (void) const { return true; }
|
virtual bool is_array (void) const { return true; }
|
||||||
virtual bool operator==(const array &rhs) const;
|
virtual bool operator==(const array &rhs) const;
|
||||||
virtual bool operator==(const node &rhs) const
|
virtual bool operator==(const node &rhs) const
|
||||||
{ return rhs == *this; }
|
{ return rhs == *this; }
|
||||||
|
|
||||||
virtual size_t size (void) const
|
virtual size_t size (void) const
|
||||||
{ return m_values.size (); }
|
{ return m_values.size (); }
|
||||||
virtual node& operator [](unsigned int idx)
|
virtual node& operator [](unsigned int idx)
|
||||||
{ return *m_values[idx]; }
|
{ return *m_values[idx]; }
|
||||||
virtual const node& operator [](unsigned int idx) const
|
virtual const node& operator [](unsigned int idx) const
|
||||||
{ return *m_values[idx]; }
|
{ return *m_values[idx]; }
|
||||||
|
|
||||||
virtual const_iterator begin (void) const { return const_iterator (m_values.begin ()); }
|
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 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.
|
/// Represents a JSON string literal.
|
||||||
class string : public node {
|
class string : public node {
|
||||||
protected:
|
protected:
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit string (const std::string &_value): m_value (_value) { ; }
|
explicit string (const std::string &_value): m_value (_value) { ; }
|
||||||
explicit string (const char *_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 const string& as_string (void) const { return *this; }
|
||||||
virtual bool is_string (void) const { return true; }
|
virtual bool is_string (void) const { return true; }
|
||||||
virtual bool operator==(const char *rhs) const;
|
virtual bool operator==(const char *rhs) const;
|
||||||
virtual bool operator==(const string &rhs) const;
|
virtual bool operator==(const string &rhs) const;
|
||||||
virtual bool operator==(const node &rhs) const
|
virtual bool operator==(const node &rhs) const
|
||||||
{ return rhs == *this; }
|
{ 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; }
|
operator const std::string&(void) const { return m_value; }
|
||||||
const std::string& native (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.
|
/// Represents a JSON integer/float literal.
|
||||||
class number : public node {
|
class number : public node {
|
||||||
protected:
|
protected:
|
||||||
double m_value;
|
double m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit number (double _value): m_value (_value) { ; }
|
explicit number (double _value): m_value (_value) { ; }
|
||||||
explicit number (int _value): m_value (_value) { ; }
|
explicit number (int _value): m_value (_value) { ; }
|
||||||
explicit number (size_t _value): m_value (_value) { ; }
|
explicit number (size_t _value): m_value (_value) { ; }
|
||||||
|
|
||||||
virtual const number& as_number (void) const { return *this; }
|
virtual const number& as_number (void) const { return *this; }
|
||||||
virtual bool is_number (void) const { return true; }
|
virtual bool is_number (void) const { return true; }
|
||||||
virtual bool operator==(const number &rhs) const;
|
virtual bool operator==(const number &rhs) const;
|
||||||
virtual bool operator==(const node &rhs) const
|
virtual bool operator==(const node &rhs) const
|
||||||
{ return rhs == *this; }
|
{ return rhs == *this; }
|
||||||
|
|
||||||
operator double(void) const { return m_value; }
|
operator double(void) const { return m_value; }
|
||||||
double native (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.
|
/// Represents a JSON boolean literal.
|
||||||
class boolean : public node {
|
class boolean : public node {
|
||||||
protected:
|
protected:
|
||||||
bool m_value;
|
bool m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit boolean (bool _value): m_value (_value) { ; }
|
explicit boolean (bool _value): m_value (_value) { ; }
|
||||||
|
|
||||||
virtual const boolean& as_boolean (void) const { return *this; }
|
virtual const boolean& as_boolean (void) const { return *this; }
|
||||||
virtual bool is_boolean (void) const { return true; }
|
virtual bool is_boolean (void) const { return true; }
|
||||||
virtual bool operator==(const boolean &rhs) const;
|
virtual bool operator==(const boolean &rhs) const;
|
||||||
virtual bool operator==(const node &rhs) const
|
virtual bool operator==(const node &rhs) const
|
||||||
{ return rhs == *this; }
|
{ return rhs == *this; }
|
||||||
|
|
||||||
operator bool (void) const { return m_value; }
|
operator bool (void) const { return m_value; }
|
||||||
bool native (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.
|
/// Represents a JSON null value.
|
||||||
class null : public node {
|
class null : public node {
|
||||||
public:
|
public:
|
||||||
virtual bool operator==(const null&) const { return true; }
|
virtual bool operator==(const null&) const { return true; }
|
||||||
virtual bool operator==(const node &rhs) const
|
virtual bool operator==(const node &rhs) const
|
||||||
{ return rhs == *this; }
|
{ return rhs == *this; }
|
||||||
|
|
||||||
virtual bool is_null (void) const { return true; }
|
virtual bool is_null (void) const { return true; }
|
||||||
virtual const null& as_null (void) const { return *this; }
|
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.
|
/// The base class for all exceptions throw directly by the json namespace.
|
||||||
class error : public std::runtime_error {
|
class error : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
error (const std::string &_what):
|
error (const std::string &_what):
|
||||||
std::runtime_error (_what)
|
std::runtime_error (_what)
|
||||||
{ ; }
|
{ ; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base class for all type conversion errors
|
/// Base class for all type conversion errors
|
||||||
class type_error : public error {
|
class type_error : public error {
|
||||||
public:
|
public:
|
||||||
type_error (const std::string &_what):
|
type_error (const std::string &_what):
|
||||||
error (_what)
|
error (_what)
|
||||||
{ ; }
|
{ ; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base class for errors thrown during parsing
|
/// Base class for errors thrown during parsing
|
||||||
class parse_error : public error {
|
class parse_error : public error {
|
||||||
public:
|
public:
|
||||||
parse_error (const std::string &_what):
|
parse_error (const std::string &_what):
|
||||||
error (_what)
|
error (_what)
|
||||||
{ ; }
|
{ ; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base class for errors thrown during schema validation
|
/// Base class for errors thrown during schema validation
|
||||||
class schema_error : public error {
|
class schema_error : public error {
|
||||||
public:
|
public:
|
||||||
schema_error (const std::string &_what):
|
schema_error (const std::string &_what):
|
||||||
error (_what)
|
error (_what)
|
||||||
{ ; }
|
{ ; }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator <<(std::ostream &os, const json::node &n);
|
operator <<(std::ostream &os, const json::tree::node &n);
|
||||||
|
|
||||||
|
|
||||||
// Instantiate this template for the type you wish to output. We use a
|
// Instantiate this template for the type you wish to output. We use a
|
||||||
// helper class here to avoid partial template specialisation of a
|
// helper class here to avoid partial template specialisation of a
|
||||||
// function (eg, for templated types).
|
// function (eg, for templated types).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct io {
|
struct io {
|
||||||
static std::unique_ptr<json::node> serialise (const T&);
|
static std::unique_ptr<json::tree::node> serialise (const T&);
|
||||||
static T deserialise (const json::node&);
|
static T deserialise (const json::tree::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)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class ...Args>
|
template <typename T, class ...Args>
|
||||||
T from_json (const json::node &n, Args&&... args) {
|
std::unique_ptr<json::tree::node> to_json (const T &t, Args&&... args) {
|
||||||
return json::io<T>::deserialise (n, std::forward<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
|
#endif
|
||||||
|
@ -186,10 +186,10 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
namespace json {
|
namespace json { namespace tree {
|
||||||
template <>
|
template <>
|
||||||
util::range<double>
|
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" ||
|
if (node.is_string () && (node == "UNIT" ||
|
||||||
node == "unit")) {
|
node == "unit")) {
|
||||||
return util::range<double>::UNIT;
|
return util::range<double>::UNIT;
|
||||||
@ -203,4 +203,4 @@ namespace json {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} }
|
||||||
|
@ -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 ());
|
CHECK (ptr->is_object ());
|
||||||
|
|
||||||
const json::node &ref = *ptr;
|
const json::tree::node &ref = *ptr;
|
||||||
|
|
||||||
CHECK ( ref["string"].is_string ());
|
CHECK ( ref["string"].is_string ());
|
||||||
CHECK (!ref["string"].is_array ());
|
CHECK (!ref["string"].is_array ());
|
||||||
|
@ -48,8 +48,8 @@ main (int argc, char **argv) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
boost::filesystem::path input (argv[ARG_INPUT]);
|
boost::filesystem::path input (argv[ARG_INPUT]);
|
||||||
std::cout << *json::parse (input) << "\n";
|
std::cout << *json::tree::parse (input) << "\n";
|
||||||
} catch (const json::error& err) {
|
} catch (const json::tree::error& err) {
|
||||||
std::cerr << err.what () << "\n";
|
std::cerr << err.what () << "\n";
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ print_usage (int argc, char **argv) {
|
|||||||
|
|
||||||
|
|
||||||
const char*
|
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_array ()) return "array";
|
||||||
if (node.is_boolean ()) return "boolean";
|
if (node.is_boolean ()) return "boolean";
|
||||||
if (node.is_null ()) return "null";
|
if (node.is_null ()) return "null";
|
||||||
@ -68,13 +68,13 @@ type_to_string (const json::node &node) {
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_node_valid (const json::node &node,
|
is_node_valid (const json::tree::node &node,
|
||||||
const json::object &schema);
|
const json::tree::object &schema);
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_type_valid (const json::node &node,
|
is_type_valid (const json::tree::node &node,
|
||||||
const json::node &type) {
|
const json::tree::node &type) {
|
||||||
if (type.is_array ()) {
|
if (type.is_array ()) {
|
||||||
return any_of (type.as_array ().begin (),
|
return any_of (type.as_array ().begin (),
|
||||||
type.as_array ().end (),
|
type.as_array ().end (),
|
||||||
@ -82,20 +82,20 @@ is_type_valid (const json::node &node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!type.is_string ())
|
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 ANY_VALIDATOR = [] (const json::tree::node &) { return true; };
|
||||||
static const auto INT_VALIDATOR = [] (const json::node &n) {
|
static const auto INT_VALIDATOR = [] (const json::tree::node &n) {
|
||||||
return n.is_number () && is_integer (n.as_number ());
|
return n.is_number () && is_integer (n.as_number ());
|
||||||
};
|
};
|
||||||
|
|
||||||
static const map<string, function<bool(const json::node&)>> TYPE_VALIDATORS ({
|
static const map<string, function<bool(const json::tree::node&)>> TYPE_VALIDATORS ({
|
||||||
{ "array", bind (&json::node::is_array, _1) },
|
{ "array", bind (&json::tree::node::is_array, _1) },
|
||||||
{ "boolean", bind (&json::node::is_boolean, _1) },
|
{ "boolean", bind (&json::tree::node::is_boolean, _1) },
|
||||||
{ "null", bind (&json::node::is_null, _1) },
|
{ "null", bind (&json::tree::node::is_null, _1) },
|
||||||
{ "number", bind (&json::node::is_number, _1) },
|
{ "number", bind (&json::tree::node::is_number, _1) },
|
||||||
{ "object", bind (&json::node::is_object, _1) },
|
{ "object", bind (&json::tree::node::is_object, _1) },
|
||||||
{ "string", bind (&json::node::is_string, _1) },
|
{ "string", bind (&json::tree::node::is_string, _1) },
|
||||||
{ "any", ANY_VALIDATOR },
|
{ "any", ANY_VALIDATOR },
|
||||||
{ "integer", INT_VALIDATOR },
|
{ "integer", INT_VALIDATOR },
|
||||||
});
|
});
|
||||||
@ -111,18 +111,18 @@ is_type_valid (const json::node &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_disallow_valid (const json::node &node,
|
is_disallow_valid (const json::tree::node &node,
|
||||||
const json::node &constraint)
|
const json::tree::node &constraint)
|
||||||
{ return !is_type_valid (node, constraint); }
|
{ return !is_type_valid (node, constraint); }
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_enum_valid (const json::node &node,
|
is_enum_valid (const json::tree::node &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!constraint.is_array ())
|
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 (),
|
return valids.end () != std::find (valids.begin (),
|
||||||
valids.end (),
|
valids.end (),
|
||||||
node);
|
node);
|
||||||
@ -130,15 +130,15 @@ is_enum_valid (const json::node &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_enum_valid (const json::string &node,
|
is_enum_valid (const json::tree::string &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
return is_enum_valid (static_cast<const json::node&> (node), constraint);
|
return is_enum_valid (static_cast<const json::tree::node&> (node), constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_always_valid (const json::node &,
|
is_always_valid (const json::tree::node &,
|
||||||
const json::node &)
|
const json::tree::node &)
|
||||||
{ return true; }
|
{ return true; }
|
||||||
|
|
||||||
|
|
||||||
@ -153,14 +153,14 @@ is_always_valid (const json::node &,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_boolean_valid (const json::node &node,
|
is_boolean_valid (const json::tree::node &node,
|
||||||
const json::object &)
|
const json::tree::object &)
|
||||||
{ return node.is_boolean (); }
|
{ return node.is_boolean (); }
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_null_valid (const json::node &node,
|
is_null_valid (const json::tree::node &node,
|
||||||
const json::object &)
|
const json::tree::object &)
|
||||||
{ return node.is_null (); }
|
{ return node.is_null (); }
|
||||||
|
|
||||||
|
|
||||||
@ -169,36 +169,36 @@ is_null_valid (const json::node &node,
|
|||||||
//
|
//
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_minimum_valid (const json::number &node,
|
is_minimum_valid (const json::tree::number &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
return constraint["minimum"].as_number () <= node;
|
return constraint["minimum"].as_number () <= node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_maximum_valid (const json::number &node,
|
is_maximum_valid (const json::tree::number &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
return constraint["maximum"].as_number () >= node;
|
return constraint["maximum"].as_number () >= node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_exclusive_minimum_valid (const json::number &node,
|
is_exclusive_minimum_valid (const json::tree::number &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
return constraint["exclusiveMinimum"].as_number () < node;
|
return constraint["exclusiveMinimum"].as_number () < node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_exclusive_maximum_valid (const json::number &node,
|
is_exclusive_maximum_valid (const json::tree::number &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
return constraint["exclusiveMaximum"].as_number () > node;
|
return constraint["exclusiveMaximum"].as_number () > node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_divisible_by_valid (const json::number &node,
|
is_divisible_by_valid (const json::tree::number &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
return exactly_equal (fmod (node.native (),
|
return exactly_equal (fmod (node.native (),
|
||||||
constraint["divisibleBy"].as_number ()),
|
constraint["divisibleBy"].as_number ()),
|
||||||
0.0);
|
0.0);
|
||||||
@ -206,9 +206,9 @@ is_divisible_by_valid (const json::number &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_number_valid (const json::number &node,
|
is_number_valid (const json::tree::number &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
typedef bool (*number_validator_t)(const json::number&, const json::node&);
|
typedef bool (*number_validator_t)(const json::tree::number&, const json::tree::node&);
|
||||||
static const map<string, number_validator_t> VALIDATORS = {
|
static const map<string, number_validator_t> VALIDATORS = {
|
||||||
{ "minimum", &is_minimum_valid },
|
{ "minimum", &is_minimum_valid },
|
||||||
{ "maximum", &is_maximum_valid },
|
{ "maximum", &is_maximum_valid },
|
||||||
@ -239,8 +239,8 @@ is_number_valid (const json::number &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_min_length_valid (const json::string &node,
|
is_min_length_valid (const json::tree::string &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!is_integer (constraint))
|
if (!is_integer (constraint))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -249,8 +249,8 @@ is_min_length_valid (const json::string &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_max_length_valid (const json::string &node,
|
is_max_length_valid (const json::tree::string &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!is_integer (constraint))
|
if (!is_integer (constraint))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -259,8 +259,8 @@ is_max_length_valid (const json::string &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_pattern_valid (const json::string &node,
|
is_pattern_valid (const json::tree::string &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!constraint.is_string ())
|
if (!constraint.is_string ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -271,9 +271,9 @@ is_pattern_valid (const json::string &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_string_valid (const json::string &node,
|
is_string_valid (const json::tree::string &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
typedef bool (*string_validator_t)(const json::string&, const json::node&);
|
typedef bool (*string_validator_t)(const json::tree::string&, const json::tree::node&);
|
||||||
static const map<std::string, string_validator_t> VALIDATORS = {
|
static const map<std::string, string_validator_t> VALIDATORS = {
|
||||||
{ "minLength", &is_min_length_valid },
|
{ "minLength", &is_min_length_valid },
|
||||||
{ "maxLength", &is_max_length_valid },
|
{ "maxLength", &is_max_length_valid },
|
||||||
@ -281,9 +281,9 @@ is_string_valid (const json::string &node,
|
|||||||
{ "enum", &is_enum_valid },
|
{ "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 std::string &key = i.first;
|
||||||
const json::node &constraint = *i.second;
|
const json::tree::node &constraint = *i.second;
|
||||||
|
|
||||||
auto validator = VALIDATORS.find (key);
|
auto validator = VALIDATORS.find (key);
|
||||||
if (validator == VALIDATORS.end ()) {
|
if (validator == VALIDATORS.end ()) {
|
||||||
@ -302,8 +302,8 @@ is_string_valid (const json::string &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_string_valid (const json::node &node,
|
is_string_valid (const json::tree::node &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
if (!node.is_string ())
|
if (!node.is_string ())
|
||||||
return false;
|
return false;
|
||||||
return is_string_valid (node.as_string (), schema);
|
return is_string_valid (node.as_string (), schema);
|
||||||
@ -315,36 +315,36 @@ is_string_valid (const json::node &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_max_items_valid (const json::array &node,
|
is_max_items_valid (const json::tree::array &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!constraint.is_number () && is_integer (constraint.as_number ()))
|
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 ();
|
return node.size () <= constraint.as_number ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_min_items_valid (const json::array &node,
|
is_min_items_valid (const json::tree::array &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!constraint.is_number () && is_integer (constraint.as_number ()))
|
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 ();
|
return node.size () >= constraint.as_number ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_unique_items_valid (const json::array &node,
|
is_unique_items_valid (const json::tree::array &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
if (!constraint.is_boolean ())
|
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)
|
if (node.size () < 2)
|
||||||
return true;
|
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 ())
|
if (find (i + 1, node.end (), *i) != node.end ())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -354,13 +354,13 @@ is_unique_items_valid (const json::array &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_items_valid (const json::array &node,
|
is_items_valid (const json::tree::array &node,
|
||||||
const json::node &_schema) {
|
const json::tree::node &_schema) {
|
||||||
if (!_schema.is_object ())
|
if (!_schema.is_object ())
|
||||||
throw json::schema_error ("array_items constraint must be an object");
|
throw json::tree::schema_error ("array_items constraint must be an object");
|
||||||
const json::object &schema = _schema.as_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))
|
if (!is_node_valid (i, schema))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -372,19 +372,19 @@ is_items_valid (const json::array &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_additional_items_valid (const json::array &,
|
is_additional_items_valid (const json::tree::array &,
|
||||||
const json::node &) {
|
const json::tree::node &) {
|
||||||
not_implemented ();
|
not_implemented ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_array_valid (const json::array &node,
|
is_array_valid (const json::tree::array &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
CHECK (node.is_array ());
|
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 ({
|
static const map<string, array_validator_t> VALIDATORS ({
|
||||||
{ "items", &is_items_valid },
|
{ "items", &is_items_valid },
|
||||||
{ "minItems", &is_min_items_valid },
|
{ "minItems", &is_min_items_valid },
|
||||||
@ -393,9 +393,9 @@ is_array_valid (const json::array &node,
|
|||||||
{ "additionalItems", &is_additional_items_valid },
|
{ "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 std::string &key = i.first;
|
||||||
const json::node &constraint = *i.second;
|
const json::tree::node &constraint = *i.second;
|
||||||
|
|
||||||
auto validator = VALIDATORS.find (key);
|
auto validator = VALIDATORS.find (key);
|
||||||
if (validator == VALIDATORS.end ()) {
|
if (validator == VALIDATORS.end ()) {
|
||||||
@ -418,11 +418,11 @@ is_array_valid (const json::array &node,
|
|||||||
//
|
//
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_properties_valid (const json::object &node,
|
is_properties_valid (const json::tree::object &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
for (const json::object::const_iterator::value_type &element: node) {
|
for (const json::tree::object::const_iterator::value_type &element: node) {
|
||||||
const std::string &key = element.first;
|
const std::string &key = element.first;
|
||||||
const json::node &val = *element.second;
|
const json::tree::node &val = *element.second;
|
||||||
|
|
||||||
if (!schema.has (key)) {
|
if (!schema.has (key)) {
|
||||||
std::cerr << "[warning] no constraint found for key: " << key << "\n";
|
std::cerr << "[warning] no constraint found for key: " << key << "\n";
|
||||||
@ -440,30 +440,30 @@ is_properties_valid (const json::object &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_properties_valid (const json::object &node,
|
is_properties_valid (const json::tree::object &node,
|
||||||
const json::node &constraint) {
|
const json::tree::node &constraint) {
|
||||||
CHECK (node.is_object ());
|
CHECK (node.is_object ());
|
||||||
|
|
||||||
if (!constraint.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 ());
|
return is_properties_valid (node, constraint.as_object ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_object_valid (const json::object &node,
|
is_object_valid (const json::tree::object &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
typedef bool (*object_validator_t)(const json::object&, const json::node&);
|
typedef bool (*object_validator_t)(const json::tree::object&, const json::tree::node&);
|
||||||
static const map<string, object_validator_t> VALIDATORS = {
|
static const map<string, object_validator_t> VALIDATORS = {
|
||||||
{ "properties", &is_properties_valid },
|
{ "properties", &is_properties_valid },
|
||||||
//{ "patternProperties", &is_pattern_properties_valid },
|
//{ "patternProperties", &is_pattern_properties_valid },
|
||||||
//{ "additionalProperties", &is_additionaL_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 std::string &name = i.first;
|
||||||
const json::node &constraint = *i.second;
|
const json::tree::node &constraint = *i.second;
|
||||||
|
|
||||||
auto validator = VALIDATORS.find (name);
|
auto validator = VALIDATORS.find (name);
|
||||||
if (validator == VALIDATORS.end ()) {
|
if (validator == VALIDATORS.end ()) {
|
||||||
@ -482,8 +482,8 @@ is_object_valid (const json::object &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_object_valid (const json::node &node,
|
is_object_valid (const json::tree::node &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
if (!node.is_object ())
|
if (!node.is_object ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -496,8 +496,8 @@ is_object_valid (const json::node &node,
|
|||||||
//
|
//
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_node_valid (const json::node &node,
|
is_node_valid (const json::tree::node &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
if (schema.has ("$ref")) {
|
if (schema.has ("$ref")) {
|
||||||
const std::string &uri = schema["$ref"].as_string ();
|
const std::string &uri = schema["$ref"].as_string ();
|
||||||
std::cerr << "loading referenced schema: " << uri << "\n";
|
std::cerr << "loading referenced schema: " << uri << "\n";
|
||||||
@ -507,7 +507,7 @@ is_node_valid (const json::node &node,
|
|||||||
return false;
|
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 ());
|
return is_node_valid (node, referenced->as_object ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,8 +558,8 @@ is_node_valid (const json::node &node,
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_root_valid (const json::node &node,
|
is_root_valid (const json::tree::node &node,
|
||||||
const json::object &schema) {
|
const json::tree::object &schema) {
|
||||||
if (!node.is_array () && !node.is_object ())
|
if (!node.is_array () && !node.is_object ())
|
||||||
return false;
|
return false;
|
||||||
return is_node_valid (node, schema);
|
return is_node_valid (node, schema);
|
||||||
@ -579,11 +579,11 @@ main (int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load the schema and input
|
// Load the schema and input
|
||||||
unique_ptr<json::node> schema, input;
|
unique_ptr<json::tree::node> schema, input;
|
||||||
try {
|
try {
|
||||||
schema = json::parse (boost::filesystem::path (argv[ARG_SCHEMA]));
|
schema = json::tree::parse (boost::filesystem::path (argv[ARG_SCHEMA]));
|
||||||
input = json::parse (boost::filesystem::path (argv[ARG_INPUT]));
|
input = json::tree::parse (boost::filesystem::path (argv[ARG_INPUT]));
|
||||||
} catch (const json::parse_error &err) {
|
} catch (const json::tree::parse_error &err) {
|
||||||
std::cerr << "malformed json for schema or input. " << err.what () << "\n";
|
std::cerr << "malformed json for schema or input. " << err.what () << "\n";
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -594,7 +594,7 @@ main (int argc, char **argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const json::object &schema_object = schema->as_object ();
|
const json::tree::object &schema_object = schema->as_object ();
|
||||||
|
|
||||||
// Check input is valid
|
// Check input is valid
|
||||||
if (!is_node_valid (*input, schema_object)) {
|
if (!is_node_valid (*input, schema_object)) {
|
||||||
|
@ -23,8 +23,8 @@ main (int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
json::parse (boost::filesystem::path (argv[ARG_PATH]));
|
json::tree::parse (boost::filesystem::path (argv[ARG_PATH]));
|
||||||
} catch (json::error &x) {
|
} catch (json::tree::error &x) {
|
||||||
std::cerr << "Error: " << x.what () << std::endl;
|
std::cerr << "Error: " << x.what () << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -414,9 +414,9 @@ util::operator<< (std::ostream &os, const util::vector<S,T> &v) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
const json::node&
|
const json::tree::node&
|
||||||
util::operator>> (const json::node &node, util::vector<S,T> &v) {
|
util::operator>> (const json::tree::node &node, util::vector<S,T> &v) {
|
||||||
const json::array &array = node.as_array ();
|
const json::tree::array &array = node.as_array ();
|
||||||
if (array.size () != S)
|
if (array.size () != S)
|
||||||
throw std::runtime_error ("Invalid dimensionality for json-to-vector");
|
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 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 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) \
|
#define INSTANTIATE(T) \
|
||||||
|
@ -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> std::ostream& operator<< (std::ostream&, const vector<S,T>&);
|
||||||
|
|
||||||
template <size_t S, typename 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
|
// convenience typedefs
|
||||||
typedef vector<2,size_t> vector2u;
|
typedef vector<2,size_t> vector2u;
|
||||||
|
Loading…
Reference in New Issue
Block a user