]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[2572] introduced a special source size of "unknown".
authorJINMEI Tatuya <jinmei@isc.org>
Thu, 10 Jan 2013 23:23:29 +0000 (15:23 -0800)
committerJINMEI Tatuya <jinmei@isc.org>
Thu, 10 Jan 2013 23:23:29 +0000 (15:23 -0800)
this will help handle special cases like using the lexer with stdin
associated with a pipe.

src/lib/dns/master_lexer.cc
src/lib/dns/master_lexer.h
src/lib/dns/master_lexer_inputsource.cc
src/lib/dns/master_lexer_inputsource.h
src/lib/dns/tests/master_lexer_inputsource_unittest.cc

index b3a618f7d272bc29425d75e17ed34a801356b2a1..710f349c76f7f78777f42ef5c00cf85ea9c228be 100644 (file)
 
 #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
index cf46c53bc0b6de4311cfb9c33988962258f665fb..6f6ce7dadbd774396fac074d34556671f85c2516 100644 (file)
@@ -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
index 10d637f585f7214020f3dab02c302e7e1e211bc3..335a0dd6dd399e3341c15abab8921fc9adb1a9c5 100644 (file)
@@ -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");
     }
index 793505954d75b79a194ab9acd422ad0cd22dd63b..2ad0100b6e22fe9075a866f2f1a6c266d88b5035 100644 (file)
@@ -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_); }
index 1dc3408f3b462a6cd8e300d171ce1e01965cb88d..a26b02ca14f6fa25b3347479436bd06fe0ab3951 100644 (file)
@@ -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