]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Improved SBuf::appendf() readability and correctness.
authorFrancesco Chemolli <kinkie@squid-cache.org>
Wed, 31 Jul 2013 12:17:23 +0000 (14:17 +0200)
committerFrancesco Chemolli <kinkie@squid-cache.org>
Wed, 31 Jul 2013 12:17:23 +0000 (14:17 +0200)
Clarified documentation.
Added SBuf::spaceSize()
Fixed display result in appendf() unit test.

src/SBuf.cc
src/SBuf.h
src/tests/testSBuf.cc

index b49a40c5c4c19690d41526a81d11b09db7c6f3aa..64f1a82d69663543d251c78228a55cd73998d0e9 100644 (file)
@@ -268,47 +268,45 @@ SBuf::appendf(const char *fmt, ...)
 SBuf&
 SBuf::vappendf(const char *fmt, va_list vargs)
 {
+    Must(fmt != NULL);
+    int sz = 0;
+    //reserve twice the format-string size, it's a likely heuristic
+    size_type requiredSpaceEstimate = strlen(fmt)*2;
+
+    char *space = rawSpace(requiredSpaceEstimate);
 #ifdef VA_COPY
     va_list ap;
+    VA_COPY(ap, vargs);
+    sz = vsnprintf(space, spaceSize(), fmt, ap);
+    va_end(ap);
+#else
+    sz = vsnprintf(space, spaceSize(), fmt, vargs);
 #endif
-    int sz = 0;
 
-    Must(fmt != NULL);
-
-    //reserve twice the format-string size, it's a likely heuristic
-    rawSpace(strlen(fmt)*2);
+    /* check for possible overflow */
+    /* snprintf on Linux returns -1 on output errors, or the size
+     * that would have been written if enough space had been available */
+    /* vsnprintf is standard in C99 */
 
-    while (length() <= maxSize) {
-#ifdef VA_COPY
-        /* Fix of bug 753r. The value of vargs is undefined
-         * after vsnprintf() returns. Make a copy of vargs
-         * in case we loop around and call vsnprintf() again.
-         */
-        VA_COPY(ap, vargs);
-        sz = vsnprintf(bufEnd(), store_->spaceSize(), fmt, ap);
-        va_end(ap);
-#else /* VA_COPY */
-        sz = vsnprintf(bufEnd(), store_->spaceSize(), fmt, vargs);
-#endif /* VA_COPY*/
-        /* check for possible overflow */
-        /* snprintf on Linux returns -1 on overflows */
-        /* snprintf on FreeBSD returns at least free_space on overflows */
-
-        if (sz >= static_cast<int>(store_->spaceSize()))
-            rawSpace(sz*2); // TODO: tune heuristics
-        else if (sz < 0) // output error in vsnprintf
-            throw TextException("output error in vsnprintf",__FILE__, __LINE__);
-        else
-            break;
+    if (sz >= static_cast<int>(spaceSize())) {
+        // not enough space on the first go, we now know how much we need
+        requiredSpaceEstimate = sz*2; // TODO: tune heuristics
+        space = rawSpace(requiredSpaceEstimate);
+        sz = vsnprintf(space, spaceSize(), fmt, vargs);
     }
 
+    if (sz < 0) // output error in either vsnprintf
+        throw TextException("output error in vsnprintf",__FILE__, __LINE__);
+
+    // data was appended, update internal state
     len_ += sz;
+
     // TODO: this does NOT belong here, but to class-init or autoconf
-    /* on Linux and FreeBSD, '\0' is not counted in return value */
-    /* on XXX it might be counted */
-    /* check that '\0' is appended and not counted */
+    /* C99 specifies that the final '\0' is not counted in vsnprintf's
+     * return value. Older compilers/libraries might instead count it */
+    /* check whether '\0' was appended and counted */
 
-    if (operator[](len_-1) == '\0') {
+    if (at(len_-1) == '\0') {
         --sz;
         --len_;
     }
index fb65ca6f588d0f75cf53f9819a6083bfadbcb96e..91ae9ae34d254cd9fdedaaec0b8ec0fef55ccffb 100644 (file)
@@ -346,14 +346,20 @@ public:
      * be invalidated by the first call to a non-const method call
      * on the SBuf.
      * This call guarantees to never return NULL.
-     * This method can also be used to prepare the SBuf by preallocating a
-     * predefined amount of free space; this may help to optimize subsequent
-     * calls to SBuf::append or similar methods. In this case the returned
-     * pointer should be ignored.
+     * \see reserveSpace
+     * \note Unlike reserveSpace(), this method does not guarantee exclusive
+     *       buffer ownership. It is instead optimized for a one writer
+     *       (appender), many readers scenario by avoiding unnecessary
+     *       copying and allocations.
      * \throw SBufTooBigException if the user tries to allocate too big a SBuf
      */
     char *rawSpace(size_type minSize);
 
+    /**
+     *
+     */
+    size_type spaceSize() const { return store_->spaceSize(); }
+
     /** Force a SBuf's size
      * \warning use with EXTREME caution, this is a dangerous operation
      *
@@ -403,7 +409,7 @@ public:
      */
     bool isEmpty() const {return (len_==0);}
 
-    /** Request to extend the SBuf's free store space.
+    /** Request to guarantee the SBuf's free store space.
      *
      * After the reserveSpace request, the SBuf is guaranteed to have at
      * least minSpace bytes of unused backing store following the currently
@@ -412,7 +418,7 @@ public:
      */
     void reserveSpace(size_type minSpace) {reserveCapacity(length()+minSpace);}
 
-    /** Request to resize the SBuf's store capacity
+    /** Request to guarantee the SBuf's store capacity
      *
      * After this method is called, the SBuf is guaranteed to have at least
      * minCapacity bytes of total buffer size, including the currently-used
index 41cc334a3b2e045429207876cf8a8f451140e9f7..432093a6f12b382680bc32fbcc370c748aa13164 100644 (file)
@@ -201,7 +201,7 @@ testSBuf::testAppendf()
     SBuf s1,s2;
     s1.appendf("%s:%d:%03.2f",fox,1234,1234.56);
     s2.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
-    CPPUNIT_ASSERT_EQUAL(s1,s2);
+    CPPUNIT_ASSERT_EQUAL(s2,s1);
 }
 
 void