// The parser of name from a string. It is a template, because
// some parameters are used with two different types, while others
// are private type aliases.
-template<class String, class Iterator, class Offsets, class Data>
+template<class Iterator, class Offsets, class Data>
void
-stringParse(const String& namestring, Iterator s, Iterator send,
- bool downcase, Offsets& offsets, Data& ndata)
+stringParse(Iterator s, Iterator send, bool downcase, Offsets& offsets,
+ Data& ndata)
{
+ const Iterator orig_s(s);
//
// Initialize things to make the compiler happy; they're not required.
//
//
bool done = false;
bool is_root = false;
+ const bool empty = s == send;
ft_state state = ft_init;
// Prepare the output buffers.
if (c == '.') {
if (s != send) {
isc_throw(EmptyLabel,
- "non terminating empty label in " << namestring);
+ "non terminating empty label in " <<
+ string(orig_s, send));
}
is_root = true;
} else if (c == '@' && s == send) {
if (c == '.') {
if (count == 0) {
isc_throw(EmptyLabel,
- "duplicate period in " << namestring);
+ "duplicate period in " << string(orig_s, send));
}
ndata.at(offsets.back()) = count;
offsets.push_back(ndata.size());
} else {
if (++count > Name::MAX_LABELLEN) {
isc_throw(TooLongLabel,
- "label is too long in " << namestring);
+ "label is too long in " << string(orig_s, send));
}
ndata.push_back(downcase ? maptolower[c] : c);
}
// This looks like a bitstring label, which was deprecated.
// Intentionally drop it.
isc_throw(BadLabelType,
- "invalid label type in " << namestring);
+ "invalid label type in " << string(orig_s, send));
}
state = ft_escape;
// FALLTHROUGH
if (!isdigit(c & 0xff)) {
if (++count > Name::MAX_LABELLEN) {
isc_throw(TooLongLabel,
- "label is too long in " << namestring);
+ "label is too long in " << string(orig_s, send));
}
ndata.push_back(downcase ? maptolower[c] : c);
state = ft_ordinary;
if (!isdigit(c & 0xff)) {
isc_throw(BadEscape,
"mixture of escaped digit and non-digit in "
- << namestring);
+ << string(orig_s, send));
}
value *= 10;
value += digitvalue[c];
if (value > 255) {
isc_throw(BadEscape,
"escaped decimal is too large in "
- << namestring);
+ << string(orig_s, send));
}
if (++count > Name::MAX_LABELLEN) {
isc_throw(TooLongLabel,
- "label is too long in " << namestring);
+ "label is too long in " << string(orig_s, send));
}
ndata.push_back(downcase ? maptolower[value] : value);
state = ft_ordinary;
if (!done) { // no trailing '.' was found.
if (ndata.size() == Name::MAX_WIRE) {
isc_throw(TooLongName,
- "name is too long for termination in " << namestring);
+ "name is too long for termination in " <<
+ string(orig_s, send));
}
assert(s == send);
if (state != ft_ordinary && state != ft_at) {
isc_throw(IncompleteName,
"incomplete textual name in " <<
- (namestring.empty() ? "<empty>" : namestring));
+ (empty ? "<empty>" : string(orig_s, send)));
}
if (state == ft_ordinary) {
assert(count != 0);
Name::Name(const std::string &namestring, bool downcase) {
// Prepare inputs for the parser
- std::string::const_iterator s = namestring.begin();
- std::string::const_iterator send = namestring.end();
+ const std::string::const_iterator s = namestring.begin();
+ const std::string::const_iterator send = namestring.end();
// Prepare outputs
NameOffsets offsets;
NameString ndata;
// To the parsing
- stringParse(namestring, s, send, downcase, offsets, ndata);
+ stringParse(s, send, downcase, offsets, ndata);
// And get the output
labelcount_ = offsets.size();
offsets_.assign(offsets.begin(), offsets.end());
}
+Name::Name(const char* namedata, size_t data_len, const Name*, bool downcase) {
+ // Prepare inputs for the parser
+ const char* end = namedata + data_len;
+
+ // Prepare outputs
+ NameOffsets offsets;
+ NameString ndata;
+
+ // Do the actual parsing
+ stringParse(namedata, end, downcase, offsets, ndata);
+
+ // Get the output
+ labelcount_ = offsets.size();
+ assert(labelcount_ > 0 && labelcount_ <= Name::MAX_LABELS);
+ ndata_.assign(ndata.data(), ndata.size());
+ length_ = ndata_.size();
+ offsets_.assign(offsets.begin(), offsets.end());
+}
+
namespace {
///
/// Wire-format name parser states.
// NameParserException.
EXPECT_THROW(Name(txt, false), ExceptionType);
EXPECT_THROW(Name(txt, false), NameParserException);
-#if 0
- // TODO: Enable once the new constructor exists.
// The same is thrown when constructing by the master-file constructor
EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()),
ExceptionType);
EXPECT_THROW(Name(txt.c_str(), txt.length(), &Name::ROOT_NAME()),
NameParserException);
-#endif
}
TEST_F(NameTest, fromText) {
EXPECT_EQ(Name::MAX_LABELS, maxlabels.getLabelCount());
}
-#if 0
-// TODO: Enable once the constructor exists, there's a need to test the changes
// on the rest while we prepare it.
// Check the @ syntax is accepted and it just copies the origin.
TEST_F(NameTest, copyOrigin) {
// Test the master-file constructor does not append the origin when the
// provided name is absolute
TEST_F(NameTest, dontAppendOrigin) {
- EXPECT_EQ(example_name, Name("www.example.org.", 16, &origin_name));
+ EXPECT_EQ(example_name, Name("www.example.com.", 16, &origin_name));
// The downcase works (only if provided, though)
- EXPECT_EQ(example_name, Name("WWW.EXAMPLE.ORG.", 16, &origin_name, true));
- EXPECT_EQ(example_name_upper, Name("WWW.EXAMPLE.ORG.", 16, &origin_name));
+ EXPECT_EQ(example_name, Name("WWW.EXAMPLE.COM.", 16, &origin_name, true));
+ EXPECT_EQ(example_name_upper, Name("WWW.EXAMPLE.COM.", 16, &origin_name));
// And it does not require the origin to be provided
- EXPECT_NO_THROW(Name("www.example.org.", 16, NULL));
+ EXPECT_NO_THROW(Name("www.example.com.", 16, NULL));
}
// Test the master-file constructor properly appends the origin when
EXPECT_EQ(example_name, Name("WWW", 3, &origin_name_upper, true));
EXPECT_EQ(example_name_upper, Name("WWW", 3, &origin_name_upper));
// Check we can prepend more than one label
- EXPECT_EQ(Name("a.b.c.d.example.org."), Name("a.b.c.d", 7, &origin_name));
+ EXPECT_EQ(Name("a.b.c.d.example.com."), Name("a.b.c.d", 7, &origin_name));
// When the name is relative, we throw.
EXPECT_THROW(Name("www", 3, NULL), MissingNameOrigin);
}
EXPECT_NO_THROW(Name(max_labels_str, strlen(max_labels_str),
&Name::ROOT_NAME()));
}
-#endif
TEST_F(NameTest, fromWire) {
//