2010-02-02 14:14:52 +00:00
|
|
|
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
|
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
|
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
2010-07-16 06:31:56 +00:00
|
|
|
#include <config.h>
|
2010-03-19 19:58:38 +00:00
|
|
|
|
2010-07-16 06:31:56 +00:00
|
|
|
#include <cc/data.h>
|
2009-10-30 17:28:17 +00:00
|
|
|
|
2013-01-08 20:18:06 -08:00
|
|
|
#include <cstring>
|
2010-04-01 00:38:56 +00:00
|
|
|
#include <cassert>
|
2010-06-30 19:31:23 +00:00
|
|
|
#include <climits>
|
2010-08-16 23:36:54 +00:00
|
|
|
#include <map>
|
2009-10-30 17:28:17 +00:00
|
|
|
#include <cstdio>
|
|
|
|
#include <iostream>
|
2010-03-15 04:52:16 +00:00
|
|
|
#include <string>
|
2009-10-30 17:28:17 +00:00
|
|
|
#include <sstream>
|
|
|
|
|
2010-03-15 04:52:16 +00:00
|
|
|
#include <boost/algorithm/string.hpp> // for iequals
|
2009-10-30 17:28:17 +00:00
|
|
|
|
2010-06-15 13:37:41 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
2009-10-30 17:28:17 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2012-04-02 15:16:27 +02:00
|
|
|
namespace {
|
2013-01-08 20:12:37 -08:00
|
|
|
const char* const WHITESPACE = " \b\f\n\r\t";
|
2012-04-02 15:16:27 +02:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
namespace isc {
|
|
|
|
namespace data {
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
std::string
|
2010-08-16 23:36:54 +00:00
|
|
|
Element::str() const {
|
2010-06-15 10:11:48 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
toJSON(ss);
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ss.str());
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string
|
2010-08-16 23:36:54 +00:00
|
|
|
Element::toWire() const {
|
2010-06-15 10:11:48 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
toJSON(ss);
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ss.str());
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
Element::toWire(std::ostream& ss) const {
|
2010-06-15 10:11:48 +00:00
|
|
|
toJSON(ss);
|
|
|
|
}
|
|
|
|
|
2010-03-19 19:58:38 +00:00
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::getValue(long int&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::getValue(double&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::getValue(bool&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::getValue(std::string&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::getValue(std::vector<ConstElementPtr>&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::getValue(std::map<std::string, ConstElementPtr>&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::setValue(const long int) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::setValue(const double) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::setValue(const bool) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::setValue(const std::string&) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::setValue(const std::vector<ConstElementPtr>&) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::setValue(const std::map<std::string, ConstElementPtr>&) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::get(const int) const {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "get(int) called on a non-list Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::set(const size_t, ConstElementPtr) {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "set(int, element) called on a non-list Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::add(ConstElementPtr) {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "add() called on a non-list Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::remove(const int) {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "remove(int) called on a non-list Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
2010-08-16 23:36:54 +00:00
|
|
|
Element::size() const {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "size() called on a non-list Element");
|
|
|
|
}
|
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::get(const std::string&) const {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "get(string) called on a non-map Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::set(const std::string&, ConstElementPtr) {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "set(name, element) called on a non-map Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::remove(const std::string&) {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "remove(string) called on a non-map Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::contains(const std::string&) const {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "contains(string) called on a non-map Element");
|
|
|
|
}
|
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr
|
2010-11-08 05:58:10 +00:00
|
|
|
Element::find(const std::string&) const {
|
2010-03-19 19:58:38 +00:00
|
|
|
isc_throw(TypeError, "find(string) called on a non-map Element");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
Element::find(const std::string&, ConstElementPtr&) const {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-03-19 19:58:38 +00:00
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
namespace {
|
|
|
|
inline void
|
2010-10-15 08:59:24 +00:00
|
|
|
throwJSONError(const std::string& error, const std::string& file, int line,
|
|
|
|
int pos)
|
2010-02-02 14:14:52 +00:00
|
|
|
{
|
2010-06-16 10:15:21 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << error << " in " + file + ":" << line << ":" << pos;
|
|
|
|
isc_throw(JSONError, ss.str());
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2010-03-15 08:35:45 +00:00
|
|
|
}
|
2009-10-30 17:28:17 +00:00
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
std::ostream&
|
2013-01-08 20:12:37 -08:00
|
|
|
operator<<(std::ostream& out, const Element& e) {
|
2010-08-16 23:36:54 +00:00
|
|
|
return (out << e.str());
|
2009-11-04 13:41:12 +00:00
|
|
|
}
|
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
bool
|
|
|
|
operator==(const Element& a, const Element& b) {
|
|
|
|
return (a.equals(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const Element& a, const Element& b) {
|
|
|
|
return (!a.equals(b));
|
2010-02-28 20:00:49 +00:00
|
|
|
};
|
|
|
|
|
2009-10-30 17:28:17 +00:00
|
|
|
//
|
|
|
|
// factory functions
|
|
|
|
//
|
2010-06-15 10:11:48 +00:00
|
|
|
ElementPtr
|
|
|
|
Element::create() {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new NullElement()));
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
|
|
|
|
2009-10-30 17:28:17 +00:00
|
|
|
ElementPtr
|
2010-06-30 11:49:10 +00:00
|
|
|
Element::create(const long int i) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new IntElement(i)));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-03-15 08:24:50 +00:00
|
|
|
Element::create(const double d) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new DoubleElement(d)));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-03-15 08:24:50 +00:00
|
|
|
Element::create(const std::string& s) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new StringElement(s)));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-03-15 08:24:50 +00:00
|
|
|
Element::create(const bool b) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new BoolElement(b)));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-06-15 12:38:55 +00:00
|
|
|
Element::createList() {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new ListElement()));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-06-15 12:38:55 +00:00
|
|
|
Element::createMap() {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr(new MapElement()));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2010-06-15 13:02:26 +00:00
|
|
|
// helper functions for fromJSON factory
|
2009-10-30 17:28:17 +00:00
|
|
|
//
|
2010-03-15 08:35:45 +00:00
|
|
|
namespace {
|
|
|
|
bool
|
2013-01-08 20:12:37 -08:00
|
|
|
charIn(const int c, const char* chars) {
|
2013-01-08 20:18:06 -08:00
|
|
|
const size_t chars_len = std::strlen(chars);
|
|
|
|
for (size_t i = 0; i < chars_len; ++i) {
|
2009-10-30 17:28:17 +00:00
|
|
|
if (chars[i] == c) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (true);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
void
|
2013-01-08 20:12:37 -08:00
|
|
|
skipChars(std::istream& in, const char* chars, int& line, int& pos) {
|
2012-12-21 10:11:05 +01:00
|
|
|
int c = in.peek();
|
2013-01-08 20:12:37 -08:00
|
|
|
while (charIn(c, chars) && c != EOF) {
|
2009-11-04 13:41:12 +00:00
|
|
|
if (c == '\n') {
|
2010-03-15 08:24:50 +00:00
|
|
|
++line;
|
2009-11-04 13:41:12 +00:00
|
|
|
pos = 1;
|
|
|
|
} else {
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2009-11-04 13:41:12 +00:00
|
|
|
}
|
2013-02-09 14:52:37 -08:00
|
|
|
in.ignore();
|
2009-10-30 17:28:17 +00:00
|
|
|
c = in.peek();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip on the input stream to one of the characters in chars
|
|
|
|
// if another character is found this function returns false
|
2010-01-16 07:37:40 +00:00
|
|
|
// unless that character is specified in the optional may_skip
|
2009-10-30 17:28:17 +00:00
|
|
|
//
|
|
|
|
// the character found is left on the stream
|
2010-03-15 08:35:45 +00:00
|
|
|
void
|
2013-01-08 20:12:37 -08:00
|
|
|
skipTo(std::istream& in, const std::string& file, int& line,
|
|
|
|
int& pos, const char* chars, const char* may_skip="")
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
2012-12-21 10:11:05 +01:00
|
|
|
int c = in.get();
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2009-10-30 17:28:17 +00:00
|
|
|
while (c != EOF) {
|
2009-11-04 13:41:12 +00:00
|
|
|
if (c == '\n') {
|
|
|
|
pos = 1;
|
2010-03-15 08:24:50 +00:00
|
|
|
++line;
|
2009-11-04 13:41:12 +00:00
|
|
|
}
|
2013-01-08 20:12:37 -08:00
|
|
|
if (charIn(c, may_skip)) {
|
2009-10-30 17:28:17 +00:00
|
|
|
c = in.get();
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2013-01-08 20:12:37 -08:00
|
|
|
} else if (charIn(c, chars)) {
|
|
|
|
while (charIn(in.peek(), may_skip)) {
|
2009-11-04 13:41:12 +00:00
|
|
|
if (in.peek() == '\n') {
|
|
|
|
pos = 1;
|
2010-03-15 08:24:50 +00:00
|
|
|
++line;
|
2009-11-04 13:41:12 +00:00
|
|
|
}
|
2013-02-09 14:52:37 -08:00
|
|
|
in.ignore();
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
in.putback(c);
|
2010-03-15 08:24:50 +00:00
|
|
|
--pos;
|
2009-11-04 13:41:12 +00:00
|
|
|
return;
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2012-12-21 10:11:05 +01:00
|
|
|
throwJSONError(std::string("'") + std::string(1, c) + "' read, one of \"" + chars + "\" expected", file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-15 13:37:41 +00:00
|
|
|
throwJSONError(std::string("EOF read, one of \"") + chars + "\" expected", file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
// TODO: Should we check for all other official escapes here (and
|
|
|
|
// error on the rest)?
|
2010-03-15 08:35:45 +00:00
|
|
|
std::string
|
2013-01-08 20:12:37 -08:00
|
|
|
strFromStringstream(std::istream& in, const std::string& file,
|
|
|
|
const int line, int& pos) throw (JSONError)
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
|
|
|
std::stringstream ss;
|
2012-12-21 10:11:05 +01:00
|
|
|
int c = in.get();
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2009-10-30 17:28:17 +00:00
|
|
|
if (c == '"') {
|
|
|
|
c = in.get();
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-06-15 13:37:41 +00:00
|
|
|
throwJSONError("String expected", file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2012-03-29 17:10:45 +02:00
|
|
|
|
2009-10-30 17:28:17 +00:00
|
|
|
while (c != EOF && c != '"') {
|
2012-03-29 17:10:45 +02:00
|
|
|
if (c == '\\') {
|
|
|
|
// see the spec for allowed escape characters
|
2012-03-30 11:14:57 +02:00
|
|
|
switch (in.peek()) {
|
|
|
|
case '"':
|
|
|
|
c = '"';
|
|
|
|
break;
|
|
|
|
case '/':
|
|
|
|
c = '/';
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
c = '\\';
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
c = '\b';
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
c = '\f';
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
c = '\n';
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
c = '\r';
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
c = '\t';
|
|
|
|
break;
|
|
|
|
default:
|
2012-03-29 17:56:30 +02:00
|
|
|
throwJSONError("Bad escape", file, line, pos);
|
2012-03-29 17:10:45 +02:00
|
|
|
}
|
2012-03-30 11:14:57 +02:00
|
|
|
// drop the escaped char
|
2013-02-09 14:52:37 -08:00
|
|
|
in.ignore();
|
2012-03-30 11:14:57 +02:00
|
|
|
++pos;
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2012-12-21 10:11:05 +01:00
|
|
|
ss.put(c);
|
2009-10-30 17:28:17 +00:00
|
|
|
c = in.get();
|
2010-03-15 08:24:50 +00:00
|
|
|
++pos;
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2012-04-02 10:50:26 +02:00
|
|
|
if (c == EOF) {
|
|
|
|
throwJSONError("Unterminated string", file, line, pos);
|
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ss.str());
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
std::string
|
2013-01-08 20:12:37 -08:00
|
|
|
wordFromStringstream(std::istream& in, int& pos) {
|
2009-10-30 17:28:17 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
while (isalpha(in.peek())) {
|
|
|
|
ss << (char) in.get();
|
|
|
|
}
|
2009-11-04 13:41:12 +00:00
|
|
|
pos += ss.str().size();
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ss.str());
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2013-01-08 20:12:37 -08:00
|
|
|
std::string
|
|
|
|
numberFromStringstream(std::istream& in, int& pos) {
|
2010-06-30 11:49:10 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
while (isdigit(in.peek()) || in.peek() == '+' || in.peek() == '-' ||
|
|
|
|
in.peek() == '.' || in.peek() == 'e' || in.peek() == 'E') {
|
|
|
|
ss << (char) in.get();
|
2010-01-13 13:14:31 +00:00
|
|
|
}
|
2010-06-30 11:49:10 +00:00
|
|
|
pos += ss.str().size();
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ss.str());
|
2010-01-13 13:14:31 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 13:37:41 +00:00
|
|
|
// Should we change from IntElement and DoubleElement to NumberElement
|
|
|
|
// that can also hold an e value? (and have specific getters if the
|
|
|
|
// value is larger than an int can handle)
|
2010-03-15 08:35:45 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
fromStringstreamNumber(std::istream& in, int& pos) {
|
2012-12-19 09:41:31 +05:30
|
|
|
long int i;
|
2010-06-15 10:11:48 +00:00
|
|
|
double d = 0.0;
|
|
|
|
bool is_double = false;
|
2013-01-08 20:12:37 -08:00
|
|
|
char* endptr;
|
2010-06-15 10:11:48 +00:00
|
|
|
|
2013-01-08 20:12:37 -08:00
|
|
|
std::string number = numberFromStringstream(in, pos);
|
2010-06-30 11:49:10 +00:00
|
|
|
|
|
|
|
i = strtol(number.c_str(), &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
d = strtod(number.c_str(), &endptr);
|
2010-06-15 10:11:48 +00:00
|
|
|
is_double = true;
|
2010-06-30 11:49:10 +00:00
|
|
|
if (*endptr != '\0') {
|
|
|
|
isc_throw(JSONError, std::string("Bad number: ") + number);
|
2010-06-15 10:11:48 +00:00
|
|
|
} else {
|
2010-06-30 16:34:37 +00:00
|
|
|
if (d == HUGE_VAL || d == -HUGE_VAL) {
|
2010-06-30 11:49:10 +00:00
|
|
|
isc_throw(JSONError, std::string("Number overflow: ") + number);
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-30 11:49:10 +00:00
|
|
|
} else {
|
|
|
|
if (i == LONG_MAX || i == LONG_MIN) {
|
|
|
|
isc_throw(JSONError, std::string("Number overflow: ") + number);
|
|
|
|
}
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
2012-09-27 16:00:48 +02:00
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
if (is_double) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::create(d));
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::create(i));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
fromStringstreamBool(std::istream& in, const std::string& file,
|
|
|
|
const int line, int& pos)
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
2013-01-08 20:12:37 -08:00
|
|
|
const std::string word = wordFromStringstream(in, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
if (boost::iequals(word, "True")) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::create(true));
|
2009-10-30 17:28:17 +00:00
|
|
|
} else if (boost::iequals(word, "False")) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::create(false));
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-06-15 13:37:41 +00:00
|
|
|
throwJSONError(std::string("Bad boolean value: ") + word, file, line, pos);
|
2010-06-16 10:15:21 +00:00
|
|
|
// above is a throw shortcurt, return empty is never reached
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr());
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
fromStringstreamNull(std::istream& in, const std::string& file,
|
|
|
|
const int line, int& pos)
|
2010-06-15 10:11:48 +00:00
|
|
|
{
|
2013-01-08 20:12:37 -08:00
|
|
|
const std::string word = wordFromStringstream(in, pos);
|
2010-06-15 10:11:48 +00:00
|
|
|
if (boost::iequals(word, "null")) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::create());
|
2010-06-15 10:11:48 +00:00
|
|
|
} else {
|
2010-06-15 13:37:41 +00:00
|
|
|
throwJSONError(std::string("Bad null value: ") + word, file, line, pos);
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr());
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
fromStringstreamString(std::istream& in, const std::string& file, int& line,
|
|
|
|
int& pos)
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
2013-01-08 20:12:37 -08:00
|
|
|
return (Element::create(strFromStringstream(in, file, line, pos)));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
fromStringstreamList(std::istream& in, const std::string& file, int& line,
|
|
|
|
int& pos)
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
2012-12-21 10:11:05 +01:00
|
|
|
int c = 0;
|
2010-06-15 12:38:55 +00:00
|
|
|
ElementPtr list = Element::createList();
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr cur_list_element;
|
2009-10-30 17:28:17 +00:00
|
|
|
|
2013-01-08 20:12:37 -08:00
|
|
|
skipChars(in, WHITESPACE, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
while (c != EOF && c != ']') {
|
2009-11-04 13:41:12 +00:00
|
|
|
if (in.peek() != ']') {
|
2010-06-15 13:02:26 +00:00
|
|
|
cur_list_element = Element::fromJSON(in, file, line, pos);
|
2010-06-15 12:38:55 +00:00
|
|
|
list->add(cur_list_element);
|
2013-01-08 20:12:37 -08:00
|
|
|
skipTo(in, file, line, pos, ",]", WHITESPACE);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
c = in.get();
|
2009-11-04 13:41:12 +00:00
|
|
|
pos++;
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (list);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
fromStringstreamMap(std::istream& in, const std::string& file, int& line,
|
|
|
|
int& pos)
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
2010-06-15 12:38:55 +00:00
|
|
|
ElementPtr map = Element::createMap();
|
2013-01-08 20:12:37 -08:00
|
|
|
skipChars(in, WHITESPACE, line, pos);
|
2012-12-21 10:11:05 +01:00
|
|
|
int c = in.peek();
|
2011-06-29 10:21:47 +02:00
|
|
|
if (c == EOF) {
|
|
|
|
throwJSONError(std::string("Unterminated map, <string> or } expected"), file, line, pos);
|
2011-07-01 15:55:37 +02:00
|
|
|
} else if (c == '}') {
|
2010-02-03 11:38:38 +00:00
|
|
|
// empty map, skip closing curly
|
2013-02-09 14:52:37 -08:00
|
|
|
in.ignore();
|
2010-02-03 11:38:38 +00:00
|
|
|
} else {
|
|
|
|
while (c != EOF && c != '}') {
|
2013-01-08 20:12:37 -08:00
|
|
|
std::string key = strFromStringstream(in, file, line, pos);
|
2010-03-31 23:55:26 +00:00
|
|
|
|
2013-01-08 20:12:37 -08:00
|
|
|
skipTo(in, file, line, pos, ":", WHITESPACE);
|
2010-02-03 11:38:38 +00:00
|
|
|
// skip the :
|
2013-02-09 14:52:37 -08:00
|
|
|
in.ignore();
|
2010-02-03 11:38:38 +00:00
|
|
|
pos++;
|
2010-06-15 12:38:55 +00:00
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr value = Element::fromJSON(in, file, line, pos);
|
2010-06-15 12:38:55 +00:00
|
|
|
map->set(key, value);
|
2012-09-27 16:00:48 +02:00
|
|
|
|
2013-01-08 20:12:37 -08:00
|
|
|
skipTo(in, file, line, pos, ",}", WHITESPACE);
|
2010-02-03 11:38:38 +00:00
|
|
|
c = in.get();
|
|
|
|
pos++;
|
|
|
|
}
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (map);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2013-01-08 20:12:37 -08:00
|
|
|
} // unnamed namespace
|
2009-10-30 17:28:17 +00:00
|
|
|
|
2010-06-27 19:37:00 +00:00
|
|
|
std::string
|
2010-10-15 08:59:24 +00:00
|
|
|
Element::typeToName(Element::types type) {
|
2010-08-16 22:08:14 +00:00
|
|
|
switch (type) {
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::integer:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("integer"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::real:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("real"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::boolean:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("boolean"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::string:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("string"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::list:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("list"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::map:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("map"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::null:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("null"));
|
2010-06-27 19:37:00 +00:00
|
|
|
case Element::any:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("any"));
|
2010-06-27 19:37:00 +00:00
|
|
|
default:
|
2010-08-16 22:08:14 +00:00
|
|
|
return (std::string("unknown"));
|
2010-06-27 19:37:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Element::types
|
|
|
|
Element::nameToType(const std::string& type_name) {
|
|
|
|
if (type_name == "integer") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::integer);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "real") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::real);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "boolean") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::boolean);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "string") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::string);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "list") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::list);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "map") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::map);
|
2011-07-15 11:33:27 +02:00
|
|
|
} else if (type_name == "named_set") {
|
2011-07-08 09:41:27 +02:00
|
|
|
return (Element::map);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "null") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::null);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else if (type_name == "any") {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (Element::any);
|
2010-06-27 19:37:00 +00:00
|
|
|
} else {
|
|
|
|
isc_throw(TypeError, type_name + " is not a valid type name");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-30 17:28:17 +00:00
|
|
|
ElementPtr
|
2010-06-15 13:37:41 +00:00
|
|
|
Element::fromJSON(std::istream& in) throw(JSONError) {
|
2009-11-04 13:41:12 +00:00
|
|
|
int line = 1, pos = 1;
|
2010-08-16 22:08:14 +00:00
|
|
|
return (fromJSON(in, "<istream>", line, pos));
|
2010-02-03 11:38:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-10-15 08:59:24 +00:00
|
|
|
Element::fromJSON(std::istream& in, const std::string& file_name)
|
|
|
|
throw(JSONError)
|
2010-02-03 11:38:38 +00:00
|
|
|
{
|
|
|
|
int line = 1, pos = 1;
|
2010-08-16 22:08:14 +00:00
|
|
|
return (fromJSON(in, file_name, line, pos));
|
2009-11-04 13:41:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
Element::fromJSON(std::istream& in, const std::string& file, int& line,
|
2010-10-15 08:59:24 +00:00
|
|
|
int& pos) throw(JSONError)
|
2009-10-30 17:28:17 +00:00
|
|
|
{
|
2012-12-21 10:11:05 +01:00
|
|
|
int c = 0;
|
2009-10-30 17:28:17 +00:00
|
|
|
ElementPtr element;
|
|
|
|
bool el_read = false;
|
2013-01-08 20:12:37 -08:00
|
|
|
skipChars(in, WHITESPACE, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
while (c != EOF && !el_read) {
|
|
|
|
c = in.get();
|
2009-11-04 13:41:12 +00:00
|
|
|
pos++;
|
2009-10-30 17:28:17 +00:00
|
|
|
switch(c) {
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
case '0':
|
2010-06-27 19:37:00 +00:00
|
|
|
case '-':
|
|
|
|
case '+':
|
2010-06-30 11:49:10 +00:00
|
|
|
case '.':
|
|
|
|
in.putback(c);
|
2013-01-08 20:12:37 -08:00
|
|
|
element = fromStringstreamNumber(in, pos);
|
2010-06-27 19:37:00 +00:00
|
|
|
el_read = true;
|
|
|
|
break;
|
2009-10-30 17:28:17 +00:00
|
|
|
case 't':
|
|
|
|
case 'T':
|
|
|
|
case 'f':
|
|
|
|
case 'F':
|
|
|
|
in.putback(c);
|
2013-01-08 20:12:37 -08:00
|
|
|
element = fromStringstreamBool(in, file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
el_read = true;
|
|
|
|
break;
|
2010-06-15 10:11:48 +00:00
|
|
|
case 'n':
|
2010-06-27 19:37:00 +00:00
|
|
|
case 'N':
|
2010-06-15 10:11:48 +00:00
|
|
|
in.putback(c);
|
2013-01-08 20:12:37 -08:00
|
|
|
element = fromStringstreamNull(in, file, line, pos);
|
2010-06-15 10:11:48 +00:00
|
|
|
el_read = true;
|
|
|
|
break;
|
2009-10-30 17:28:17 +00:00
|
|
|
case '"':
|
|
|
|
in.putback('"');
|
2013-01-08 20:12:37 -08:00
|
|
|
element = fromStringstreamString(in, file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
el_read = true;
|
|
|
|
break;
|
|
|
|
case '[':
|
2013-01-08 20:12:37 -08:00
|
|
|
element = fromStringstreamList(in, file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
el_read = true;
|
|
|
|
break;
|
|
|
|
case '{':
|
2013-01-08 20:12:37 -08:00
|
|
|
element = fromStringstreamMap(in, file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
el_read = true;
|
|
|
|
break;
|
2009-11-04 13:41:12 +00:00
|
|
|
case EOF:
|
|
|
|
break;
|
2009-10-30 17:28:17 +00:00
|
|
|
default:
|
2012-12-21 10:11:05 +01:00
|
|
|
throwJSONError(std::string("error: unexpected character ") + std::string(1, c), file, line, pos);
|
2009-10-30 17:28:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (el_read) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (element);
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-06-15 14:40:31 +00:00
|
|
|
isc_throw(JSONError, "nothing read");
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-03 13:07:00 +00:00
|
|
|
ElementPtr
|
2013-01-08 20:12:37 -08:00
|
|
|
Element::fromJSON(const std::string& in) {
|
2009-11-03 13:07:00 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << in;
|
2012-04-02 15:16:27 +02:00
|
|
|
int line = 1, pos = 1;
|
|
|
|
ElementPtr result(fromJSON(ss, "<string>", line, pos));
|
2013-01-08 20:12:37 -08:00
|
|
|
skipChars(ss, WHITESPACE, line, pos);
|
2012-04-02 15:16:27 +02:00
|
|
|
// ss must now be at end
|
|
|
|
if (ss.peek() != EOF) {
|
|
|
|
throwJSONError("Extra data", "<string>", line, pos);
|
|
|
|
}
|
|
|
|
return result;
|
2009-11-03 13:07:00 +00:00
|
|
|
}
|
2010-01-13 13:14:31 +00:00
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
// to JSON format
|
|
|
|
|
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
IntElement::toJSON(std::ostream& ss) const {
|
2009-12-24 11:30:19 +00:00
|
|
|
ss << intValue();
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
DoubleElement::toJSON(std::ostream& ss) const {
|
2009-12-24 11:30:19 +00:00
|
|
|
ss << doubleValue();
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
BoolElement::toJSON(std::ostream& ss) const {
|
2010-06-27 19:37:00 +00:00
|
|
|
if (boolValue()) {
|
2010-06-15 10:11:48 +00:00
|
|
|
ss << "true";
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-06-15 10:11:48 +00:00
|
|
|
ss << "false";
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
NullElement::toJSON(std::ostream& ss) const {
|
2010-06-15 10:11:48 +00:00
|
|
|
ss << "null";
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
StringElement::toJSON(std::ostream& ss) const {
|
2009-10-30 17:28:17 +00:00
|
|
|
ss << "\"";
|
2012-03-29 17:10:45 +02:00
|
|
|
char c;
|
|
|
|
const std::string& str = stringValue();
|
|
|
|
for (size_t i = 0; i < str.size(); ++i) {
|
|
|
|
c = str[i];
|
|
|
|
// Escape characters as defined in JSON spec
|
2012-03-29 17:56:30 +02:00
|
|
|
// Note that we do not escape forward slash; this
|
|
|
|
// is allowed, but not mandatory.
|
2012-03-30 11:14:57 +02:00
|
|
|
switch (c) {
|
|
|
|
case '"':
|
|
|
|
ss << '\\' << c;
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
ss << '\\' << c;
|
|
|
|
break;
|
|
|
|
case '\b':
|
|
|
|
ss << '\\' << 'b';
|
|
|
|
break;
|
|
|
|
case '\f':
|
|
|
|
ss << '\\' << 'f';
|
|
|
|
break;
|
|
|
|
case '\n':
|
|
|
|
ss << '\\' << 'n';
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
ss << '\\' << 'r';
|
|
|
|
break;
|
|
|
|
case '\t':
|
|
|
|
ss << '\\' << 't';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ss << c;
|
2012-03-29 17:10:45 +02:00
|
|
|
}
|
|
|
|
}
|
2009-10-30 17:28:17 +00:00
|
|
|
ss << "\"";
|
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
ListElement::toJSON(std::ostream& ss) const {
|
2009-10-30 17:28:17 +00:00
|
|
|
ss << "[ ";
|
2010-03-15 08:24:50 +00:00
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
const std::vector<ConstElementPtr>& v = listValue();
|
|
|
|
for (std::vector<ConstElementPtr>::const_iterator it = v.begin();
|
2010-03-15 08:24:50 +00:00
|
|
|
it != v.end(); ++it) {
|
2009-10-30 17:28:17 +00:00
|
|
|
if (it != v.begin()) {
|
|
|
|
ss << ", ";
|
|
|
|
}
|
2010-06-15 10:11:48 +00:00
|
|
|
(*it)->toJSON(ss);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
ss << " ]";
|
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
MapElement::toJSON(std::ostream& ss) const {
|
2010-06-15 10:11:48 +00:00
|
|
|
ss << "{ ";
|
2010-03-15 08:24:50 +00:00
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
const std::map<std::string, ConstElementPtr>& m = mapValue();
|
|
|
|
for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
|
2010-03-15 08:24:50 +00:00
|
|
|
it != m.end(); ++it) {
|
2009-10-30 17:28:17 +00:00
|
|
|
if (it != m.begin()) {
|
|
|
|
ss << ", ";
|
|
|
|
}
|
|
|
|
ss << "\"" << (*it).first << "\": ";
|
2010-02-22 12:42:15 +00:00
|
|
|
if ((*it).second) {
|
2010-06-15 10:11:48 +00:00
|
|
|
(*it).second->toJSON(ss);
|
2010-02-22 12:42:15 +00:00
|
|
|
} else {
|
|
|
|
ss << "None";
|
|
|
|
}
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2010-06-15 10:11:48 +00:00
|
|
|
ss << " }";
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-01-04 12:59:22 +00:00
|
|
|
// throws when one of the types in the path (except the one
|
2009-10-30 17:28:17 +00:00
|
|
|
// we're looking for) is not a MapElement
|
|
|
|
// returns 0 if it could simply not be found
|
|
|
|
// should that also be an exception?
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr
|
|
|
|
MapElement::find(const std::string& id) const {
|
2010-03-15 08:24:50 +00:00
|
|
|
const size_t sep = id.find('/');
|
2009-10-30 17:28:17 +00:00
|
|
|
if (sep == std::string::npos) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (get(id));
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr ce = get(id.substr(0, sep));
|
2009-10-30 17:28:17 +00:00
|
|
|
if (ce) {
|
2009-12-18 17:41:23 +00:00
|
|
|
// ignore trailing slash
|
2010-03-15 08:24:50 +00:00
|
|
|
if (sep + 1 != id.size()) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ce->find(id.substr(sep + 1)));
|
2009-12-18 17:41:23 +00:00
|
|
|
} else {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ce);
|
2009-12-18 17:41:23 +00:00
|
|
|
}
|
2009-10-30 17:28:17 +00:00
|
|
|
} else {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (ElementPtr());
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-03-15 08:24:50 +00:00
|
|
|
Element::fromWire(const std::string& s) {
|
2009-10-30 17:28:17 +00:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << s;
|
2010-06-15 10:11:48 +00:00
|
|
|
int line = 0, pos = 0;
|
2010-08-16 22:08:14 +00:00
|
|
|
return (fromJSON(ss, "<wire>", line, pos));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ElementPtr
|
2010-11-08 16:01:31 +00:00
|
|
|
Element::fromWire(std::stringstream& in, int) {
|
2009-10-30 17:28:17 +00:00
|
|
|
//
|
|
|
|
// Check protocol version
|
|
|
|
//
|
2010-06-15 10:11:48 +00:00
|
|
|
//for (int i = 0 ; i < 4 ; ++i) {
|
|
|
|
// const unsigned char version_byte = get_byte(in);
|
|
|
|
// if (PROTOCOL_VERSION[i] != version_byte) {
|
|
|
|
// throw DecodeError("Protocol version incorrect");
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//length -= 4;
|
|
|
|
int line = 0, pos = 0;
|
2010-08-16 22:08:14 +00:00
|
|
|
return (fromJSON(in, "<wire>", line, pos));
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 12:38:55 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
MapElement::set(const std::string& key, ConstElementPtr value) {
|
2010-06-27 19:37:00 +00:00
|
|
|
m[key] = value;
|
2010-06-15 12:38:55 +00:00
|
|
|
}
|
|
|
|
|
2009-10-30 17:28:17 +00:00
|
|
|
bool
|
2012-10-10 03:51:09 +05:30
|
|
|
MapElement::find(const std::string& id, ConstElementPtr& t) const {
|
2009-10-30 17:28:17 +00:00
|
|
|
try {
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr p = find(id);
|
2009-10-30 17:28:17 +00:00
|
|
|
if (p) {
|
|
|
|
t = p;
|
2010-08-16 22:08:14 +00:00
|
|
|
return (true);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2011-12-12 17:34:26 +00:00
|
|
|
} catch (const TypeError&) {
|
2009-10-30 17:28:17 +00:00
|
|
|
// ignore
|
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2009-10-30 17:28:17 +00:00
|
|
|
}
|
2009-12-18 17:41:23 +00:00
|
|
|
|
2010-02-28 20:00:49 +00:00
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
IntElement::equals(const Element& other) const {
|
|
|
|
return (other.getType() == Element::integer) &&
|
|
|
|
(i == other.intValue());
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
DoubleElement::equals(const Element& other) const {
|
|
|
|
return (other.getType() == Element::real) &&
|
|
|
|
(d == other.doubleValue());
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
BoolElement::equals(const Element& other) const {
|
|
|
|
return (other.getType() == Element::boolean) &&
|
|
|
|
(b == other.boolValue());
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 10:11:48 +00:00
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
NullElement::equals(const Element& other) const {
|
|
|
|
return (other.getType() == Element::null);
|
2010-06-15 10:11:48 +00:00
|
|
|
}
|
|
|
|
|
2010-02-28 20:00:49 +00:00
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
StringElement::equals(const Element& other) const {
|
|
|
|
return (other.getType() == Element::string) &&
|
|
|
|
(s == other.stringValue());
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
ListElement::equals(const Element& other) const {
|
|
|
|
if (other.getType() == Element::list) {
|
2011-12-12 17:09:00 +00:00
|
|
|
const size_t s = size();
|
2010-08-16 23:36:54 +00:00
|
|
|
if (s != other.size()) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
2011-12-12 17:09:00 +00:00
|
|
|
for (size_t i = 0; i < s; ++i) {
|
2010-08-16 23:36:54 +00:00
|
|
|
if (!get(i)->equals(*other.get(i))) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (true);
|
2010-02-28 20:00:49 +00:00
|
|
|
} else {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
MapElement::equals(const Element& other) const {
|
|
|
|
if (other.getType() == Element::map) {
|
|
|
|
const std::map<std::string, ConstElementPtr>& m = mapValue();
|
|
|
|
for (std::map<std::string, ConstElementPtr>::const_iterator it =
|
|
|
|
m.begin();
|
2010-02-28 20:00:49 +00:00
|
|
|
it != m.end() ; ++it) {
|
2010-08-16 23:36:54 +00:00
|
|
|
if (other.contains((*it).first)) {
|
|
|
|
if (!get((*it).first)->equals(*other.get((*it).first))) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// quickly walk through the other map too, to see if there's
|
|
|
|
// anything in there that we don't have. We don't need to
|
|
|
|
// compare those elements; if one of them is missing we
|
|
|
|
// differ (and if it's not missing the loop above has checked
|
|
|
|
// it)
|
2010-08-16 23:36:54 +00:00
|
|
|
std::map<std::string, ConstElementPtr>::const_iterator it;
|
|
|
|
for (it = other.mapValue().begin();
|
|
|
|
it != other.mapValue().end();
|
|
|
|
++it) {
|
2010-02-28 20:00:49 +00:00
|
|
|
if (!contains((*it).first)) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
2010-08-16 22:08:14 +00:00
|
|
|
return (true);
|
2010-02-28 20:00:49 +00:00
|
|
|
} else {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (false);
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-18 17:41:23 +00:00
|
|
|
bool
|
2010-08-16 23:36:54 +00:00
|
|
|
isNull(ConstElementPtr p) {
|
2010-08-16 22:08:14 +00:00
|
|
|
return (!p);
|
2009-12-18 17:41:23 +00:00
|
|
|
}
|
|
|
|
|
2010-02-28 20:00:49 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
removeIdentical(ElementPtr a, ConstElementPtr b) {
|
2010-02-28 20:33:42 +00:00
|
|
|
if (!b) {
|
|
|
|
return;
|
|
|
|
}
|
2010-02-28 20:00:49 +00:00
|
|
|
if (a->getType() != Element::map || b->getType() != Element::map) {
|
2010-03-07 07:06:42 +00:00
|
|
|
isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
2010-02-28 20:33:42 +00:00
|
|
|
|
2011-12-12 18:12:39 +00:00
|
|
|
// As maps do not allow entries with multiple keys, we can either iterate
|
|
|
|
// over a checking for identical entries in b or vice-versa. As elements
|
|
|
|
// are removed from a if a match is found, we choose to iterate over b to
|
|
|
|
// avoid problems with element removal affecting the iterator.
|
|
|
|
const std::map<std::string, ConstElementPtr>& m = b->mapValue();
|
2010-08-16 23:36:54 +00:00
|
|
|
for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
|
2010-02-28 20:00:49 +00:00
|
|
|
it != m.end() ; ++it) {
|
2011-12-12 18:12:39 +00:00
|
|
|
if (a->contains((*it).first)) {
|
2010-08-16 23:36:54 +00:00
|
|
|
if (a->get((*it).first)->equals(*b->get((*it).first))) {
|
2010-02-28 20:00:49 +00:00
|
|
|
a->remove((*it).first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-28 20:33:42 +00:00
|
|
|
}
|
2010-02-28 20:00:49 +00:00
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
ConstElementPtr
|
|
|
|
removeIdentical(ConstElementPtr a, ConstElementPtr b) {
|
|
|
|
ElementPtr result = Element::createMap();
|
|
|
|
|
|
|
|
if (!b) {
|
|
|
|
return (result);
|
|
|
|
}
|
2012-09-27 16:00:48 +02:00
|
|
|
|
2010-08-16 23:36:54 +00:00
|
|
|
if (a->getType() != Element::map || b->getType() != Element::map) {
|
|
|
|
isc_throw(TypeError, "Non-map Elements passed to removeIdentical");
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::map<std::string, ConstElementPtr>& m = a->mapValue();
|
|
|
|
for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
|
|
|
|
it != m.end() ; ++it) {
|
|
|
|
if (!b->contains((*it).first) ||
|
|
|
|
!a->get((*it).first)->equals(*b->get((*it).first))) {
|
|
|
|
result->set((*it).first, (*it).second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2010-02-28 20:33:42 +00:00
|
|
|
void
|
2010-08-16 23:36:54 +00:00
|
|
|
merge(ElementPtr element, ConstElementPtr other) {
|
2010-02-28 20:33:42 +00:00
|
|
|
if (element->getType() != Element::map ||
|
|
|
|
other->getType() != Element::map) {
|
2010-03-07 07:06:42 +00:00
|
|
|
isc_throw(TypeError, "merge arguments not MapElements");
|
2010-02-28 20:33:42 +00:00
|
|
|
}
|
2012-09-27 16:00:48 +02:00
|
|
|
|
2010-10-17 05:10:55 +00:00
|
|
|
const std::map<std::string, ConstElementPtr>& m = other->mapValue();
|
2010-08-16 23:36:54 +00:00
|
|
|
for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
|
2010-02-28 20:33:42 +00:00
|
|
|
it != m.end() ; ++it) {
|
2010-06-16 10:15:21 +00:00
|
|
|
if ((*it).second && (*it).second->getType() != Element::null) {
|
2010-02-28 20:33:42 +00:00
|
|
|
element->set((*it).first, (*it).second);
|
|
|
|
} else if (element->contains((*it).first)) {
|
|
|
|
element->remove((*it).first);
|
|
|
|
}
|
|
|
|
}
|
2010-02-28 20:00:49 +00:00
|
|
|
}
|
2010-02-28 20:33:42 +00:00
|
|
|
|
2010-03-15 08:35:45 +00:00
|
|
|
}
|
|
|
|
}
|