26#include <boost/lexical_cast.hpp>
35const char*
const WHITESPACE =
" \b\f\n\r\t";
45 std::ostringstream ss;
62 if (type_ ==
list || type_ ==
map) {
64 for (
size_t i = 0; i < s; ++i) {
69 }
else if (type_ ==
map) {
80 child = boost::const_pointer_cast<Element>(
get(key));
84 if (child->getType() !=
list && child->getType() !=
map) {
90 child->removeEmptyContainersRecursively(level - 1);
105 std::stringstream ss;
112 std::stringstream ss;
254throwJSONError(
const std::string& error,
const std::string& file,
int line,
256 std::stringstream ss;
257 ss << error <<
" in " + file +
":" << line <<
":" << pos;
264 return (out << e.
str());
315 return (
create(
static_cast<long long int>(i), pos));
320 return (
create(
static_cast<long long int>(i), pos));
325 return (
create(
static_cast<long long int>(i), pos));
345 return (
create(std::string(s), pos));
364charIn(
const int c,
const char* chars) {
365 const size_t chars_len = std::strlen(chars);
366 for (
size_t i = 0; i < chars_len; ++i) {
375skipChars(std::istream& in,
const char* chars,
int& line,
int& pos) {
377 while (charIn(c, chars) && c != EOF) {
395skipTo(std::istream& in,
const std::string& file,
int& line,
int& pos,
396 const char* chars,
const char* may_skip=
"") {
404 if (charIn(c, may_skip)) {
407 }
else if (charIn(c, chars)) {
408 while (charIn(in.peek(), may_skip)) {
409 if (in.peek() ==
'\n') {
419 throwJSONError(std::string(
"'") + std::string(1, c) +
"' read, one of \"" + chars +
"\" expected", file, line, pos);
422 throwJSONError(std::string(
"EOF read, one of \"") + chars +
"\" expected", file, line, pos);
429strFromStringstream(std::istream& in,
const std::string& file,
430 const int line,
int& pos) {
431 std::stringstream ss;
438 throwJSONError(
"String expected", file, line, pos);
441 while (c != EOF && c !=
'"') {
476 throwJSONError(
"Unsupported unicode escape", file, line, pos);
483 throwJSONError(
"Unsupported unicode escape", file, line, pos - 2);
489 if ((d >=
'0') && (d <=
'9')) {
491 }
else if ((d >=
'A') && (d <=
'F')) {
492 c = (d -
'A' + 10) << 4;
493 }
else if ((d >=
'a') && (d <=
'f')) {
494 c = (d -
'a' + 10) << 4;
496 throwJSONError(
"Not hexadecimal in unicode escape", file, line, pos - 3);
502 if ((d >=
'0') && (d <=
'9')) {
504 }
else if ((d >=
'A') && (d <=
'F')) {
506 }
else if ((d >=
'a') && (d <=
'f')) {
509 throwJSONError(
"Not hexadecimal in unicode escape", file, line, pos - 4);
513 throwJSONError(
"Bad escape", file, line, pos);
524 throwJSONError(
"Unterminated string", file, line, pos);
530wordFromStringstream(std::istream& in,
int& pos) {
531 std::stringstream ss;
532 while (isalpha(in.peek())) {
533 ss << (char) in.get();
535 pos += ss.str().size();
540numberFromStringstream(std::istream& in,
int& pos) {
541 std::stringstream ss;
542 while (isdigit(in.peek()) || in.peek() ==
'+' || in.peek() ==
'-' ||
543 in.peek() ==
'.' || in.peek() ==
'e' || in.peek() ==
'E') {
544 ss << (char) in.get();
546 pos += ss.str().size();
561fromStringstreamNumber(std::istream& in,
const std::string& file,
562 const int line,
int& pos) {
565 const uint32_t start_pos = pos;
567 const std::string number = numberFromStringstream(in, pos);
570 if (number.find_first_of(
".eE") < number.size()) {
573 Element::Position(file, line, start_pos)));
574 }
catch (
const boost::bad_lexical_cast& exception) {
575 throwJSONError(
"Number overflow while trying to cast '" + number +
576 "' to double: " + exception.what(),
577 file, line, start_pos);
584 Element::Position(file, line, start_pos)));
585 }
catch (
const boost::bad_lexical_cast& exception64) {
589 Element::Position(file, line, start_pos)));
590 }
catch (overflow_error
const& exception128) {
591 throwJSONError(
"Number overflow while trying to cast '" + number +
592 "' to int64 and subsequently to int128: " +
593 exception64.what() +
", " + exception128.what(),
594 file, line, start_pos);
601fromStringstreamBool(std::istream& in,
const std::string& file,
602 const int line,
int& pos) {
605 const uint32_t start_pos = pos;
607 const std::string word = wordFromStringstream(in, pos);
609 if (word ==
"true") {
612 }
else if (word ==
"false") {
616 throwJSONError(std::string(
"Bad boolean value: ") + word, file,
623fromStringstreamNull(std::istream& in,
const std::string& file,
624 const int line,
int& pos) {
627 const uint32_t start_pos = pos;
629 const std::string word = wordFromStringstream(in, pos);
630 if (word ==
"null") {
633 throwJSONError(std::string(
"Bad null value: ") + word, file,
640fromStringstreamString(std::istream& in,
const std::string& file,
int& line,
644 const uint32_t start_pos = pos;
646 const std::string string_value = strFromStringstream(in, file, line, pos);
652fromStringstreamList(std::istream& in,
const std::string& file,
int& line,
653 int& pos,
unsigned level) {
655 isc_throw(JSONError,
"fromJSON elements nested too deeply");
661 skipChars(in, WHITESPACE, line, pos);
662 while (c != EOF && c !=
']') {
663 if (in.peek() !=
']') {
666 list->add(cur_list_element);
667 c = skipTo(in, file, line, pos,
",]", WHITESPACE);
677fromStringstreamMap(std::istream& in,
const std::string& file,
int& line,
678 int& pos,
unsigned level) {
680 isc_throw(JSONError,
"fromJSON elements nested too deeply");
683 skipChars(in, WHITESPACE, line, pos);
686 throwJSONError(std::string(
"Unterminated map, <string> or } expected"), file, line, pos);
687 }
else if (c ==
'}') {
691 while (c != EOF && c !=
'}') {
692 std::string key = strFromStringstream(in, file, line, pos);
694 skipTo(in, file, line, pos,
":", WHITESPACE);
699 map->set(key, value);
701 c = skipTo(in, file, line, pos,
",}", WHITESPACE);
712 return (std::string(
"integer"));
714 return (std::string(
"bigint"));
716 return (std::string(
"real"));
718 return (std::string(
"boolean"));
720 return (std::string(
"string"));
722 return (std::string(
"list"));
724 return (std::string(
"map"));
726 return (std::string(
"null"));
728 return (std::string(
"any"));
730 return (std::string(
"unknown"));
736 if (type_name ==
"integer") {
738 }
else if (type_name ==
"bigint") {
740 }
else if (type_name ==
"real") {
742 }
else if (type_name ==
"boolean") {
744 }
else if (type_name ==
"string") {
746 }
else if (type_name ==
"list") {
748 }
else if (type_name ==
"map") {
750 }
else if (type_name ==
"named_set") {
752 }
else if (type_name ==
"null") {
754 }
else if (type_name ==
"any") {
764 int line = 1, pos = 1;
765 stringstream filtered;
777 int line = 1, pos = 1;
778 stringstream filtered;
782 return (
fromJSON(preproc ? filtered : in, file_name, line, pos));
787 int& pos,
unsigned level) {
793 bool el_read =
false;
794 skipChars(in, WHITESPACE, line, pos);
795 while (c != EOF && !el_read) {
814 element = fromStringstreamNumber(in, file, line, pos);
821 element = fromStringstreamBool(in, file, line, pos);
827 element = fromStringstreamNull(in, file, line, pos);
833 element = fromStringstreamString(in, file, line, pos);
837 element = fromStringstreamList(in, file, line, pos, level);
841 element = fromStringstreamMap(in, file, line, pos, level);
847 throwJSONError(std::string(
"error: unexpected character ") + std::string(1, c), file, line, pos);
860 std::stringstream ss;
863 int line = 1, pos = 1;
864 stringstream filtered;
869 skipChars(ss, WHITESPACE, line, pos);
871 if (ss.peek() != EOF) {
872 throwJSONError(
"Extra data",
"<string>", line, pos);
882 std::ifstream infile(file_name.c_str(), std::ios::in | std::ios::binary);
883 if (!infile.is_open()) {
884 const char* error = strerror(errno);
889 return (
fromJSON(infile, file_name, preproc));
912 ostringstream val_ss;
915 if (val_ss.str().find_first_of(
'.') == string::npos) {
938 for (
size_t i = 0; i <
str.size(); ++i) {
939 const signed char c =
str[i];
966 if (c < 0x20 || c == 0x7f) {
967 std::ostringstream esc;
972 << (
static_cast<unsigned>(c) & 0xff);
986 "arguments include cycles");
990 const std::vector<ElementPtr>& v =
listValue();
992 for (
auto const& it : v) {
998 it->toJSON(ss, level - 1);
1007 "arguments include cycles");
1012 for (
auto const& it : m) {
1018 ss <<
"\"" << it.first <<
"\": ";
1020 it.second->toJSON(ss, level - 1);
1034 const size_t sep =
id.find(
'/');
1035 if (sep == std::string::npos) {
1041 if (sep + 1 !=
id.
size()) {
1042 return (ce->find(
id.substr(sep + 1)));
1054 std::stringstream ss;
1056 int line = 0, pos = 0;
1057 return (
fromJSON(ss,
"<wire>", line, pos));
1072 int line = 0, pos = 0;
1073 return (
fromJSON(in,
"<wire>", line, pos));
1144 "arguments include cycles");
1147 const size_t s =
size();
1148 if (s != other.
size()) {
1151 for (
size_t i = 0; i < s; ++i) {
1168 int const t(l.at(0)->getType());
1171 if (index.empty()) {
1182 }
else if (t ==
list) {
1187 if (!index.empty()) {
1195 std::sort(l.begin(), l.end(), comparator);
1202 "arguments include cycles");
1208 for (
auto const& kv :
mapValue()) {
1209 auto key = kv.first;
1242 for (
auto const& kv : b->mapValue()) {
1243 auto key = kv.first;
1244 if (a->contains(key)) {
1245 if (a->get(key)->equals(*b->get(key))) {
1264 for (
auto const& kv : a->mapValue()) {
1265 auto key = kv.first;
1266 if (!b->contains(key) ||
1267 !a->get(key)->equals(*b->get(key))) {
1268 result->set(key, kv.second);
1282 for (
auto const& kv : other->mapValue()) {
1283 auto key = kv.first;
1284 auto value = kv.second;
1286 element->set(key, value);
1287 }
else if (element->contains(key)) {
1288 element->remove(key);
1299 "arguments include cycles");
1301 if (element->getType() != other->getType()) {
1309 for (
auto const& right : other->listValue()) {
1312 auto f = hierarchy[idx].find(key);
1313 if (f != hierarchy[idx].end()) {
1315 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1316 for (
auto const& left : element->listValue()) {
1317 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1320 if (f->second.match_(mutable_left, mutable_right)) {
1323 key, idx, level - 1);
1327 new_elements->add(right);
1330 new_elements->add(right);
1334 for (
auto const& right : new_elements->listValue()) {
1335 element->add(right);
1341 for (
auto const& kv : other->mapValue()) {
1342 auto current_key = kv.first;
1343 auto value = boost::const_pointer_cast<Element>(kv.second);
1345 if (element->contains(current_key) &&
1348 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1350 current_key, idx + 1, level - 1);
1352 element->set(current_key, value);
1367 "arguments include cycles");
1369 if (element->getType() != other->getType()) {
1374 for (
auto const& value : other->listValue()) {
1375 ElementPtr mutable_right = boost::const_pointer_cast<Element>(value);
1376 for (uint32_t iter = 0; iter < element->listValue().
size();) {
1377 bool removed =
false;
1380 auto f = hierarchy[idx].find(key);
1381 if (f != hierarchy[idx].end()) {
1382 ElementPtr mutable_left = boost::const_pointer_cast<Element>(element->listValue().at(iter));
1385 if (f->second.match_(mutable_left, mutable_right)) {
1389 if (f->second.no_data_(mutable_right)) {
1390 element->remove(iter);
1394 hierarchy, key, idx, level - 1);
1395 if (mutable_left->empty()) {
1396 element->remove(iter);
1401 }
else if (element->listValue().at(iter)->equals(*value)) {
1402 element->remove(iter);
1417 for (
auto const& kv : other->mapValue()) {
1418 auto current_key = kv.first;
1419 auto value = boost::const_pointer_cast<Element>(kv.second);
1421 if (element->contains(current_key)) {
1422 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1426 current_key, idx + 1, level - 1);
1427 if (mutable_element->empty()) {
1428 element->remove(current_key);
1433 auto f = hierarchy[idx].find(key);
1434 if (f != hierarchy[idx].end()) {
1437 if (f->second.is_key_(current_key)) {
1439 new_elements->set(current_key, mutable_element);
1442 element->remove(current_key);
1448 if (element->size()) {
1449 for (
auto const& kv : new_elements->mapValue()) {
1450 element->set(kv.first, kv.second);
1459extend(
const std::string& container,
const std::string& extension,
1461 std::string key,
size_t idx,
bool alter,
unsigned level) {
1465 "arguments include cycles");
1467 if (element->getType() != other->getType()) {
1472 for (
auto const& right : other->listValue()) {
1475 auto f = hierarchy[idx].find(key);
1476 if (f != hierarchy[idx].end()) {
1477 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1478 for (
auto const& left : element->listValue()) {
1479 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1480 if (container == key) {
1483 if (f->second.match_(mutable_left, mutable_right)) {
1484 extend(container, extension, mutable_left, mutable_right,
1485 hierarchy, key, idx, alter, level - 1);
1494 for (
auto const& kv : other->mapValue()) {
1495 auto current_key = kv.first;
1496 auto value = boost::const_pointer_cast<Element>(kv.second);
1498 if (element->contains(current_key) &&
1501 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1502 if (container == key) {
1505 extend(container, extension, mutable_element, value,
1506 hierarchy, current_key, idx + 1, alter, level - 1);
1507 }
else if (alter && current_key == extension) {
1508 element->set(current_key, value);
1522 auto pos = from->getPosition();
1523 int from_type = from->getType();
1536 for (
auto const& elem : from->listValue()) {
1540 result->add(
copy(elem, level - 1));
1546 for (
auto const& kv : from->mapValue()) {
1547 auto key = kv.first;
1548 auto value = kv.second;
1550 result->set(key, value);
1552 result->set(key,
copy(value, level - 1));
1569 "arguments include cycles");
1572 isc_throw(BadValue,
"isEquivalent got a null pointer");
1575 if (a->getType() != b->getType()) {
1581 return (b->empty());
1584 if (a->size() != b->size()) {
1589 const size_t s = a->size();
1590 std::list<ConstElementPtr> l;
1591 for (
size_t i = 0; i < s; ++i) {
1592 l.push_back(b->get(i));
1596 for (
size_t i = 0; i < s; ++i) {
1600 for (
auto it = l.begin(); it != l.end(); ++it) {
1602 if (isEquivalent0(item, *it, level - 1)) {
1616 isc_throw(Unexpected,
"isEquivalent internal error");
1621 if (a->size() != b->size()) {
1625 for (
auto const& kv : a->mapValue()) {
1628 if (!item || !isEquivalent0(kv.second, item, level - 1)) {
1634 return (a->equals(*b));
1642 return (isEquivalent0(a, b, 100));
1649 unsigned indent,
unsigned step,
unsigned level) {
1652 "arguments include cycles");
1655 isc_throw(BadValue,
"prettyPrint got a null pointer");
1659 if (element->empty()) {
1665 if (!element->get(0)) {
1666 isc_throw(BadValue,
"prettyPrint got a null pointer");
1668 int first_type = element->get(0)->getType();
1669 bool complex =
false;
1673 std::string separator = complex ?
",\n" :
", ";
1676 out <<
"[" << (complex ?
"\n" :
" ");
1679 auto const& l = element->listValue();
1681 for (
auto const& it : l) {
1690 out << std::string(indent + step,
' ');
1693 prettyPrint0(it, out, indent + step, step, level - 1);
1698 out <<
"\n" << std::string(indent,
' ');
1705 if (element->size() == 0) {
1714 auto const& m = element->mapValue();
1716 for (
auto const& it : m) {
1724 out << std::string(indent + step,
' ');
1726 out <<
"\"" << it.first <<
"\": ";
1728 prettyPrint0(it.second, out, indent + step, step, level - 1);
1732 out <<
"\n" << std::string(indent,
' ') <<
"}";
1735 element->toJSON(out);
1743 unsigned indent,
unsigned step) {
1749 std::stringstream ss;
1758 while (std::getline(in, line)) {
1761 if (!line.empty() && line[0] ==
'#') {
1776typedef std::set<ConstElementPtr> Arc;
1785 auto type = element->getType();
1791 if (element->empty()) {
1795 if (arc.count(element) > 0) {
1799 arc.insert(element);
1801 for (
auto const& it : element->listValue()) {
1802 if (IsCircular0(it, arc)) {
1809 for (
auto const& it : element->mapValue()) {
1810 if (IsCircular0(it.second, arc)) {
1821 return (IsCircular0(element, Arc()));
1826 if (max_depth == 0U) {
1834 for (
auto const& i : element->listValue()) {
1836 if (sub == max_depth - 1) {
1839 if (sub + 1 > ret) {
1844 for (
auto const& i : element->mapValue()) {
1846 if (sub == max_depth - 1) {
1849 if (sub + 1 > ret) {
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a function is called in a prohibited way.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const override
Converts the Element to JSON format and appends it to the given stringstream.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const override
Checks whether the other Element is equal.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const
Test equality.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const
Converts the Element to JSON format and appends it to the given output stream.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const
Converts the Element to JSON format and appends it to the given output stream.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const
Test equality.
The Element class represents a piece of data, used by the command channel and configuration parts.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
virtual bool getValue(int64_t &t) const
Get the integer value.
static std::string typeToName(Element::types type)
Returns the name of the given type as a string.
virtual int64_t intValue() const
Return the integer value.
static constexpr unsigned MAX_NESTING_LEVEL
Maximum nesting level of Element objects.
std::string str() const
Returns a string representing the Element and all its child elements.
virtual std::string stringValue() const
Return the string value.
std::string toWire() const
Returns the wireformat for the Element and all its child elements.
types
The types that an Element can hold.
virtual void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const =0
Converts the Element to JSON format and appends it to the given output stream.
static ElementPtr fromWire(std::stringstream &in, int length)
These function parse the wireformat at the given stringstream (of the given length).
virtual bool setValue(const long long int v)
Set the integer value.
static ElementPtr fromJSONFile(const std::string &file_name, bool preproc=false)
Reads contents of specified file and interprets it as JSON.
virtual bool empty() const
Return true if there are no elements in the list.
virtual void remove(const int i)
Removes the element at the given position.
virtual bool contains(const std::string &name) const
Checks if there is data at the given key.
virtual ConstElementPtr find(const std::string &identifier) const
Recursively finds any data at the given identifier.
virtual size_t size() const
Returns the number of elements in the list.
Element(types t, const Position &pos=ZERO_POSITION())
Constructor.
virtual const std::map< std::string, ConstElementPtr > & mapValue() const
Return the map value.
virtual void add(ElementPtr element)
Adds an ElementPtr to the list.
virtual const std::vector< ElementPtr > & listValue() const
Return the list value.
virtual bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const =0
Test equality.
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
virtual ConstElementPtr get(const int i) const
Returns the ElementPtr at the given index.
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static Element::types nameToType(const std::string &type_name)
Converts the string to the corresponding type Throws a TypeError if the name is unknown.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
virtual void set(const size_t i, ElementPtr element)
Sets the ElementPtr at the given index.
virtual double doubleValue() const
Return the double value.
virtual isc::util::int128_t bigIntValue() const
Return the big integer value.
virtual bool boolValue() const
Return the boolean value.
static void preprocess(std::istream &in, std::stringstream &out)
input text preprocessor.
virtual ElementPtr getNonConst(const int i) const
returns element as non-const pointer.
void removeEmptyContainersRecursively(unsigned level=MAX_NESTING_LEVEL)
Remove all empty maps and lists from this Element and its descendants.
Notes: IntElement type is changed to int64_t.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const
Converts the Element to JSON format and appends it to the given output stream.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const
Test equality.
A standard Data module exception that is thrown if a parse error is encountered when constructing an ...
void sort(std::string const &index=std::string())
Sorts the elements inside the list.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const
Converts the Element to JSON format and appends it to the given output stream.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const
Test equality.
ConstElementPtr find(const std::string &id) const override
Recursively finds any data at the given identifier.
void set(const std::string &key, ConstElementPtr value) override
Sets the ElementPtr at the given key.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const override
Test equality.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const override
Converts the Element to JSON format and appends it to the given output stream.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const
Test equality.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const
Converts the Element to JSON format and appends it to the given output stream.
bool equals(const Element &other, unsigned level=MAX_NESTING_LEVEL) const
Test equality.
void toJSON(std::ostream &ss, unsigned level=MAX_NESTING_LEVEL) const
Converts the Element to JSON format and appends it to the given output stream.
A standard Data module exception that is thrown if a function is called for an Element that has a wro...
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
#define throwTypeError(error)
Add the position to a TypeError message should be used in place of isc_throw(TypeError,...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
bool operator==(const Element &a, const Element &b)
Test equality.
void extend(const std::string &container, const std::string &extension, ElementPtr &element, ElementPtr &other, HierarchyDescriptor &hierarchy, std::string key, size_t idx, bool alter, unsigned level)
Extends data by adding the specified 'extension' elements from 'other' inside the 'container' element...
void removeIdentical(ElementPtr a, ConstElementPtr b)
Remove all values from the first ElementPtr that are equal in the second.
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element. (on the first level).
bool isEquivalent(ConstElementPtr a, ConstElementPtr b)
Compares the data with other using unordered lists.
bool operator<(Element const &a, Element const &b)
Test less than.
bool IsCircular(ConstElementPtr element)
Check if the data is circular.
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
boost::shared_ptr< const Element > ConstElementPtr
void mergeDiffAdd(ElementPtr &element, ElementPtr &other, HierarchyDescriptor &hierarchy, std::string key, size_t idx, unsigned level)
Merges the diff data by adding the missing elements from 'other' to 'element' (recursively).
unsigned getNestDepth(ConstElementPtr element, unsigned max_depth)
Compute the nesting depth.
bool isNull(ConstElementPtr p)
Checks whether the given ElementPtr is a null pointer.
std::ostream & operator<<(std::ostream &out, const Element::Position &pos)
Insert Element::Position as a string into stream.
void mergeDiffDel(ElementPtr &element, ElementPtr &other, HierarchyDescriptor &hierarchy, std::string key, size_t idx, unsigned level)
Merges the diff data by removing the data present in 'other' from 'element' (recursively).
bool operator!=(const Element &a, const Element &b)
Test inequality.
boost::shared_ptr< Element > ElementPtr
std::vector< FunctionMap > HierarchyDescriptor
Hierarchy descriptor of the containers in a specific Element hierarchy tree.
boost::multiprecision::checked_int128_t int128_t
Defines the logger used by the top-level component of kea-lfc.
Represents the position of the data element within a configuration string.
uint32_t pos_
Position within the line.
std::string str() const
Returns the position in the textual format.
uint32_t line_
Line number.
std::string file_
File name.