Commit 4baf3a4d authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2572] introduced a special source size of "unknown".

this will help handle special cases like using the lexer with stdin
associated with a pipe.
parent 76ca3129
......@@ -24,12 +24,22 @@
#include <bitset>
#include <cassert>
#include <limits>
#include <string>
#include <vector>
namespace isc {
namespace dns {
// The definition of SOURCE_SIZE_UNKNOWN. Note that we initialize it using
// a method of another library. Technically, this could trigger a static
// initialization fiasco. But in this particular usage it's very unlikely
// to happen because this value is expected to be used only as a return
// value of a MasterLexer's method, and its constructor needs definitions
// here.
const size_t MasterLexer::SOURCE_SIZE_UNKNOWN =
std::numeric_limits<size_t>::max();
namespace {
typedef boost::shared_ptr<master_lexer_internal::InputSource> InputSourcePtr;
} // end unnamed namespace
......
......@@ -331,6 +331,16 @@ public:
const MasterToken token_;
};
/// \brief Special value for input source size meaning "unknown".
///
/// This constant value will be used as a return value of
/// \c getTotalSourceSize() when the size of one of the pushed sources
/// is unknown. Note that this value itself is a valid integer in the
/// range of the type, so there's still a small possibility of
/// ambiguity. In practice, however, the value should be sufficiently
/// large that should eliminate the possibility.
static const size_t SOURCE_SIZE_UNKNOWN;
/// \brief Options for getNextToken.
///
/// A compound option, indicating multiple options are set, can be
......@@ -458,6 +468,12 @@ public:
/// the size of the data available in the stream at the time of the
/// source is pushed.
///
/// In some special cases, it's possible that the size of the file or
/// stream is unknown. It happens, for example, if the standard input
/// is associated with a pipe from the output of another process and it's
/// specified as an input source. If the size of some of the pushed
/// pushed source is unknown, this method returns SOURCE_SIZE_UNKNOWN.
///
/// If there is no source pushed in the lexer, it returns 0.
///
/// \throw None
......
......@@ -37,16 +37,27 @@ createStreamName(const std::istream& input_stream) {
size_t
getStreamSize(std::istream& is) {
is.seekg(0, std::ios_base::end);
if (is.fail() || is.bad()) {
if (is.bad()) {
// This means the istream has an integrity error. It doesn't make
// sense to continue from this point, so we treat it as a fatal error.
isc_throw(InputSource::OpenError,
"failed to seek end of input source");
} else if (is.fail()) {
// This is an error specific to seekg(). There can be several
// reasons, but the most likely cause in this context is that the
// stream is associated with a special type of file such as a pipe.
// In this case, it's more likely that other main operations of
// the input source work fine, so we continue with just setting
// the stream size to "unknown".
is.clear(); // clear this error not to confuse later ops.
return (MasterLexer::SOURCE_SIZE_UNKNOWN);
}
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()) {
if (is.fail()) {
isc_throw(InputSource::OpenError,
"failed to seek beginning of input source");
}
......
......@@ -89,8 +89,10 @@ public:
/// \brief Returns the size of the input source in bytes.
///
/// If the size is unknown, it returns \c MasterLexer::SOURCE_SIZE_UNKNOWN.
///
/// See \c MasterLexer::getTotalSourceSize() for the definition of
/// the size of sources.
/// the size of sources and for when the size can be unknown.
///
/// \throw None
size_t getSize() const { return (input_size_); }
......
......@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <dns/master_lexer_inputsource.h>
#include <dns/master_lexer.h>
#include <exceptions/exceptions.h>
#include <gtest/gtest.h>
......@@ -346,9 +347,16 @@ TEST_F(InputSourceTest, getSize) {
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.
// Pretend there's an error in seeking in the stream. It will be
// considered a seek specific error, and getSize() returns "unknown".
iss.setstate(std::ios_base::failbit);
EXPECT_EQ(MasterLexer::SOURCE_SIZE_UNKNOWN, InputSource(iss).getSize());
// The fail bit should have been cleared.
EXPECT_FALSE(iss.fail());
// Pretend there's a *critical* error in the stream. The constructor will
// throw in the attempt of getting the input size.
iss.setstate(std::ios_base::badbit);
EXPECT_THROW(InputSource isrc(iss), InputSource::OpenError);
// Check with input source from file name. We hardcode the file size
......
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