51 const signed char digitvalue[256] = {
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
56 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
74 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
76 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
77 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
78 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
79 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
80 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
81 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
82 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
83 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
84 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
85 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
86 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
87 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
88 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
89 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
90 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
91 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
92 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
93 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
94 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
95 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
96 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
97 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
98 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
99 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
100 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
101 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
102 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
103 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
104 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
105 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
126 template<
class Iterator,
class Offsets,
class Data>
128 stringParse(Iterator s, Iterator send,
bool downcase, Offsets& offsets,
131 const Iterator orig_s(s);
135 unsigned int digits = 0;
136 unsigned int value = 0;
137 unsigned int count = 0;
143 bool is_root =
false;
144 const bool empty = s == send;
145 ft_state state = ft_init;
148 offsets.reserve(Name::MAX_LABELS);
149 offsets.push_back(0);
150 ndata.reserve(Name::MAX_WIRE);
157 while (ndata.size() < Name::MAX_WIRE && s != send && !done) {
158 unsigned char c = *s++;
168 "non terminating empty label in " <<
169 string(orig_s, send));
172 }
else if (c ==
'@' && s == send) {
188 state = ft_initialescape;
198 "duplicate period in " <<
string(orig_s, send));
200 ndata.at(offsets.back()) = count;
201 offsets.push_back(ndata.size());
207 }
else if (c ==
'\\') {
210 if (++count > Name::MAX_LABELLEN) {
212 "label is too long in " <<
string(orig_s, send));
214 ndata.push_back(downcase ?
maptolower[c] : c);
217 case ft_initialescape:
222 "invalid label type in " <<
string(orig_s, send));
226 if (!isdigit(c & 0xff)) {
227 if (++count > Name::MAX_LABELLEN) {
229 "label is too long in " <<
string(orig_s, send));
231 ndata.push_back(downcase ?
maptolower[c] : c);
237 state = ft_escdecimal;
240 if (!isdigit(c & 0xff)) {
242 "mixture of escaped digit and non-digit in "
243 <<
string(orig_s, send));
246 value += digitvalue[c];
251 "escaped decimal is too large in "
252 <<
string(orig_s, send));
254 if (++count > Name::MAX_LABELLEN) {
256 "label is too long in " <<
string(orig_s, send));
258 ndata.push_back(downcase ?
maptolower[value] : value);
269 if (ndata.size() == Name::MAX_WIRE) {
271 "name is too long for termination in " <<
272 string(orig_s, send));
275 if (state != ft_ordinary) {
277 "incomplete textual name in " <<
278 (empty ?
"<empty>" :
string(orig_s, send)));
280 if (state == ft_ordinary) {
282 ndata.at(offsets.back()) = count;
284 offsets.push_back(ndata.size());
286 ndata.push_back(
'\0');
293 Name::Name(
const std::string &namestring,
bool downcase) {
295 const std::string::const_iterator s = namestring.begin();
296 const std::string::const_iterator send = namestring.end();
303 stringParse(s, send, downcase, offsets, ndata);
306 labelcount_ = offsets.size();
308 ndata_.assign(ndata.data(), ndata.size());
309 length_ = ndata_.size();
310 offsets_.assign(offsets.begin(), offsets.end());
313 Name::Name(
const char* namedata,
size_t data_len,
const Name* origin,
317 if (namedata == NULL || data_len == 0) {
319 "No data provided to Name constructor");
323 const bool absolute = (namedata[data_len - 1] ==
'.');
325 if (!absolute && origin == NULL) {
327 "No origin available and name is relative");
330 const char* end = namedata + data_len;
337 stringParse(namedata, end, downcase, offsets, ndata);
340 labelcount_ = offsets.size();
342 ndata_.assign(ndata.data(), ndata.size());
343 length_ = ndata_.size();
344 offsets_.assign(offsets.begin(), offsets.end());
352 ndata_.erase(ndata_.end() - 1);
353 ndata_.append(origin->ndata_);
357 size_t offset = offsets_.back();
359 size_t offset_count = offsets_.size();
360 offsets_.insert(offsets_.end(), origin->offsets_.begin(),
361 origin->offsets_.end());
362 for (NameOffsets::iterator it(offsets_.begin() + offset_count);
363 it != offsets_.end(); ++it) {
368 length_ = ndata_.size();
369 labelcount_ = offsets_.size();
372 if (labelcount_ > Name::MAX_LABELS || length_ > Name::MAX_WIRE) {
391 offsets.reserve(Name::MAX_LABELS);
402 unsigned int nused = 0;
403 bool seen_pointer =
false;
404 fw_state state = fw_start;
406 unsigned int cused = 0;
408 unsigned int pos_begin = current;
409 unsigned int biggest_pointer = current;
414 unsigned int new_current = 0;
420 while (current < buffer.
getLength() && !done) {
429 if (c <= MAX_LABELLEN) {
430 offsets.push_back(nused);
431 if (nused + c + 1 > Name::MAX_WIRE) {
433 << nused + c + 1 <<
" bytes");
442 }
else if ((c & COMPRESS_POINTER_MARK8) == COMPRESS_POINTER_MARK8) {
446 new_current = c & ~COMPRESS_POINTER_MARK8;
448 state = fw_newcurrent;
470 if (new_current >= biggest_pointer) {
472 "bad compression pointer (out of range): " <<
475 biggest_pointer = new_current;
476 current = new_current;
490 labelcount_ = offsets.size();
492 offsets_.assign(offsets.begin(), offsets.end());
498 buffer.
writeData(ndata_.data(), ndata_.size());
507 Name::toText(
bool omit_final_dot)
const {
509 return (ls.
toText(omit_final_dot));
513 Name::toRawText(
bool omit_final_dot)
const {
519 Name::compare(
const Name& other)
const {
526 Name::equals(
const Name& other)
const {
527 if (length_ != other.length_ || labelcount_ != other.labelcount_) {
531 for (
unsigned int l = labelcount_, pos = 0; l > 0; --l) {
532 uint8_t count = ndata_[pos];
533 if (count != other.ndata_[pos]) {
538 while (count-- > 0) {
539 uint8_t label1 = ndata_[pos];
540 uint8_t label2 = other.ndata_[pos];
553 Name::leq(
const Name& other)
const {
554 return (compare(other).getOrder() <= 0);
558 Name::geq(
const Name& other)
const {
559 return (compare(other).getOrder() >= 0);
563 Name::lthan(
const Name& other)
const {
564 return (compare(other).getOrder() < 0);
568 Name::gthan(
const Name& other)
const {
569 return (compare(other).getOrder() > 0);
573 Name::isWildcard()
const {
574 return (length_ >= 2 && ndata_[0] == 1 && ndata_[1] ==
'*');
578 Name::concatenate(
const Name& suffix)
const {
582 unsigned int length = length_ + suffix.length_ - 1;
583 if (length > Name::MAX_WIRE) {
588 retname.ndata_.reserve(length);
589 retname.ndata_.assign(ndata_, 0, length_ - 1);
590 retname.ndata_.insert(retname.ndata_.end(),
591 suffix.ndata_.begin(), suffix.ndata_.end());
593 retname.length_ = length;
600 unsigned int labels = labelcount_ + suffix.labelcount_ - 1;
602 retname.offsets_.reserve(labels);
603 retname.offsets_.assign(&offsets_[0], &offsets_[0] + labelcount_ - 1);
604 transform(suffix.offsets_.begin(), suffix.offsets_.end(),
605 back_inserter(retname.offsets_),
606 [
this] (
char x) {
return (x + length_ - 1); });
608 retname.labelcount_ = labels;
614 Name::reverse()
const {
620 retname.offsets_.reserve(labelcount_);
621 retname.ndata_.reserve(length_);
624 NameOffsets::const_reverse_iterator rit0 = offsets_.rbegin();
625 NameOffsets::const_reverse_iterator rit1 = rit0 + 1;
626 NameString::const_iterator n0 = ndata_.begin();
627 retname.offsets_.push_back(0);
628 while (rit1 != offsets_.rend()) {
629 retname.ndata_.append(n0 + *rit1, n0 + *rit0);
630 retname.offsets_.push_back(retname.ndata_.size());
634 retname.ndata_.push_back(0);
636 retname.labelcount_ = labelcount_;
637 retname.length_ = length_;
643 Name::split(
const unsigned int first,
const unsigned int n)
const {
644 if (n == 0 || n > labelcount_ || first > labelcount_ - n) {
651 unsigned int newlabels = (first + n == labelcount_) ? n : n + 1;
657 retname.offsets_.reserve(newlabels);
658 transform(offsets_.begin() + first, offsets_.begin() + first + newlabels,
659 back_inserter(retname.offsets_),
660 [&](
char x) {
return (x - offsets_[first]); });
668 retname.ndata_.reserve(retname.offsets_.back() + 1);
669 retname.ndata_.assign(ndata_, offsets_[first], retname.offsets_.back());
670 retname.ndata_.push_back(0);
672 retname.length_ = retname.ndata_.size();
673 retname.labelcount_ = retname.offsets_.size();
680 Name::split(
const unsigned int level)
const {
681 if (level >= getLabelCount()) {
683 <<
") for name " << *
this);
686 return (split(level, getLabelCount() - level));
691 unsigned int nlen = length_;
692 unsigned int labels = labelcount_;
693 unsigned int pos = 0;
695 while (labels > 0 && nlen > 0) {
701 unsigned int count = ndata_.
at(pos++);
The Name class encapsulates DNS names.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
Thrown when origin is NULL and is needed.
virtual void writeName(const Name &name, bool compress=true)=0
Write a Name object into the internal buffer in wire format, with or without name compression...
std::string toText() const
Convert the LabelSequence to a string.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
std::string toRawText(bool omit_final_dot) const
Convert the LabelSequence to a string without escape sequences.
std::string toText(bool omit_final_dot=false) const
Convert the Name to a string.
uint8_t at(size_t pos) const
Provides one-byte name data in wire format at the specified position.
This is a supplemental class used only as a return value of Name::compare() and LabelSequence::compar...
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
The AbstractMessageRenderer class is an abstract base class that provides common interfaces for rende...
std::ostream & operator<<(std::ostream &os, const Name &name)
Insert the name as a string into stream.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Defines the logger used by the top-level component of kea-dhcp-ddns.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
NameComparisonResult compare(const LabelSequence &other, bool case_sensitive=false) const
Compares two label sequences.
Light-weight Accessor to Name data.
const uint8_t maptolower[]