Commit 844348f6 authored by JINMEI Tatuya's avatar JINMEI Tatuya

[2370] separate error type token to support error code

parent 57b907ed
......@@ -95,7 +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 += master_lexer.h master_lexer.cc
libb10_dns___la_SOURCES += message.h message.cc
libb10_dns___la_SOURCES += messagerenderer.h messagerenderer.cc
libb10_dns___la_SOURCES += name.h name.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 <dns/master_lexer.h>
#include <cassert>
#include <string>
namespace {
const char* const error_text[] = {
"lexer not started", // NOT_STARTED
"unbalanced parentheses", // UNBALANCED_PAREN
"unexpected end of input", // UNEXPECTED_END
"unbalanced quotes" // UNBALANCED_QUOTES
};
const size_t error_text_max_count = sizeof(error_text) / sizeof(error_text[0]);
}
namespace isc {
namespace dns {
std::string
MasterLexer::Token::getErrorText() const {
if (type_ != ERROR) {
isc_throw(InvalidOperation,
"Token::getErrorText() for non error type");
}
// The class integrity ensures the following:
assert(val_.error_code_ < error_text_max_count);
return (error_text[val_.error_code_]);
}
} // end of namespace dns
} // end of namespace isc
......@@ -32,20 +32,22 @@ public:
class MasterLexer::Token {
public:
enum Type {
ERROR,
END_OF_LINE,
END_OF_FILE,
INITIAL_WS,
SPECIAL_TYPE_MAX = INITIAL_WS,
STRING,
QSTRING,
NUMBER
NUMBER,
ERROR
};
enum ErrorCode {
NOT_STARTED,
UNBALANCED_PAREN,
UNEXPECTED_END,
UNBALANCED_QUOTES
UNBALANCED_QUOTES,
MAX_ERROR_CODE = UNBALANCED_QUOTES
};
struct StringRegion {
......@@ -54,7 +56,7 @@ public:
};
explicit Token(Type type) : type_(type) {
if (type >= STRING) {
if (type > SPECIAL_TYPE_MAX) {
isc_throw(InvalidParameter, "Token per-type constructor "
"called with invalid type: " << type);
}
......@@ -68,6 +70,13 @@ public:
explicit Token(uint32_t number) : type_(NUMBER) {
val_.number_ = number;
}
explicit Token(ErrorCode error_code) : type_(ERROR) {
if (error_code > MAX_ERROR_CODE) {
isc_throw(InvalidParameter, "Invalid master lexer error code: "
<< error_code);
}
val_.error_code_ = error_code;
}
Type getType() const { return (type_); }
std::string getString() const {
......@@ -81,7 +90,7 @@ public:
const StringRegion& getStringRegion() const {
if (type_ != STRING && type_ != QSTRING) {
isc_throw(InvalidOperation,
"Token::getString() for non string-variant type");
"Token::getStringRegion() for non string-variant type");
}
return (val_.str_region_);
}
......@@ -92,12 +101,21 @@ public:
}
return (val_.number_);
}
ErrorCode getErrorCode() const {
if (type_ != ERROR) {
isc_throw(InvalidOperation,
"Token::getErrorCode() for non error type");
}
return (val_.error_code_);
};
std::string getErrorText() const;
private:
Type type_;
union {
StringRegion str_region_;
uint32_t number_;
ErrorCode error_code_;
} val_;
};
......
......@@ -33,12 +33,14 @@ public:
MasterLexerTokenTest() :
token_eof(MasterLexer::Token::END_OF_FILE),
token_str(TEST_STRING, TEST_STRING_LEN),
token_num(42)
token_num(42),
token_err(MasterLexer::Token::UNEXPECTED_END)
{}
const MasterLexer::Token token_eof; // an example of special type token
const MasterLexer::Token token_str;
const MasterLexer::Token token_num;
const MasterLexer::Token token_err;
};
......@@ -116,5 +118,39 @@ TEST_F(MasterLexerTokenTest, specials) {
isc::InvalidParameter);
EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::NUMBER),
isc::InvalidParameter);
EXPECT_THROW(MasterLexer::Token t(MasterLexer::Token::ERROR),
isc::InvalidParameter);
}
TEST_F(MasterLexerTokenTest, errors) {
EXPECT_EQ(MasterLexer::Token::ERROR, token_err.getType());
EXPECT_EQ(MasterLexer::Token::UNEXPECTED_END, token_err.getErrorCode());
EXPECT_EQ("unexpected end of input", token_err.getErrorText());
EXPECT_EQ("lexer not started",
MasterLexer::Token(MasterLexer::Token::NOT_STARTED).
getErrorText());
EXPECT_EQ("unbalanced parentheses",
MasterLexer::Token(MasterLexer::Token::UNBALANCED_PAREN).
getErrorText());
EXPECT_EQ("unbalanced quotes",
MasterLexer::Token(MasterLexer::Token::UNBALANCED_QUOTES).
getErrorText());
// getErrorCode/Text() isn't allowed for non number types
EXPECT_THROW(token_num.getErrorCode(), isc::InvalidOperation);
EXPECT_THROW(token_num.getErrorText(), isc::InvalidOperation);
// Only the pre-defined error code is accepted. Hardcoding '4' (max code
// + 1) is intentional; it'd be actually better if we notice it when we
// update the enum list (which shouldn't happen too often).
EXPECT_THROW(MasterLexer::Token(MasterLexer::Token::ErrorCode(4)),
isc::InvalidParameter);
// Check the coexistence of "from number" and "from error-code"
// constructors won't cause confusion.
EXPECT_EQ(MasterLexer::Token::NUMBER,
MasterLexer::Token(static_cast<uint32_t>(
MasterLexer::Token::NOT_STARTED)).
getType());
}
}
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