25#include <boost/lexical_cast.hpp>
32const char*
const WHITESPACE =
" \b\f\n\r\t";
42 std::ostringstream ss;
59 if (type_ ==
list || type_ ==
map) {
61 for (
size_t i = 0; i < s; ++i) {
66 }
else if (type_ ==
map) {
77 child = boost::const_pointer_cast<Element>(
get(key));
81 if (child->getType() !=
list && child->getType() !=
map) {
87 child->removeEmptyContainersRecursively(level - 1);
102 std::stringstream ss;
109 std::stringstream ss;
251throwJSONError(
const std::string& error,
const std::string& file,
int line,
253 std::stringstream ss;
254 ss << error <<
" in " + file +
":" << line <<
":" << pos;
261 return (out << e.
str());
316 return (
create(
static_cast<long long int>(i), pos));
321 return (
create(
static_cast<long long int>(i), pos));
326 return (
create(
static_cast<long long int>(i), pos));
346 return (
create(std::string(s), pos));
365charIn(
const int c,
const char* chars) {
366 const size_t chars_len = std::strlen(chars);
367 for (
size_t i = 0; i < chars_len; ++i) {
376skipChars(std::istream& in,
const char* chars,
int& line,
int& pos) {
378 while (charIn(c, chars) && c != EOF) {
396skipTo(std::istream& in,
const std::string& file,
int& line,
int& pos,
397 const char* chars,
const char* may_skip=
"") {
405 if (charIn(c, may_skip)) {
408 }
else if (charIn(c, chars)) {
409 while (charIn(in.peek(), may_skip)) {
410 if (in.peek() ==
'\n') {
420 throwJSONError(std::string(
"'") + std::string(1, c) +
"' read, one of \"" + chars +
"\" expected", file, line, pos);
423 throwJSONError(std::string(
"EOF read, one of \"") + chars +
"\" expected", file, line, pos);
430strFromStringstream(std::istream& in,
const std::string& file,
431 const int line,
int& pos) {
432 std::stringstream ss;
439 throwJSONError(
"String expected", file, line, pos);
442 while (c != EOF && c !=
'"') {
477 throwJSONError(
"Unsupported unicode escape", file, line, pos);
484 throwJSONError(
"Unsupported unicode escape", file, line, pos - 2);
490 if ((d >=
'0') && (d <=
'9')) {
492 }
else if ((d >=
'A') && (d <=
'F')) {
493 c = (d -
'A' + 10) << 4;
494 }
else if ((d >=
'a') && (d <=
'f')) {
495 c = (d -
'a' + 10) << 4;
497 throwJSONError(
"Not hexadecimal in unicode escape", file, line, pos - 3);
503 if ((d >=
'0') && (d <=
'9')) {
505 }
else if ((d >=
'A') && (d <=
'F')) {
507 }
else if ((d >=
'a') && (d <=
'f')) {
510 throwJSONError(
"Not hexadecimal in unicode escape", file, line, pos - 4);
514 throwJSONError(
"Bad escape", file, line, pos);
525 throwJSONError(
"Unterminated string", file, line, pos);
531wordFromStringstream(std::istream& in,
int& pos) {
532 std::stringstream ss;
533 while (isalpha(in.peek())) {
534 ss << (char) in.get();
536 pos += ss.str().size();
541numberFromStringstream(std::istream& in,
int& pos) {
542 std::stringstream ss;
543 while (isdigit(in.peek()) || in.peek() ==
'+' || in.peek() ==
'-' ||
544 in.peek() ==
'.' || in.peek() ==
'e' || in.peek() ==
'E') {
545 ss << (char) in.get();
547 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.size() > 1) && (number[0] ==
'0') && isdigit(number[1])) ||
571 ((number.size() > 2) && (number[0] ==
'-') &&
572 (number[1] ==
'0') && isdigit(number[2]))) {
573 throwJSONError(
"Illegal leading zeros in '" + number +
"'",
574 file, line, start_pos);
577 if (number.find_first_of(
".eE") < number.size()) {
580 Element::Position(file, line, start_pos)));
581 }
catch (
const boost::bad_lexical_cast& exception) {
582 throwJSONError(
"Number overflow while trying to cast '" + number +
583 "' to double: " + exception.what(),
584 file, line, start_pos);
591 Element::Position(file, line, start_pos)));
592 }
catch (
const boost::bad_lexical_cast& exception64) {
596 Element::Position(file, line, start_pos)));
597 }
catch (overflow_error
const& exception128) {
598 throwJSONError(
"Number overflow while trying to cast '" + number +
599 "' to int64 and subsequently to int128: " +
600 exception64.what() +
", " + exception128.what(),
601 file, line, start_pos);
608fromStringstreamBool(std::istream& in,
const std::string& file,
609 const int line,
int& pos) {
612 const uint32_t start_pos = pos;
614 const std::string word = wordFromStringstream(in, pos);
616 if (word ==
"true") {
619 }
else if (word ==
"false") {
623 throwJSONError(std::string(
"Bad boolean value: ") + word, file,
630fromStringstreamNull(std::istream& in,
const std::string& file,
631 const int line,
int& pos) {
634 const uint32_t start_pos = pos;
636 const std::string word = wordFromStringstream(in, pos);
637 if (word ==
"null") {
640 throwJSONError(std::string(
"Bad null value: ") + word, file,
647fromStringstreamString(std::istream& in,
const std::string& file,
int& line,
651 const uint32_t start_pos = pos;
653 const std::string string_value = strFromStringstream(in, file, line, pos);
659fromStringstreamList(std::istream& in,
const std::string& file,
int& line,
660 int& pos,
unsigned level) {
662 isc_throw(JSONError,
"fromJSON elements nested too deeply");
668 skipChars(in, WHITESPACE, line, pos);
669 while (c != EOF && c !=
']') {
670 if (in.peek() !=
']') {
673 list->add(cur_list_element);
674 c = skipTo(in, file, line, pos,
",]", WHITESPACE);
684fromStringstreamMap(std::istream& in,
const std::string& file,
int& line,
685 int& pos,
unsigned level) {
687 isc_throw(JSONError,
"fromJSON elements nested too deeply");
690 skipChars(in, WHITESPACE, line, pos);
693 throwJSONError(std::string(
"Unterminated map, <string> or } expected"), file, line, pos);
694 }
else if (c ==
'}') {
698 while (c != EOF && c !=
'}') {
699 std::string key = strFromStringstream(in, file, line, pos);
701 skipTo(in, file, line, pos,
":", WHITESPACE);
706 map->set(key, value);
708 c = skipTo(in, file, line, pos,
",}", WHITESPACE);
719 return (std::string(
"integer"));
721 return (std::string(
"bigint"));
723 return (std::string(
"real"));
725 return (std::string(
"boolean"));
727 return (std::string(
"string"));
729 return (std::string(
"list"));
731 return (std::string(
"map"));
733 return (std::string(
"null"));
735 return (std::string(
"any"));
737 return (std::string(
"unknown"));
743 if (type_name ==
"integer") {
745 }
else if (type_name ==
"bigint") {
747 }
else if (type_name ==
"real") {
749 }
else if (type_name ==
"boolean") {
751 }
else if (type_name ==
"string") {
753 }
else if (type_name ==
"list") {
755 }
else if (type_name ==
"map") {
757 }
else if (type_name ==
"named_set") {
759 }
else if (type_name ==
"null") {
761 }
else if (type_name ==
"any") {
771 int line = 1, pos = 1;
772 stringstream filtered;
784 int line = 1, pos = 1;
785 stringstream filtered;
789 return (
fromJSON(preproc ? filtered : in, file_name, line, pos));
794 int& pos,
unsigned level) {
800 bool el_read =
false;
801 skipChars(in, WHITESPACE, line, pos);
802 while (c != EOF && !el_read) {
820 element = fromStringstreamNumber(in, file, line, pos);
827 element = fromStringstreamBool(in, file, line, pos);
833 element = fromStringstreamNull(in, file, line, pos);
839 element = fromStringstreamString(in, file, line, pos);
843 element = fromStringstreamList(in, file, line, pos, level);
847 element = fromStringstreamMap(in, file, line, pos, level);
853 throwJSONError(std::string(
"error: unexpected character ") + std::string(1, c), file, line, pos);
866 std::stringstream ss;
869 int line = 1, pos = 1;
870 stringstream filtered;
875 skipChars(ss, WHITESPACE, line, pos);
877 if (ss.peek() != EOF) {
878 throwJSONError(
"Extra data",
"<string>", line, pos);
888 std::ifstream infile(file_name.c_str(), std::ios::in | std::ios::binary);
889 if (!infile.is_open()) {
890 const char* error = strerror(errno);
895 return (
fromJSON(infile, file_name, preproc));
918 ostringstream val_ss;
921 if (val_ss.str().find_first_of(
".eE") == string::npos) {
944 for (
size_t i = 0; i <
str.size(); ++i) {
945 const signed char c =
str[i];
972 if (c < 0x20 || c == 0x7f) {
973 std::ostringstream esc;
978 << (
static_cast<unsigned>(c) & 0xff);
992 "arguments include cycles");
996 const std::vector<ElementPtr>& v =
listValue();
998 for (
auto const& it : v) {
1004 it->toJSON(ss, level - 1);
1013 "arguments include cycles");
1018 for (
auto const& it : m) {
1024 ss <<
"\"" << it.first <<
"\": ";
1026 it.second->toJSON(ss, level - 1);
1040 const size_t sep =
id.find(
'/');
1041 if (sep == std::string::npos) {
1047 if (sep + 1 !=
id.
size()) {
1048 return (ce->find(
id.substr(sep + 1)));
1060 std::stringstream ss;
1062 int line = 0, pos = 0;
1063 return (
fromJSON(ss,
"<wire>", line, pos));
1078 int line = 0, pos = 0;
1079 return (
fromJSON(in,
"<wire>", line, pos));
1150 "arguments include cycles");
1153 const size_t s =
size();
1154 if (s != other.
size()) {
1157 for (
size_t i = 0; i < s; ++i) {
1174 int const t(l.at(0)->getType());
1177 if (index.empty()) {
1188 }
else if (t ==
list) {
1193 if (!index.empty()) {
1201 std::sort(l.begin(), l.end(), comparator);
1208 "arguments include cycles");
1214 for (
auto const& kv :
mapValue()) {
1215 auto key = kv.first;
1248 for (
auto const& kv : b->mapValue()) {
1249 auto key = kv.first;
1250 if (a->contains(key)) {
1251 if (a->get(key)->equals(*b->get(key))) {
1270 for (
auto const& kv : a->mapValue()) {
1271 auto key = kv.first;
1272 if (!b->contains(key) ||
1273 !a->get(key)->equals(*b->get(key))) {
1274 result->set(key, kv.second);
1288 for (
auto const& kv : other->mapValue()) {
1289 auto key = kv.first;
1290 auto value = kv.second;
1292 element->set(key, value);
1293 }
else if (element->contains(key)) {
1294 element->remove(key);
1305 "arguments include cycles");
1307 if (element->getType() != other->getType()) {
1315 for (
auto const& right : other->listValue()) {
1318 if (hierarchy.size() <= idx) {
1320 << idx <<
" in hierarchy of size "
1321 << hierarchy.size());
1323 auto f = hierarchy[idx].find(key);
1324 if (f != hierarchy[idx].end()) {
1326 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1327 for (
auto const& left : element->listValue()) {
1328 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1331 if (f->second.match_(mutable_left, mutable_right)) {
1334 key, idx, level - 1);
1338 new_elements->add(right);
1341 new_elements->add(right);
1345 for (
auto const& right : new_elements->listValue()) {
1346 element->add(right);
1352 for (
auto const& kv : other->mapValue()) {
1353 auto current_key = kv.first;
1354 auto value = boost::const_pointer_cast<Element>(kv.second);
1356 if (element->contains(current_key) &&
1359 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1361 current_key, idx + 1, level - 1);
1363 element->set(current_key, value);
1378 "arguments include cycles");
1380 if (element->getType() != other->getType()) {
1385 for (
auto const& value : other->listValue()) {
1386 ElementPtr mutable_right = boost::const_pointer_cast<Element>(value);
1387 for (uint32_t iter = 0; iter < element->listValue().
size();) {
1388 bool removed =
false;
1391 if (hierarchy.size() <= idx) {
1393 << idx <<
" in hierarchy of size "
1394 << hierarchy.size());
1396 auto f = hierarchy[idx].find(key);
1397 if (f != hierarchy[idx].end()) {
1398 ElementPtr mutable_left = boost::const_pointer_cast<Element>(element->listValue().at(iter));
1401 if (f->second.match_(mutable_left, mutable_right)) {
1405 if (f->second.no_data_(mutable_right)) {
1406 element->remove(iter);
1410 hierarchy, key, idx, level - 1);
1411 if (mutable_left->empty()) {
1412 element->remove(iter);
1417 }
else if (element->listValue().at(iter)->equals(*value)) {
1418 element->remove(iter);
1433 for (
auto const& kv : other->mapValue()) {
1434 auto current_key = kv.first;
1435 auto value = boost::const_pointer_cast<Element>(kv.second);
1437 if (element->contains(current_key)) {
1438 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1442 current_key, idx + 1, level - 1);
1443 if (mutable_element->empty()) {
1444 element->remove(current_key);
1449 if (hierarchy.size() <= idx) {
1451 << idx <<
" in hierarchy of size "
1452 << hierarchy.size());
1454 auto f = hierarchy[idx].find(key);
1455 if (f != hierarchy[idx].end()) {
1458 if (f->second.is_key_(current_key)) {
1460 new_elements->set(current_key, mutable_element);
1463 element->remove(current_key);
1469 if (element->size()) {
1470 for (
auto const& kv : new_elements->mapValue()) {
1471 element->set(kv.first, kv.second);
1480extend(
const std::string& container,
const std::string& extension,
1482 std::string key,
size_t idx,
bool alter,
unsigned level) {
1486 "arguments include cycles");
1488 if (element->getType() != other->getType()) {
1493 for (
auto const& right : other->listValue()) {
1496 if (hierarchy.size() <= idx) {
1498 << idx <<
" in hierarchy of size "
1499 << hierarchy.size());
1501 auto f = hierarchy[idx].find(key);
1502 if (f != hierarchy[idx].end()) {
1503 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1504 for (
auto const& left : element->listValue()) {
1505 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1506 if (container == key) {
1509 if (f->second.match_(mutable_left, mutable_right)) {
1510 extend(container, extension, mutable_left, mutable_right,
1511 hierarchy, key, idx, alter, level - 1);
1520 for (
auto const& kv : other->mapValue()) {
1521 auto current_key = kv.first;
1522 auto value = boost::const_pointer_cast<Element>(kv.second);
1524 if (element->contains(current_key) &&
1527 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1528 if (container == key) {
1531 extend(container, extension, mutable_element, value,
1532 hierarchy, current_key, idx + 1, alter, level - 1);
1533 }
else if (alter && current_key == extension) {
1534 element->set(current_key, value);
1548 auto pos = from->getPosition();
1564 for (
auto const& elem : from->listValue()) {
1568 result->add(
copy(elem, level - 1));
1574 for (
auto const& kv : from->mapValue()) {
1575 auto key = kv.first;
1576 auto value = kv.second;
1578 result->set(key, value);
1580 result->set(key,
copy(value, level - 1));
1597 "arguments include cycles");
1600 isc_throw(BadValue,
"isEquivalent got a null pointer");
1603 if (a->getType() != b->getType()) {
1609 return (b->empty());
1612 if (a->size() != b->size()) {
1617 const size_t s = a->size();
1618 std::list<ConstElementPtr> l;
1619 for (
size_t i = 0; i < s; ++i) {
1620 l.push_back(b->get(i));
1624 for (
size_t i = 0; i < s; ++i) {
1628 for (
auto it = l.begin(); it != l.end(); ++it) {
1630 if (isEquivalent0(item, *it, level - 1)) {
1644 isc_throw(Unexpected,
"isEquivalent internal error");
1649 if (a->size() != b->size()) {
1653 for (
auto const& kv : a->mapValue()) {
1656 if (!item || !isEquivalent0(kv.second, item, level - 1)) {
1662 return (a->equals(*b));
1670 return (isEquivalent0(a, b, 100));
1677 unsigned indent,
unsigned step,
unsigned level) {
1680 "arguments include cycles");
1683 isc_throw(BadValue,
"prettyPrint got a null pointer");
1687 if (element->empty()) {
1693 if (!element->get(0)) {
1694 isc_throw(BadValue,
"prettyPrint got a null pointer");
1697 bool complex =
false;
1701 std::string separator = complex ?
",\n" :
", ";
1704 out <<
"[" << (complex ?
"\n" :
" ");
1707 auto const& l = element->listValue();
1709 for (
auto const& it : l) {
1718 out << std::string(indent + step,
' ');
1721 prettyPrint0(it, out, indent + step, step, level - 1);
1726 out <<
"\n" << std::string(indent,
' ');
1733 if (element->size() == 0) {
1742 auto const& m = element->mapValue();
1744 for (
auto const& it : m) {
1752 out << std::string(indent + step,
' ');
1754 out <<
"\"" << it.first <<
"\": ";
1756 prettyPrint0(it.second, out, indent + step, step, level - 1);
1760 out <<
"\n" << std::string(indent,
' ') <<
"}";
1763 element->toJSON(out);
1771 unsigned indent,
unsigned step) {
1777 std::stringstream ss;
1786 while (std::getline(in, line)) {
1789 if (!line.empty() && line[0] ==
'#') {
1804typedef std::set<ConstElementPtr> Arc;
1813 auto type = element->getType();
1819 if (element->empty()) {
1823 if (arc.count(element) > 0) {
1827 arc.insert(element);
1829 for (
auto const& it : element->listValue()) {
1830 if (IsCircular0(it, arc)) {
1837 for (
auto const& it : element->mapValue()) {
1838 if (IsCircular0(it.second, arc)) {
1849 return (IsCircular0(element, Arc()));
1854 if (max_depth == 0U) {
1862 for (
auto const& i : element->listValue()) {
1864 if (sub == max_depth - 1) {
1867 if (sub + 1 > ret) {
1872 for (
auto const& i : element->mapValue()) {
1874 if (sub == max_depth - 1) {
1877 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.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
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.