Commit 29ff6beb authored by Mukund Sivaraman's avatar Mukund Sivaraman
Browse files

[2369] Add InputSource helper class (work-in-progress)

parent dc3884d6
......@@ -93,6 +93,7 @@ libb10_dns___la_LDFLAGS = -no-undefined -version-info 2:0:0
libb10_dns___la_SOURCES =
libb10_dns___la_SOURCES += edns.h edns.cc
libb10_dns___la_SOURCES += exceptions.h exceptions.cc
libb10_dns___la_SOURCES += inputsource.h inputsource.cc
libb10_dns___la_SOURCES += labelsequence.h labelsequence.cc
libb10_dns___la_SOURCES += masterload.h masterload.cc
libb10_dns___la_SOURCES += message.h message.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/inputsource.h>
#include <exceptions/exceptions.h>
namespace isc {
namespace dns {
namespace master_lexer_internal {
int
InputSource::getChar() {
if (buffer_pos_ == buffer_.size()) {
// We may have reached EOF at the last call to
// getChar(). at_eof_ will be set then. We then simply return
// early.
if (at_eof_) {
return -1;
}
// We are not yet at EOF. Read from the stream.
int c = input_.get();
// Have we reached EOF now? If so, set at_eof_ and return early,
// but don't modify buffer_pos_ (which should still be equal to
// the size of buffer_).
if (!input_.good()) {
at_eof_ = true;
return -1;
}
buffer_.push_back(c);
}
int c = buffer_[buffer_pos_++];
if (c == '\n') {
line_++;
}
return (c);
}
void
InputSource::ungetChar() {
if (at_eof_) {
at_eof_ = false;
} else if (buffer_pos_ == 0) {
isc_throw(OutOfRange, "Cannot skip before the start of buffer");
} else {
if (buffer_[buffer_pos_] == '\n') {
line_--;
}
buffer_pos_--;
}
}
void
InputSource::ungetAll() {
buffer_pos_ = 0;
line_ = saved_line_;
at_eof_ = false;
}
} // namespace master_lexer_internal
} // namespace dns
} // namespace isc
// 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 DNS_INPUTSOURCE_H
#define DNS_INPUTSOURCE_H 1
#include <iostream>
#include <string>
#include <vector>
namespace isc {
namespace dns {
namespace master_lexer_internal {
class InputSource {
public:
InputSource(std::istream& input, const std::string& name) :
input_(input),
name_(name),
at_eof_(false),
line_(1),
saved_line_(line_),
buffer_pos_(buffer_.size())
{}
const std::string& getName() {
return (name_);
}
bool atEOF() const {
return (at_eof_);
}
size_t getCurrentLine() const {
return (line_);
}
void saveLine() {
saved_line_ = line_;
}
int getChar();
void ungetChar();
void ungetAll();
private:
std::istream& input_;
const std::string name_;
bool at_eof_;
size_t line_;
size_t saved_line_;
std::vector<char> buffer_;
size_t buffer_pos_;
};
} // namespace master_lexer_internal
} // namespace dns
} // namespace isc
#endif // DNS_INPUTSOURCE_H
// Local Variables:
// mode: c++
// End:
......@@ -22,6 +22,7 @@ if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = unittest_util.h unittest_util.cc
run_unittests_SOURCES += edns_unittest.cc
run_unittests_SOURCES += inputsource_unittest.cc
run_unittests_SOURCES += labelsequence_unittest.cc
run_unittests_SOURCES += messagerenderer_unittest.cc
run_unittests_SOURCES += name_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 <dns/inputsource.h>
#include <exceptions/exceptions.h>
#include <gtest/gtest.h>
#include <iostream>
#include <sstream>
#include <string>
#include <string.h>
using namespace std;
using namespace isc::dns;
using namespace isc::dns::master_lexer_internal;
namespace {
class InputSourceTest : public ::testing::Test {
protected:
InputSourceTest() :
name_("a90wjer"),
str_("Line1 to scan.\nLine2 to scan.\nLine3 to scan.\n"),
str_length_(strlen(str_)),
iss_(str_),
source_(iss_, name_)
{}
string name_;
const char* str_;
size_t str_length_;
stringstream iss_;
InputSource source_;
};
// Test the default return values set during InputSource construction.
TEST_F(InputSourceTest, defaults) {
EXPECT_EQ(name_, source_.getName());
EXPECT_EQ(1, source_.getCurrentLine());
EXPECT_FALSE(source_.atEOF());
}
// getChar() should return characters from the input stream in
// sequence. ungetChar() should skip backwards.
TEST_F(InputSourceTest, getAndUngetChar) {
for (size_t i = 0; i < str_length_; i++) {
EXPECT_EQ(str_[i], source_.getChar());
EXPECT_FALSE(source_.atEOF());
}
// At this point, we still have not reached EOF.
EXPECT_FALSE(source_.atEOF());
// This should cause EOF to be set.
EXPECT_EQ(-1, source_.getChar());
// Now, EOF should be set.
EXPECT_TRUE(source_.atEOF());
// Now, let's go backwards. This should cause the EOF to be set to
// false.
source_.ungetChar();
// Now, EOF should be false.
EXPECT_FALSE(source_.atEOF());
// This should cause EOF to be set again.
EXPECT_EQ(-1, source_.getChar());
// Now, EOF should be set.
EXPECT_TRUE(source_.atEOF());
// Now, let's go backwards in a loop. Start by skipping the EOF.
source_.ungetChar();
for (size_t i = 0; i < str_length_; i++) {
size_t index = str_length_ - 1 - i;
// Skip one character.
source_.ungetChar();
EXPECT_EQ(str_[index], source_.getChar());
// Skip the character we received again.
source_.ungetChar();
}
// Skipping past the start of buffer should throw.
EXPECT_THROW(source_.ungetChar(), isc::OutOfRange);
}
// ungetAll() should skip back to the place where the InputSource
// started at construction.
TEST_F(InputSourceTest, ungetAll) {
while (!source_.atEOF()) {
source_.getChar();
}
// Now, we are at EOF.
EXPECT_TRUE(source_.atEOF());
EXPECT_EQ(4, source_.getCurrentLine());
source_.ungetAll();
// Now we are back to where we started.
EXPECT_EQ(1, source_.getCurrentLine());
EXPECT_FALSE(source_.atEOF());
}
// Test line counters.
TEST_F(InputSourceTest, lines) {
size_t line = 1;
while (!source_.atEOF()) {
if (source_.getChar() == '\n') {
line++;
}
EXPECT_EQ(line, source_.getCurrentLine());
}
// Now, we are at EOF.
EXPECT_TRUE(source_.atEOF());
EXPECT_EQ(4, source_.getCurrentLine());
// Go backwards 1 character, skipping the last '\n'.
source_.ungetChar();
EXPECT_FALSE(source_.atEOF());
EXPECT_EQ(3, source_.getCurrentLine());
source_.ungetAll();
// Now we are back to where we started.
EXPECT_EQ(1, source_.getCurrentLine());
EXPECT_FALSE(source_.atEOF());
}
} // end namespace
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