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();
560fromStringstreamNumber(std::istream& in,
const std::string& file,
561 const int line,
int& pos) {
564 const uint32_t start_pos = pos;
566 const std::string number = numberFromStringstream(in, pos);
569 if (number.find_first_of(
".eE") < number.size()) {
572 Element::Position(file, line, start_pos)));
573 }
catch (
const boost::bad_lexical_cast& exception) {
574 throwJSONError(
"Number overflow while trying to cast '" + number +
575 "' to double: " + exception.what(),
576 file, line, start_pos);
582 if (((number.size() > 1) && (number[0] ==
'0')) ||
583 ((number.size() > 2) && (number[0] ==
'-') && (number[1] ==
'0'))) {
584 throwJSONError(
"Illegal leading zeros in '" + number +
"'",
585 file, line, start_pos);
588 if ((number.size() > 1) && (number[0] ==
'+')) {
589 throwJSONError(
"Illegal leading plus in '" + number +
"'",
590 file, line, start_pos);
594 Element::Position(file, line, start_pos)));
595 }
catch (
const boost::bad_lexical_cast& exception64) {
599 Element::Position(file, line, start_pos)));
600 }
catch (overflow_error
const& exception128) {
601 throwJSONError(
"Number overflow while trying to cast '" + number +
602 "' to int64 and subsequently to int128: " +
603 exception64.what() +
", " + exception128.what(),
604 file, line, start_pos);
611fromStringstreamBool(std::istream& in,
const std::string& file,
612 const int line,
int& pos) {
615 const uint32_t start_pos = pos;
617 const std::string word = wordFromStringstream(in, pos);
619 if (word ==
"true") {
622 }
else if (word ==
"false") {
626 throwJSONError(std::string(
"Bad boolean value: ") + word, file,
633fromStringstreamNull(std::istream& in,
const std::string& file,
634 const int line,
int& pos) {
637 const uint32_t start_pos = pos;
639 const std::string word = wordFromStringstream(in, pos);
640 if (word ==
"null") {
643 throwJSONError(std::string(
"Bad null value: ") + word, file,
650fromStringstreamString(std::istream& in,
const std::string& file,
int& line,
654 const uint32_t start_pos = pos;
656 const std::string string_value = strFromStringstream(in, file, line, pos);
662fromStringstreamList(std::istream& in,
const std::string& file,
int& line,
663 int& pos,
unsigned level) {
665 isc_throw(JSONError,
"fromJSON elements nested too deeply");
671 skipChars(in, WHITESPACE, line, pos);
672 while (c != EOF && c !=
']') {
673 if (in.peek() !=
']') {
676 list->add(cur_list_element);
677 c = skipTo(in, file, line, pos,
",]", WHITESPACE);
687fromStringstreamMap(std::istream& in,
const std::string& file,
int& line,
688 int& pos,
unsigned level) {
690 isc_throw(JSONError,
"fromJSON elements nested too deeply");
693 skipChars(in, WHITESPACE, line, pos);
696 throwJSONError(std::string(
"Unterminated map, <string> or } expected"), file, line, pos);
697 }
else if (c ==
'}') {
701 while (c != EOF && c !=
'}') {
702 std::string key = strFromStringstream(in, file, line, pos);
704 skipTo(in, file, line, pos,
":", WHITESPACE);
709 map->set(key, value);
711 c = skipTo(in, file, line, pos,
",}", WHITESPACE);
722 return (std::string(
"integer"));
724 return (std::string(
"bigint"));
726 return (std::string(
"real"));
728 return (std::string(
"boolean"));
730 return (std::string(
"string"));
732 return (std::string(
"list"));
734 return (std::string(
"map"));
736 return (std::string(
"null"));
738 return (std::string(
"any"));
740 return (std::string(
"unknown"));
746 if (type_name ==
"integer") {
748 }
else if (type_name ==
"bigint") {
750 }
else if (type_name ==
"real") {
752 }
else if (type_name ==
"boolean") {
754 }
else if (type_name ==
"string") {
756 }
else if (type_name ==
"list") {
758 }
else if (type_name ==
"map") {
760 }
else if (type_name ==
"named_set") {
762 }
else if (type_name ==
"null") {
764 }
else if (type_name ==
"any") {
774 int line = 1, pos = 1;
775 stringstream filtered;
787 int line = 1, pos = 1;
788 stringstream filtered;
792 return (
fromJSON(preproc ? filtered : in, file_name, line, pos));
797 int& pos,
unsigned level) {
803 bool el_read =
false;
804 skipChars(in, WHITESPACE, line, pos);
805 while (c != EOF && !el_read) {
824 element = fromStringstreamNumber(in, file, line, pos);
831 element = fromStringstreamBool(in, file, line, pos);
837 element = fromStringstreamNull(in, file, line, pos);
843 element = fromStringstreamString(in, file, line, pos);
847 element = fromStringstreamList(in, file, line, pos, level);
851 element = fromStringstreamMap(in, file, line, pos, level);
857 throwJSONError(std::string(
"error: unexpected character ") + std::string(1, c), file, line, pos);
870 std::stringstream ss;
873 int line = 1, pos = 1;
874 stringstream filtered;
879 skipChars(ss, WHITESPACE, line, pos);
881 if (ss.peek() != EOF) {
882 throwJSONError(
"Extra data",
"<string>", line, pos);
892 std::ifstream infile(file_name.c_str(), std::ios::in | std::ios::binary);
893 if (!infile.is_open()) {
894 const char* error = strerror(errno);
899 return (
fromJSON(infile, file_name, preproc));
922 ostringstream val_ss;
925 if (val_ss.str().find_first_of(
'.') == string::npos) {
948 for (
size_t i = 0; i <
str.size(); ++i) {
949 const signed char c =
str[i];
976 if (c < 0x20 || c == 0x7f) {
977 std::ostringstream esc;
982 << (
static_cast<unsigned>(c) & 0xff);
996 "arguments include cycles");
1000 const std::vector<ElementPtr>& v =
listValue();
1002 for (
auto const& it : v) {
1008 it->toJSON(ss, level - 1);
1017 "arguments include cycles");
1022 for (
auto const& it : m) {
1028 ss <<
"\"" << it.first <<
"\": ";
1030 it.second->toJSON(ss, level - 1);
1044 const size_t sep =
id.find(
'/');
1045 if (sep == std::string::npos) {
1051 if (sep + 1 !=
id.
size()) {
1052 return (ce->find(
id.substr(sep + 1)));
1064 std::stringstream ss;
1066 int line = 0, pos = 0;
1067 return (
fromJSON(ss,
"<wire>", line, pos));
1082 int line = 0, pos = 0;
1083 return (
fromJSON(in,
"<wire>", line, pos));
1154 "arguments include cycles");
1157 const size_t s =
size();
1158 if (s != other.
size()) {
1161 for (
size_t i = 0; i < s; ++i) {
1178 int const t(l.at(0)->getType());
1181 if (index.empty()) {
1192 }
else if (t ==
list) {
1197 if (!index.empty()) {
1205 std::sort(l.begin(), l.end(), comparator);
1212 "arguments include cycles");
1218 for (
auto const& kv :
mapValue()) {
1219 auto key = kv.first;
1252 for (
auto const& kv : b->mapValue()) {
1253 auto key = kv.first;
1254 if (a->contains(key)) {
1255 if (a->get(key)->equals(*b->get(key))) {
1274 for (
auto const& kv : a->mapValue()) {
1275 auto key = kv.first;
1276 if (!b->contains(key) ||
1277 !a->get(key)->equals(*b->get(key))) {
1278 result->set(key, kv.second);
1292 for (
auto const& kv : other->mapValue()) {
1293 auto key = kv.first;
1294 auto value = kv.second;
1296 element->set(key, value);
1297 }
else if (element->contains(key)) {
1298 element->remove(key);
1309 "arguments include cycles");
1311 if (element->getType() != other->getType()) {
1319 for (
auto const& right : other->listValue()) {
1322 auto f = hierarchy[idx].find(key);
1323 if (f != hierarchy[idx].end()) {
1325 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1326 for (
auto const& left : element->listValue()) {
1327 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1330 if (f->second.match_(mutable_left, mutable_right)) {
1333 key, idx, level - 1);
1337 new_elements->add(right);
1340 new_elements->add(right);
1344 for (
auto const& right : new_elements->listValue()) {
1345 element->add(right);
1351 for (
auto const& kv : other->mapValue()) {
1352 auto current_key = kv.first;
1353 auto value = boost::const_pointer_cast<Element>(kv.second);
1355 if (element->contains(current_key) &&
1358 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1360 current_key, idx + 1, level - 1);
1362 element->set(current_key, value);
1377 "arguments include cycles");
1379 if (element->getType() != other->getType()) {
1384 for (
auto const& value : other->listValue()) {
1385 ElementPtr mutable_right = boost::const_pointer_cast<Element>(value);
1386 for (uint32_t iter = 0; iter < element->listValue().
size();) {
1387 bool removed =
false;
1390 auto f = hierarchy[idx].find(key);
1391 if (f != hierarchy[idx].end()) {
1392 ElementPtr mutable_left = boost::const_pointer_cast<Element>(element->listValue().at(iter));
1395 if (f->second.match_(mutable_left, mutable_right)) {
1399 if (f->second.no_data_(mutable_right)) {
1400 element->remove(iter);
1404 hierarchy, key, idx, level - 1);
1405 if (mutable_left->empty()) {
1406 element->remove(iter);
1411 }
else if (element->listValue().at(iter)->equals(*value)) {
1412 element->remove(iter);
1427 for (
auto const& kv : other->mapValue()) {
1428 auto current_key = kv.first;
1429 auto value = boost::const_pointer_cast<Element>(kv.second);
1431 if (element->contains(current_key)) {
1432 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1436 current_key, idx + 1, level - 1);
1437 if (mutable_element->empty()) {
1438 element->remove(current_key);
1443 auto f = hierarchy[idx].find(key);
1444 if (f != hierarchy[idx].end()) {
1447 if (f->second.is_key_(current_key)) {
1449 new_elements->set(current_key, mutable_element);
1452 element->remove(current_key);
1458 if (element->size()) {
1459 for (
auto const& kv : new_elements->mapValue()) {
1460 element->set(kv.first, kv.second);
1469extend(
const std::string& container,
const std::string& extension,
1471 std::string key,
size_t idx,
bool alter,
unsigned level) {
1475 "arguments include cycles");
1477 if (element->getType() != other->getType()) {
1482 for (
auto const& right : other->listValue()) {
1485 auto f = hierarchy[idx].find(key);
1486 if (f != hierarchy[idx].end()) {
1487 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1488 for (
auto const& left : element->listValue()) {
1489 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1490 if (container == key) {
1493 if (f->second.match_(mutable_left, mutable_right)) {
1494 extend(container, extension, mutable_left, mutable_right,
1495 hierarchy, key, idx, alter, level - 1);
1504 for (
auto const& kv : other->mapValue()) {
1505 auto current_key = kv.first;
1506 auto value = boost::const_pointer_cast<Element>(kv.second);
1508 if (element->contains(current_key) &&
1511 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1512 if (container == key) {
1515 extend(container, extension, mutable_element, value,
1516 hierarchy, current_key, idx + 1, alter, level - 1);
1517 }
else if (alter && current_key == extension) {
1518 element->set(current_key, value);
1532 auto pos = from->getPosition();
1533 int from_type = from->getType();
1546 for (
auto const& elem : from->listValue()) {
1550 result->add(
copy(elem, level - 1));
1556 for (
auto const& kv : from->mapValue()) {
1557 auto key = kv.first;
1558 auto value = kv.second;
1560 result->set(key, value);
1562 result->set(key,
copy(value, level - 1));
1579 "arguments include cycles");
1582 isc_throw(BadValue,
"isEquivalent got a null pointer");
1585 if (a->getType() != b->getType()) {
1591 return (b->empty());
1594 if (a->size() != b->size()) {
1599 const size_t s = a->size();
1600 std::list<ConstElementPtr> l;
1601 for (
size_t i = 0; i < s; ++i) {
1602 l.push_back(b->get(i));
1606 for (
size_t i = 0; i < s; ++i) {
1610 for (
auto it = l.begin(); it != l.end(); ++it) {
1612 if (isEquivalent0(item, *it, level - 1)) {
1626 isc_throw(Unexpected,
"isEquivalent internal error");
1631 if (a->size() != b->size()) {
1635 for (
auto const& kv : a->mapValue()) {
1638 if (!item || !isEquivalent0(kv.second, item, level - 1)) {
1644 return (a->equals(*b));
1652 return (isEquivalent0(a, b, 100));
1659 unsigned indent,
unsigned step,
unsigned level) {
1662 "arguments include cycles");
1665 isc_throw(BadValue,
"prettyPrint got a null pointer");
1669 if (element->empty()) {
1675 if (!element->get(0)) {
1676 isc_throw(BadValue,
"prettyPrint got a null pointer");
1678 int first_type = element->get(0)->getType();
1679 bool complex =
false;
1683 std::string separator = complex ?
",\n" :
", ";
1686 out <<
"[" << (complex ?
"\n" :
" ");
1689 auto const& l = element->listValue();
1691 for (
auto const& it : l) {
1700 out << std::string(indent + step,
' ');
1703 prettyPrint0(it, out, indent + step, step, level - 1);
1708 out <<
"\n" << std::string(indent,
' ');
1715 if (element->size() == 0) {
1724 auto const& m = element->mapValue();
1726 for (
auto const& it : m) {
1734 out << std::string(indent + step,
' ');
1736 out <<
"\"" << it.first <<
"\": ";
1738 prettyPrint0(it.second, out, indent + step, step, level - 1);
1742 out <<
"\n" << std::string(indent,
' ') <<
"}";
1745 element->toJSON(out);
1753 unsigned indent,
unsigned step) {
1759 std::stringstream ss;
1768 while (std::getline(in, line)) {
1771 if (!line.empty() && line[0] ==
'#') {
1786typedef std::set<ConstElementPtr> Arc;
1795 auto type = element->getType();
1801 if (element->empty()) {
1805 if (arc.count(element) > 0) {
1809 arc.insert(element);
1811 for (
auto const& it : element->listValue()) {
1812 if (IsCircular0(it, arc)) {
1819 for (
auto const& it : element->mapValue()) {
1820 if (IsCircular0(it.second, arc)) {
1831 return (IsCircular0(element, Arc()));
1836 if (max_depth == 0U) {
1844 for (
auto const& i : element->listValue()) {
1846 if (sub == max_depth - 1) {
1849 if (sub + 1 > ret) {
1854 for (
auto const& i : element->mapValue()) {
1856 if (sub == max_depth - 1) {
1859 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.