24 #include <boost/lexical_cast.hpp>
31 const char*
const WHITESPACE =
" \b\f\n\r\t";
38 Element::Position::str()
const {
39 std::ostringstream ss;
40 ss << file_ <<
":" << line_ <<
":" <<
pos_;
51 Element::str()
const {
58 Element::toWire()
const {
65 Element::toWire(std::ostream& ss)
const {
70 Element::getValue(int64_t&)
const {
75 Element::getValue(
double&)
const {
80 Element::getValue(
bool&)
const {
85 Element::getValue(std::string&)
const {
90 Element::getValue(std::vector<ElementPtr>&)
const {
95 Element::getValue(std::map<std::string, ConstElementPtr>&)
const {
100 Element::setValue(
const long long int) {
110 Element::setValue(
const double) {
115 Element::setValue(
const bool) {
120 Element::setValue(
const std::string&) {
125 Element::setValue(
const std::vector<ElementPtr>&) {
130 Element::setValue(
const std::map<std::string, ConstElementPtr>&) {
135 Element::get(
const int)
const {
140 Element::getNonConst(
const int)
const {
155 Element::remove(
const int) {
160 Element::size()
const {
165 Element::empty()
const {
170 Element::get(
const std::string&)
const {
180 Element::remove(
const std::string&) {
185 Element::contains(
const std::string&)
const {
190 Element::find(
const std::string&)
const {
201 throwJSONError(
const std::string&
error,
const std::string& file,
int line,
203 std::stringstream ss;
204 ss <<
error <<
" in " + file +
":" << line <<
":" << pos;
211 return (out << e.
str());
229 case Element::integer:
233 case Element::boolean:
235 case Element::string:
251 Element::create(
const long long int i,
const Position& pos) {
261 Element::create(
const int i,
const Position& pos) {
262 return (create(
static_cast<long long int>(i), pos));
266 Element::create(
const long int i,
const Position& pos) {
267 return (create(
static_cast<long long int>(i), pos));
271 Element::create(
const uint32_t i,
const Position& pos) {
272 return (create(
static_cast<long long int>(i), pos));
276 Element::create(
const double d,
const Position& pos) {
281 Element::create(
const bool b,
const Position& pos) {
286 Element::create(
const std::string& s,
const Position& pos) {
291 Element::create(
const char *s,
const Position& pos) {
292 return (create(std::string(s), pos));
311 charIn(
const int c,
const char* chars) {
312 const size_t chars_len = std::strlen(chars);
313 for (
size_t i = 0; i < chars_len; ++i) {
322 skipChars(std::istream& in,
const char* chars,
int& line,
int& pos) {
324 while (charIn(c, chars) && c != EOF) {
342 skipTo(std::istream& in,
const std::string& file,
int& line,
int& pos,
343 const char* chars,
const char* may_skip=
"") {
351 if (charIn(c, may_skip)) {
354 }
else if (charIn(c, chars)) {
355 while (charIn(in.peek(), may_skip)) {
356 if (in.peek() ==
'\n') {
366 throwJSONError(std::string(
"'") + std::string(1, c) +
"' read, one of \"" + chars +
"\" expected", file, line, pos);
369 throwJSONError(std::string(
"EOF read, one of \"") + chars +
"\" expected", file, line, pos);
376 strFromStringstream(std::istream& in,
const std::string& file,
377 const int line,
int& pos) {
378 std::stringstream ss;
385 throwJSONError(
"String expected", file, line, pos);
388 while (c != EOF && c !=
'"') {
423 throwJSONError(
"Unsupported unicode escape", file, line, pos);
430 throwJSONError(
"Unsupported unicode escape", file, line, pos - 2);
436 if ((d >=
'0') && (d <=
'9')) {
438 }
else if ((d >=
'A') && (d <=
'F')) {
439 c = (d -
'A' + 10) << 4;
440 }
else if ((d >=
'a') && (d <=
'f')) {
441 c = (d -
'a' + 10) << 4;
443 throwJSONError(
"Not hexadecimal in unicode escape", file, line, pos - 3);
449 if ((d >=
'0') && (d <=
'9')) {
451 }
else if ((d >=
'A') && (d <=
'F')) {
453 }
else if ((d >=
'a') && (d <=
'f')) {
456 throwJSONError(
"Not hexadecimal in unicode escape", file, line, pos - 4);
460 throwJSONError(
"Bad escape", file, line, pos);
471 throwJSONError(
"Unterminated string", file, line, pos);
477 wordFromStringstream(std::istream& in,
int& pos) {
478 std::stringstream ss;
479 while (isalpha(in.peek())) {
480 ss << (char) in.get();
482 pos += ss.str().size();
487 numberFromStringstream(std::istream& in,
int& pos) {
488 std::stringstream ss;
489 while (isdigit(in.peek()) || in.peek() ==
'+' || in.peek() ==
'-' ||
490 in.peek() ==
'.' || in.peek() ==
'e' || in.peek() ==
'E') {
491 ss << (char) in.get();
493 pos += ss.str().size();
502 fromStringstreamNumber(std::istream& in,
const std::string& file,
503 const int line,
int& pos) {
506 const uint32_t start_pos = pos;
508 const std::string number = numberFromStringstream(in, pos);
510 if (number.find_first_of(
".eE") < number.size()) {
512 return (Element::create(boost::lexical_cast<double>(number),
513 Element::Position(file, line, start_pos)));
514 }
catch (
const boost::bad_lexical_cast&) {
515 throwJSONError(std::string(
"Number overflow: ") + number,
516 file, line, start_pos);
520 return (Element::create(boost::lexical_cast<int64_t>(number),
521 Element::Position(file, line, start_pos)));
522 }
catch (
const boost::bad_lexical_cast&) {
523 throwJSONError(std::string(
"Number overflow: ") + number, file,
531 fromStringstreamBool(std::istream& in,
const std::string& file,
532 const int line,
int& pos) {
535 const uint32_t start_pos = pos;
537 const std::string word = wordFromStringstream(in, pos);
539 if (word ==
"true") {
540 return (Element::create(
true, Element::Position(file, line,
542 }
else if (word ==
"false") {
543 return (Element::create(
false, Element::Position(file, line,
546 throwJSONError(std::string(
"Bad boolean value: ") + word, file,
553 fromStringstreamNull(std::istream& in,
const std::string& file,
554 const int line,
int& pos) {
557 const uint32_t start_pos = pos;
559 const std::string word = wordFromStringstream(in, pos);
560 if (word ==
"null") {
561 return (Element::create(Element::Position(file, line, start_pos)));
563 throwJSONError(std::string(
"Bad null value: ") + word, file,
570 fromStringstreamString(std::istream& in,
const std::string& file,
int& line,
574 const uint32_t start_pos = pos;
576 const std::string string_value = strFromStringstream(in, file, line, pos);
577 return (Element::create(string_value, Element::Position(file, line,
582 fromStringstreamList(std::istream& in,
const std::string& file,
int& line,
585 ElementPtr list = Element::createList(Element::Position(file, line, pos));
588 skipChars(in, WHITESPACE, line, pos);
589 while (c != EOF && c !=
']') {
590 if (in.peek() !=
']') {
591 cur_list_element = Element::fromJSON(in, file, line, pos);
592 list->add(cur_list_element);
593 c = skipTo(in, file, line, pos,
",]", WHITESPACE);
603 fromStringstreamMap(std::istream& in,
const std::string& file,
int& line,
605 ElementPtr map = Element::createMap(Element::Position(file, line, pos));
606 skipChars(in, WHITESPACE, line, pos);
609 throwJSONError(std::string(
"Unterminated map, <string> or } expected"), file, line, pos);
610 }
else if (c ==
'}') {
614 while (c != EOF && c !=
'}') {
615 std::string key = strFromStringstream(in, file, line, pos);
617 skipTo(in, file, line, pos,
":", WHITESPACE);
621 map->set(key, value);
623 c = skipTo(in, file, line, pos,
",}", WHITESPACE);
633 case Element::integer:
634 return (std::string(
"integer"));
635 case Element::bigint:
636 return (std::string(
"bigint"));
638 return (std::string(
"real"));
639 case Element::boolean:
640 return (std::string(
"boolean"));
641 case Element::string:
642 return (std::string(
"string"));
644 return (std::string(
"list"));
646 return (std::string(
"map"));
648 return (std::string(
"null"));
650 return (std::string(
"any"));
652 return (std::string(
"unknown"));
657 Element::nameToType(
const std::string& type_name) {
658 if (type_name ==
"integer") {
659 return (Element::integer);
660 }
else if (type_name ==
"bigint") {
661 return (Element::bigint);
662 }
else if (type_name ==
"real") {
663 return (Element::real);
664 }
else if (type_name ==
"boolean") {
665 return (Element::boolean);
666 }
else if (type_name ==
"string") {
667 return (Element::string);
668 }
else if (type_name ==
"list") {
669 return (Element::list);
670 }
else if (type_name ==
"map") {
671 return (Element::map);
672 }
else if (type_name ==
"named_set") {
673 return (Element::map);
674 }
else if (type_name ==
"null") {
675 return (Element::null);
676 }
else if (type_name ==
"any") {
677 return (Element::any);
684 Element::fromJSON(std::istream& in,
bool preproc) {
686 int line = 1, pos = 1;
687 stringstream filtered;
689 preprocess(in, filtered);
692 ElementPtr value = fromJSON(preproc ? filtered : in,
"<istream>", line, pos);
698 Element::fromJSON(std::istream& in,
const std::string& file_name,
bool preproc) {
699 int line = 1, pos = 1;
700 stringstream filtered;
702 preprocess(in, filtered);
704 return (fromJSON(preproc ? filtered : in, file_name, line, pos));
708 Element::fromJSON(std::istream& in,
const std::string& file,
int& line,
712 bool el_read =
false;
713 skipChars(in, WHITESPACE, line, pos);
714 while (c != EOF && !el_read) {
733 element = fromStringstreamNumber(in, file, line, pos);
740 element = fromStringstreamBool(in, file, line, pos);
746 element = fromStringstreamNull(in, file, line, pos);
752 element = fromStringstreamString(in, file, line, pos);
756 element = fromStringstreamList(in, file, line, pos);
760 element = fromStringstreamMap(in, file, line, pos);
766 throwJSONError(std::string(
"error: unexpected character ") + std::string(1, c), file, line, pos);
778 Element::fromJSON(
const std::string& in,
bool preproc) {
779 std::stringstream ss;
782 int line = 1, pos = 1;
783 stringstream filtered;
785 preprocess(ss, filtered);
787 ElementPtr result(fromJSON(preproc ? filtered : ss,
"<string>", line, pos));
788 skipChars(ss, WHITESPACE, line, pos);
790 if (ss.peek() != EOF) {
791 throwJSONError(
"Extra data",
"<string>", line, pos);
797 Element::fromJSONFile(
const std::string& file_name,
bool preproc) {
801 std::ifstream infile(file_name.c_str(), std::ios::in | std::ios::binary);
802 if (!infile.is_open()) {
803 const char*
error = strerror(errno);
808 return (fromJSON(infile, file_name, preproc));
814 IntElement::toJSON(std::ostream& ss)
const {
819 BigIntElement::toJSON(std::ostream& ss)
const {
824 DoubleElement::toJSON(std::ostream& ss)
const {
831 ostringstream val_ss;
832 val_ss << doubleValue();
834 if (val_ss.str().find_first_of(
'.') == string::npos) {
840 BoolElement::toJSON(std::ostream& ss)
const {
849 NullElement::toJSON(std::ostream& ss)
const {
854 StringElement::toJSON(std::ostream& ss)
const {
856 const std::string& str = stringValue();
857 for (
size_t i = 0; i < str.size(); ++i) {
858 const char c = str[i];
885 if (((c >= 0) && (c < 0x20)) || (c < 0) || (c >= 0x7f)) {
886 std::ostringstream esc;
891 << (
static_cast<unsigned>(c) & 0xff);
902 ListElement::toJSON(std::ostream& ss)
const {
905 const std::vector<ElementPtr>& v = listValue();
906 for (
auto it = v.begin(); it != v.end(); ++it) {
907 if (it != v.begin()) {
916 MapElement::toJSON(std::ostream& ss)
const {
919 const std::map<std::string, ConstElementPtr>& m = mapValue();
920 for (
auto it = m.begin(); it != m.end(); ++it) {
921 if (it != m.begin()) {
924 ss <<
"\"" << (*it).first <<
"\": ";
926 (*it).second->toJSON(ss);
939 MapElement::find(
const std::string&
id)
const {
940 const size_t sep =
id.find(
'/');
941 if (sep == std::string::npos) {
947 if (sep + 1 !=
id.size()) {
948 return (ce->find(
id.substr(sep + 1)));
959 Element::fromWire(
const std::string& s) {
960 std::stringstream ss;
962 int line = 0, pos = 0;
963 return (fromJSON(ss,
"<wire>", line, pos));
967 Element::fromWire(std::stringstream& in,
int) {
978 int line = 0, pos = 0;
979 return (fromJSON(in,
"<wire>", line, pos));
1008 return (other.
getType() == Element::integer && i == other.
intValue()) ||
1013 BigIntElement::equals(
const Element& other)
const {
1024 DoubleElement::equals(
const Element& other)
const {
1025 return (other.
getType() == Element::real) &&
1031 return (other.
getType() == Element::boolean) &&
1037 return (other.
getType() == Element::null);
1041 StringElement::equals(
const Element& other)
const {
1042 return (other.
getType() == Element::string) &&
1048 if (other.
getType() == Element::list) {
1049 const size_t s = size();
1050 if (s != other.
size()) {
1053 for (
size_t i = 0; i < s; ++i) {
1054 if (!get(i)->equals(*other.
get(i))) {
1065 ListElement::sort(std::string
const& index ) {
1070 int const t(l.at(0)->getType());
1073 if (index.empty()) {
1084 }
else if (t == list) {
1089 if (!index.empty()) {
1097 std::sort(l.begin(), l.end(), comparator);
1102 if (other.
getType() == Element::map) {
1103 if (size() != other.
size()) {
1106 for (
auto kv : mapValue()) {
1107 auto key = kv.first;
1109 if (!get(key)->equals(*other.
get(key))) {
1132 if (a->getType() != Element::map || b->getType() != Element::map) {
1140 for (
auto kv : b->mapValue()) {
1141 auto key = kv.first;
1142 if (a->contains(key)) {
1143 if (a->get(key)->equals(*b->get(key))) {
1158 if (a->getType() != Element::map || b->getType() != Element::map) {
1162 for (
auto kv : a->mapValue()) {
1163 auto key = kv.first;
1164 if (!b->contains(key) ||
1165 !a->get(key)->equals(*b->get(key))) {
1166 result->set(key, kv.second);
1175 if (element->getType() != Element::map ||
1176 other->getType() != Element::map) {
1180 for (
auto kv : other->mapValue()) {
1181 auto key = kv.first;
1182 auto value = kv.second;
1183 if (value && value->getType() != Element::null) {
1184 element->set(key, value);
1185 }
else if (element->contains(key)) {
1186 element->remove(key);
1194 if (element->getType() != other->getType()) {
1198 if (element->getType() == Element::list) {
1201 ElementPtr new_elements = Element::createList();
1202 for (
auto& right : other->listValue()) {
1205 auto f = hierarchy[idx].find(key);
1206 if (f != hierarchy[idx].end()) {
1208 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1209 for (
auto& left : element->listValue()) {
1210 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1213 if (f->second.match_(mutable_left, mutable_right)) {
1215 mergeDiffAdd(mutable_left, mutable_right, hierarchy, key, idx);
1219 new_elements->add(right);
1222 new_elements->add(right);
1226 for (
auto& right : new_elements->listValue()) {
1227 element->add(right);
1232 if (element->getType() == Element::map) {
1233 for (
auto kv : other->mapValue()) {
1234 auto current_key = kv.first;
1235 auto value = boost::const_pointer_cast<Element>(kv.second);
1236 if (value && value->getType() != Element::null) {
1237 if (element->contains(current_key) &&
1238 (value->getType() == Element::map ||
1239 value->getType() == Element::list)) {
1240 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1241 mergeDiffAdd(mutable_element, value, hierarchy, current_key, idx + 1);
1243 element->set(current_key, value);
1255 if (element->getType() != other->getType()) {
1259 if (element->getType() == Element::list) {
1260 for (
auto const& value : other->listValue()) {
1261 ElementPtr mutable_right = boost::const_pointer_cast<Element>(value);
1262 for (uint32_t iter = 0; iter < element->listValue().size();) {
1263 bool removed =
false;
1266 auto f = hierarchy[idx].find(key);
1267 if (f != hierarchy[idx].end()) {
1268 ElementPtr mutable_left = boost::const_pointer_cast<Element>(element->listValue().at(iter));
1271 if (f->second.match_(mutable_left, mutable_right)) {
1275 if (f->second.no_data_(mutable_right)) {
1276 element->remove(iter);
1279 mergeDiffDel(mutable_left, mutable_right, hierarchy, key, idx);
1280 if (mutable_left->empty()) {
1281 element->remove(iter);
1286 }
else if (element->listValue().at(iter)->equals(*value)) {
1287 element->remove(iter);
1298 if (element->getType() == Element::map) {
1301 ElementPtr new_elements = Element::createMap();
1302 for (
auto kv : other->mapValue()) {
1303 auto current_key = kv.first;
1304 auto value = boost::const_pointer_cast<Element>(kv.second);
1305 if (value && value->getType() != Element::null) {
1306 if (element->contains(current_key)) {
1307 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1308 if (mutable_element->getType() == Element::map ||
1309 mutable_element->getType() == Element::list) {
1310 mergeDiffDel(mutable_element, value, hierarchy, current_key, idx + 1);
1311 if (mutable_element->empty()) {
1312 element->remove(current_key);
1317 auto f = hierarchy[idx].find(key);
1318 if (f != hierarchy[idx].end()) {
1321 if (f->second.is_key_(current_key)) {
1323 new_elements->set(current_key, mutable_element);
1326 element->remove(current_key);
1332 if (element->size()) {
1333 for (
auto kv : new_elements->mapValue()) {
1334 element->set(kv.first, kv.second);
1343 extend(
const std::string& container,
const std::string& extension,
1345 std::string key,
size_t idx,
bool alter) {
1346 if (element->getType() != other->getType()) {
1350 if (element->getType() == Element::list) {
1351 for (
auto& right : other->listValue()) {
1354 auto f = hierarchy[idx].find(key);
1355 if (f != hierarchy[idx].end()) {
1356 ElementPtr mutable_right = boost::const_pointer_cast<Element>(right);
1357 for (
auto& left : element->listValue()) {
1358 ElementPtr mutable_left = boost::const_pointer_cast<Element>(left);
1359 if (container == key) {
1362 if (f->second.match_(mutable_left, mutable_right)) {
1363 extend(container, extension, mutable_left, mutable_right,
1364 hierarchy, key, idx, alter);
1372 if (element->getType() == Element::map) {
1373 for (
auto kv : other->mapValue()) {
1374 auto current_key = kv.first;
1375 auto value = boost::const_pointer_cast<Element>(kv.second);
1376 if (value && value->getType() != Element::null) {
1377 if (element->contains(current_key) &&
1378 (value->getType() == Element::map ||
1379 value->getType() == Element::list)) {
1380 ElementPtr mutable_element = boost::const_pointer_cast<Element>(element->get(current_key));
1381 if (container == key) {
1384 extend(container, extension, mutable_element, value, hierarchy, current_key, idx + 1, alter);
1385 }
else if (alter && current_key == extension) {
1386 element->set(current_key, value);
1399 int from_type = from->getType();
1400 if (from_type == Element::integer) {
1402 }
else if (from_type == Element::real) {
1404 }
else if (from_type == Element::boolean) {
1406 }
else if (from_type == Element::null) {
1408 }
else if (from_type == Element::string) {
1410 }
else if (from_type == Element::list) {
1412 for (
auto elem : from->listValue()) {
1416 result->add(
copy(elem, level - 1));
1420 }
else if (from_type == Element::map) {
1422 for (
auto kv : from->mapValue()) {
1423 auto key = kv.first;
1424 auto value = kv.second;
1426 result->set(key, value);
1428 result->set(key,
copy(value, level - 1));
1445 "arguments include cycles");
1448 isc_throw(BadValue,
"isEquivalent got a null pointer");
1451 if (a->getType() != b->getType()) {
1454 if (a->getType() == Element::list) {
1457 return (b->empty());
1460 if (a->size() != b->size()) {
1465 const size_t s = a->size();
1466 std::list<ConstElementPtr> l;
1467 for (
size_t i = 0; i < s; ++i) {
1468 l.push_back(b->get(i));
1472 for (
size_t i = 0; i < s; ++i) {
1476 for (
auto it = l.begin(); it != l.end(); ++it) {
1478 if (isEquivalent0(item, *it, level - 1)) {
1492 isc_throw(Unexpected,
"isEquivalent internal error");
1495 }
else if (a->getType() == Element::map) {
1497 if (a->size() != b->size()) {
1501 for (
auto kv : a->mapValue()) {
1504 if (!item || !isEquivalent0(kv.second, item, level - 1)) {
1510 return (a->equals(*b));
1518 return (isEquivalent0(a, b, 100));
1523 unsigned indent,
unsigned step) {
1527 if (element->getType() == Element::list) {
1529 if (element->empty()) {
1535 if (!element->get(0)) {
1538 int first_type = element->get(0)->getType();
1539 bool complex =
false;
1540 if ((first_type == Element::list) || (first_type == Element::map)) {
1543 std::string separator = complex ?
",\n" :
", ";
1546 out <<
"[" << (complex ?
"\n" :
" ");
1549 const auto& l = element->listValue();
1550 for (
auto it = l.begin(); it != l.end(); ++it) {
1552 if (it != l.begin()) {
1557 out << std::string(indent + step,
' ');
1565 out <<
"\n" << std::string(indent,
' ');
1570 }
else if (element->getType() == Element::map) {
1572 if (element->size() == 0) {
1581 const auto& m = element->mapValue();
1583 for (
auto it = m.begin(); it != m.end(); ++it) {
1591 out << std::string(indent + step,
' ');
1593 out <<
"\"" << it->first <<
"\": ";
1595 prettyPrint(it->second, out, indent + step, step);
1599 out <<
"\n" << std::string(indent,
' ') <<
"}";
1602 element->toJSON(out);
1608 std::stringstream ss;
1613 void Element::preprocess(std::istream& in, std::stringstream& out) {
1617 while (std::getline(in, line)) {
1620 if (!line.empty() && line[0] ==
'#') {
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.
The Element class represents a piece of data, used by the command channel and configuration parts.
virtual bool equals(const Element &other) const =0
types
The types that an Element can hold.
virtual int64_t intValue() const
std::string str() const
Returns a string representing the Element and all its child elements; note that this is different fro...
virtual std::string stringValue() const
virtual bool contains(const std::string &name) const
Checks if there is data at the given key.
virtual size_t size() const
Returns the number of elements in the list.
virtual ConstElementPtr get(const int i) const
Returns the ElementPtr at the given index.
virtual double doubleValue() const
virtual isc::util::int128_t bigIntValue() const
virtual bool boolValue() const
Notes: IntElement type is changed to int64_t.
A standard Data module exception that is thrown if a parse error is encountered when constructing an ...
A standard Data module exception that is thrown if a function is called for an Element that has a wro...
#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.
uint16_t pos_
The position (offset from the beginning) in the buffer where the name starts.
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
bool operator==(const Element &a, const Element &b)
void mergeDiffAdd(ElementPtr &element, ElementPtr &other, HierarchyDescriptor &hierarchy, std::string key, size_t idx)
Merges the diff data by adding the missing elements from 'other' to 'element' (recursively).
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element.
void mergeDiffDel(ElementPtr &element, ElementPtr &other, HierarchyDescriptor &hierarchy, std::string key, size_t idx)
Merges the diff data by removing the data present in 'other' from 'element' (recursively).
bool operator<(Element const &a, Element const &b)
bool isEquivalent(ConstElementPtr a, ConstElementPtr b)
Compares the data with other using unordered lists.
std::string prettyPrint(ConstElementPtr element, unsigned indent, unsigned step)
Pretty prints the data into string.
std::ostream & operator<<(std::ostream &out, const Element &e)
Insert the Element as a string into stream.
boost::shared_ptr< const Element > ConstElementPtr
void extend(const std::string &container, const std::string &extension, ElementPtr &element, ElementPtr &other, HierarchyDescriptor &hierarchy, std::string key, size_t idx, bool alter)
Extends data by adding the specified 'extension' elements from 'other' inside the 'container' element...
bool isNull(ConstElementPtr p)
Checks whether the given ElementPtr is a NULL pointer.
ConstElementPtr removeIdentical(ConstElementPtr a, ConstElementPtr b)
Create a new ElementPtr from the first ElementPtr, removing all values that are equal in the second.
bool operator!=(const Element &a, const Element &b)
boost::shared_ptr< Element > ElementPtr
std::vector< FunctionMap > HierarchyDescriptor
Hierarchy descriptor of the containers in a specific Element hierarchy tree.
boost::multiprecision::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.
std::string str() const
Returns the position in the textual format.