From: JINMEI Tatuya Date: Thu, 10 Jan 2013 00:32:56 +0000 (-0800) Subject: [2572] added InputSource::getSize() to know the total size of the source. X-Git-Tag: bind10-1.0.0-rc-release~95^2~11^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b32cd0ea8778cac7a9f9e991d3c978dc7faf93cd;p=thirdparty%2Fkea.git [2572] added InputSource::getSize() to know the total size of the source. --- diff --git a/src/lib/dns/master_lexer_inputsource.cc b/src/lib/dns/master_lexer_inputsource.cc index 03801f694f..50052bdf94 100644 --- a/src/lib/dns/master_lexer_inputsource.cc +++ b/src/lib/dns/master_lexer_inputsource.cc @@ -15,6 +15,9 @@ #include #include +#include +#include +#include #include #include @@ -31,6 +34,26 @@ createStreamName(const std::istream& input_stream) { return (ss.str()); } +size_t +getStreamSize(std::istream& is) { + is.seekg(0, std::ios_base::end); + if (is.fail() || is.bad()) { + isc_throw(InputSource::OpenError, + "failed to seek end of input source"); + } + const std::streampos len = is.tellg(); + if (len == -1) { + isc_throw(InputSource::OpenError, "failed to get input size"); + } + is.seekg(0, std::ios::beg); + if (is.fail() || is.bad()) { + isc_throw(InputSource::OpenError, + "failed to seek beginning of input source"); + } + assert(len >= 0); + return (len); +} + } // end of unnamed namespace // Explicit definition of class static constant. The value is given in the @@ -43,30 +66,41 @@ InputSource::InputSource(std::istream& input_stream) : saved_line_(line_), buffer_pos_(0), name_(createStreamName(input_stream)), - input_(input_stream) + input_(input_stream), + input_size_(getStreamSize(input_)) {} -InputSource::InputSource(const char* filename) : - at_eof_(false), - line_(1), - saved_line_(line_), - buffer_pos_(0), - name_(filename), - input_(file_stream_) -{ +namespace { +// A helper to initialize InputSource::input_ in the member initialization +// list. +std::istream& +openFileStream(std::ifstream& file_stream, const char* filename) { errno = 0; - file_stream_.open(filename); - if (file_stream_.fail()) { + file_stream.open(filename); + if (file_stream.fail()) { std::string error_txt("Error opening the input source file: "); error_txt += filename; if (errno != 0) { error_txt += "; possible cause: "; error_txt += std::strerror(errno); } - isc_throw(OpenError, error_txt); + isc_throw(InputSource::OpenError, error_txt); } + + return (file_stream); +} } +InputSource::InputSource(const char* filename) : + at_eof_(false), + line_(1), + saved_line_(line_), + buffer_pos_(0), + name_(filename), + input_(openFileStream(file_stream_, filename)), + input_size_(getStreamSize(input_)) +{} + InputSource::~InputSource() { if (file_stream_.is_open()) { diff --git a/src/lib/dns/master_lexer_inputsource.h b/src/lib/dns/master_lexer_inputsource.h index 1a4497f556..56d1ea0a0e 100644 --- a/src/lib/dns/master_lexer_inputsource.h +++ b/src/lib/dns/master_lexer_inputsource.h @@ -83,6 +83,17 @@ public: return (name_); } + /// \brief Returns the size of the input source in bytes. + /// + /// If the input source is a normal file, the return value should be + /// equal to the file size at the time of the source is created. + /// If the input source is other type of input stream, its the size of + /// the data available in the stream at the time of the construction of + /// the source. + /// + /// \throw None. + size_t getSize() const { return (input_size_); } + /// \brief Returns if the input source is at end of file. bool atEOF() const { return (at_eof_); @@ -146,6 +157,7 @@ private: const std::string name_; std::ifstream file_stream_; std::istream& input_; + const size_t input_size_; }; } // namespace master_lexer_internal diff --git a/src/lib/dns/tests/master_lexer_inputsource_unittest.cc b/src/lib/dns/tests/master_lexer_inputsource_unittest.cc index db0cbec1b0..e124383440 100644 --- a/src/lib/dns/tests/master_lexer_inputsource_unittest.cc +++ b/src/lib/dns/tests/master_lexer_inputsource_unittest.cc @@ -29,10 +29,13 @@ using namespace isc::dns::master_lexer_internal; namespace { +const char* const test_input = + "Line1 to scan.\nLine2 to scan.\nLine3 to scan.\n"; + class InputSourceTest : public ::testing::Test { protected: InputSourceTest() : - str_("Line1 to scan.\nLine2 to scan.\nLine3 to scan.\n"), + str_(test_input), str_length_(strlen(str_)), iss_(str_), source_(iss_) @@ -322,4 +325,22 @@ TEST_F(InputSourceTest, saveLine) { EXPECT_FALSE(source_.atEOF()); } +TEST_F(InputSourceTest, getSize) { + // A simple case using string stream + EXPECT_EQ(strlen(test_input), source_.getSize()); + + // Check it works with an empty input + istringstream iss(""); + EXPECT_EQ(0, InputSource(iss).getSize()); + + // Pretend there's an error in the stream. The constructor will throw + // in the attempt of getting the input size. + iss.setstate(std::ios_base::failbit); + EXPECT_THROW(InputSource isrc(iss), InputSource::OpenError); + + // Check with input source from file name. We hardcode the file size + // for simplicity. It won't change too often. + EXPECT_EQ(143, InputSource(TEST_DATA_SRCDIR "/masterload.txt").getSize()); +} + } // end namespace