Commit a5486492 authored by JINMEI Tatuya's avatar JINMEI Tatuya

[2370] defined MasterLexer and its Token classes, added main methods and tests

parent dc3884d6
......@@ -95,6 +95,7 @@ libb10_dns___la_SOURCES += edns.h edns.cc
libb10_dns___la_SOURCES += exceptions.h exceptions.cc
libb10_dns___la_SOURCES += labelsequence.h labelsequence.cc
libb10_dns___la_SOURCES += masterload.h masterload.cc
libb10_dns___la_SOURCES += master_lexer.h
libb10_dns___la_SOURCES += message.h message.cc
libb10_dns___la_SOURCES += messagerenderer.h messagerenderer.cc
libb10_dns___la_SOURCES += name.h name.cc
......@@ -145,6 +146,8 @@ libdns___include_HEADERS = \
exceptions.h \
labelsequence.h \
message.h \
master_lexer.h \
masterload.h \
messagerenderer.h \
name.h \
question.h \
......
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef MASTER_LEXER_H
#define MASTER_LEXER_H 1
#include <exceptions/exceptions.h>
#include <string>
#include <stdint.h>
namespace isc {
namespace dns {
class MasterLexer {
public:
class Token {
public:
enum Type {
ERROR,
END_OF_LINE,
END_OF_FILE,
INITIAL_WS,
STRING,
QSTRING,
NUMBER
};
struct StringRegion {
const char* beg;
size_t len;
};
explicit Token(Type type) : type_(type) {
if (type >= STRING) {
isc_throw(InvalidParameter, "Token per-type constructor "
"called with invalid type: " << type);
}
}
Token(const char* str_beg, size_t str_len, bool quoted = false) :
type_(quoted ? QSTRING : STRING)
{
val_.str_region_.beg = str_beg;
val_.str_region_.len = str_len;
}
explicit Token(uint32_t number) : type_(NUMBER) {
val_.number_ = number;
}
Type getType() const { return (type_); }
std::string getString() const {
if (type_ != STRING && type_ != QSTRING) {
isc_throw(InvalidOperation,
"Token::getString() for non string-variant type");
}
return (std::string(val_.str_region_.beg,
val_.str_region_.beg + val_.str_region_.len));
}
const StringRegion& getStringRegion() const {
if (type_ != STRING && type_ != QSTRING) {
isc_throw(InvalidOperation,
"Token::getString() for non string-variant type");
}
return (val_.str_region_);
}
uint32_t getNumber() const {
if (type_ != NUMBER) {
isc_throw(InvalidOperation,
"Token::getNumber() for non number type");
}
return (val_.number_);
}
private:
Type type_;
union {
StringRegion str_region_;
uint32_t number_;
} val_;
};
};
} // namespace dns
} // namespace isc
#endif // MASTER_LEXER_H
// Local Variables:
// mode: c++
// End:
......@@ -24,6 +24,7 @@ run_unittests_SOURCES = unittest_util.h unittest_util.cc
run_unittests_SOURCES += edns_unittest.cc
run_unittests_SOURCES += labelsequence_unittest.cc
run_unittests_SOURCES += messagerenderer_unittest.cc
run_unittests_SOURCES += master_lexer_token_unittest.cc
run_unittests_SOURCES += name_unittest.cc
run_unittests_SOURCES += nsec3hash_unittest.cc
run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc
......
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <exceptions/exceptions.h>
#include <dns/master_lexer.h>
#include <gtest/gtest.h>
#include <string>
using namespace isc::dns;
namespace {
const char TEST_STRING[] = "string token";
class MasterLexerTokenTest : public ::testing::Test {
public:
MasterLexerTokenTest() :
token_err(MasterLexer::Token::ERROR),
token_str(TEST_STRING, sizeof(TEST_STRING) - 1), // excluding ending 0
token_num(42)
{}
const MasterLexer::Token token_err;
const MasterLexer::Token token_str;
const MasterLexer::Token token_num;
};
TEST_F(MasterLexerTokenTest, strings) {
EXPECT_EQ(MasterLexer::Token::STRING, token_str.getType());
EXPECT_EQ(std::string("string token"), token_str.getString());
const MasterLexer::Token::StringRegion str_region =
token_str.getStringRegion();
EXPECT_EQ(TEST_STRING, str_region.beg);
EXPECT_EQ(sizeof(TEST_STRING) - 1, str_region.len);
// Construct type of qstring
EXPECT_EQ(MasterLexer::Token::QSTRING,
MasterLexer::Token(TEST_STRING, sizeof(TEST_STRING), true).
getType());
// if we explicitly set 'quoted' to false, it should be normal string
EXPECT_EQ(MasterLexer::Token::STRING,
MasterLexer::Token(TEST_STRING, sizeof(TEST_STRING), false).
getType());
// getString/StringRegion() aren't allowed for non string(-variant) types
EXPECT_THROW(token_err.getString(), isc::InvalidOperation);
EXPECT_THROW(token_num.getString(), isc::InvalidOperation);
EXPECT_THROW(token_err.getStringRegion(), isc::InvalidOperation);
EXPECT_THROW(token_num.getStringRegion(), isc::InvalidOperation);
}
TEST_F(MasterLexerTokenTest, numbers) {
EXPECT_EQ(42, token_num.getNumber());
EXPECT_EQ(MasterLexer::Token::NUMBER, token_num.getType());
// It's copyable and assignable.
MasterLexer::Token token(token_num);
EXPECT_EQ(42, token.getNumber());
EXPECT_EQ(MasterLexer::Token::NUMBER, token.getType());
token = token_num;
EXPECT_EQ(42, token.getNumber());
EXPECT_EQ(MasterLexer::Token::NUMBER, token.getType());
// it's okay to replace it with a different type of token
token = token_err;
EXPECT_EQ(MasterLexer::Token::ERROR, token.getType());
// Possible max value
token = MasterLexer::Token(0xffffffff);
EXPECT_EQ(4294967295u, token.getNumber());
// TBD: getNumber for other type
EXPECT_THROW(token_err.getNumber(), isc::InvalidOperation);
}
TEST_F(MasterLexerTokenTest, specials) {
// Just checking we can construct them and getType() returns correct value.
EXPECT_EQ(MasterLexer::Token::ERROR, token_err.getType());
EXPECT_EQ(MasterLexer::Token::END_OF_LINE,
MasterLexer::Token(MasterLexer::Token::END_OF_LINE).getType());
EXPECT_EQ(MasterLexer::Token::END_OF_FILE,
MasterLexer::Token(MasterLexer::Token::END_OF_FILE).getType());
EXPECT_EQ(MasterLexer::Token::INITIAL_WS,
MasterLexer::Token(MasterLexer::Token::INITIAL_WS).getType());
// Special types of tokens cannot have value-based types
EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::STRING),
isc::InvalidParameter);
EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::QSTRING),
isc::InvalidParameter);
EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::NUMBER),
isc::InvalidParameter);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment