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 <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
|
||||
|
Loading…
x
Reference in New Issue
Block a user