mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 04:57:52 +00:00
[2572] introduced a special source size of "unknown".
this will help handle special cases like using the lexer with stdin associated with a pipe.
This commit is contained in:
parent
76ca31298b
commit
4baf3a4dca
@ -24,12 +24,22 @@
|
|||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace isc {
|
namespace isc {
|
||||||
namespace dns {
|
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 {
|
namespace {
|
||||||
typedef boost::shared_ptr<master_lexer_internal::InputSource> InputSourcePtr;
|
typedef boost::shared_ptr<master_lexer_internal::InputSource> InputSourcePtr;
|
||||||
} // end unnamed namespace
|
} // end unnamed namespace
|
||||||
|
@ -331,6 +331,16 @@ public:
|
|||||||
const MasterToken token_;
|
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.
|
/// \brief Options for getNextToken.
|
||||||
///
|
///
|
||||||
/// A compound option, indicating multiple options are set, can be
|
/// 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
|
/// the size of the data available in the stream at the time of the
|
||||||
/// source is pushed.
|
/// 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.
|
/// If there is no source pushed in the lexer, it returns 0.
|
||||||
///
|
///
|
||||||
/// \throw None
|
/// \throw None
|
||||||
|
@ -37,16 +37,27 @@ createStreamName(const std::istream& input_stream) {
|
|||||||
size_t
|
size_t
|
||||||
getStreamSize(std::istream& is) {
|
getStreamSize(std::istream& is) {
|
||||||
is.seekg(0, std::ios_base::end);
|
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,
|
isc_throw(InputSource::OpenError,
|
||||||
"failed to seek end of input source");
|
"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();
|
const std::streampos len = is.tellg();
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
isc_throw(InputSource::OpenError, "failed to get input size");
|
isc_throw(InputSource::OpenError, "failed to get input size");
|
||||||
}
|
}
|
||||||
is.seekg(0, std::ios::beg);
|
is.seekg(0, std::ios::beg);
|
||||||
if (is.fail() || is.bad()) {
|
if (is.fail()) {
|
||||||
isc_throw(InputSource::OpenError,
|
isc_throw(InputSource::OpenError,
|
||||||
"failed to seek beginning of input source");
|
"failed to seek beginning of input source");
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,10 @@ public:
|
|||||||
|
|
||||||
/// \brief Returns the size of the input source in bytes.
|
/// \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
|
/// 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
|
/// \throw None
|
||||||
size_t getSize() const { return (input_size_); }
|
size_t getSize() const { return (input_size_); }
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include <dns/master_lexer_inputsource.h>
|
#include <dns/master_lexer_inputsource.h>
|
||||||
|
#include <dns/master_lexer.h>
|
||||||
#include <exceptions/exceptions.h>
|
#include <exceptions/exceptions.h>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
@ -346,9 +347,16 @@ TEST_F(InputSourceTest, getSize) {
|
|||||||
istringstream iss("");
|
istringstream iss("");
|
||||||
EXPECT_EQ(0, InputSource(iss).getSize());
|
EXPECT_EQ(0, InputSource(iss).getSize());
|
||||||
|
|
||||||
// Pretend there's an error in the stream. The constructor will throw
|
// Pretend there's an error in seeking in the stream. It will be
|
||||||
// in the attempt of getting the input size.
|
// considered a seek specific error, and getSize() returns "unknown".
|
||||||
iss.setstate(std::ios_base::failbit);
|
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);
|
EXPECT_THROW(InputSource isrc(iss), InputSource::OpenError);
|
||||||
|
|
||||||
// Check with input source from file name. We hardcode the file size
|
// Check with input source from file name. We hardcode the file size
|
||||||
|
Loading…
x
Reference in New Issue
Block a user