]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/sbuf/SBuf.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / sbuf / SBuf.h
index b0aa872d2898e08b0b7c099364724ffbba8a7d31..74b6eef3a7cb1d9cc37dec9d53f5df5f9a3be771 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
 #define SQUID_SBUF_H
 
 #include "base/InstanceId.h"
+#include "base/TextException.h"
 #include "Debug.h"
 #include "globals.h"
+#include "sbuf/forward.h"
 #include "sbuf/MemBlob.h"
 #include "sbuf/Stats.h"
-#include "SBufExceptions.h"
 
 #include <climits>
-#include <cstdarg>
 #include <iosfwd>
 #include <iterator>
 #if HAVE_UNISTD_H
@@ -39,7 +39,6 @@ typedef enum {
 } SBufCaseSensitive;
 
 class CharacterSet;
-class SBuf;
 
 /** Forward input const_iterator for SBufs
  *
@@ -60,7 +59,7 @@ public:
 protected:
     SBufIterator(const SBuf &, size_type);
 
-    const char *iter;
+    const char *iter = nullptr;
 };
 
 /** Reverse input const_iterator for SBufs
@@ -98,14 +97,11 @@ public:
     /// create an empty (zero-size) SBuf
     SBuf();
     SBuf(const SBuf &S);
-#if __cplusplus >= 201103L
     SBuf(SBuf&& S) : store_(std::move(S.store_)), off_(S.off_), len_(S.len_) {
         ++stats.moves;
-        S.store_=NULL; //RefCount supports NULL, and S is about to be destructed
-        S.off_=0;
-        S.len_=0;
+        S.store_ = nullptr; //RefCount supports nullptr, and S is about to be destructed
+        S.off_ = S.len_ = 0;
     }
-#endif
 
     /** Constructor: import c-style string
      *
@@ -136,7 +132,6 @@ public:
      * Current SBuf will share backing store with the assigned one.
      */
     SBuf& operator =(const SBuf & S) {return assign(S);}
-#if __cplusplus >= 201103L
     SBuf& operator =(SBuf &&S) {
         ++stats.moves;
         if (this != &S) {
@@ -149,7 +144,6 @@ public:
         }
         return *this;
     }
-#endif
 
     /** Import a c-string into a SBuf, copying the data.
      *
@@ -225,7 +219,7 @@ public:
 
     /** print SBuf contents and debug information about the SBuf to an ostream
      *
-     * Debug function, dumps to a stream informations on the current SBuf,
+     * Debug function, dumps to a stream information on the current SBuf,
      * including low-level details and statistics.
      */
     std::ostream& dump(std::ostream &os) const;
@@ -238,7 +232,7 @@ public:
 
     /** random-access read to any char within the SBuf.
      *
-     * \throw OutOfBoundsException when access is out of bounds
+     * \throw std::exception when access is out of bounds
      * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
      */
     char at(size_type pos) const {checkAccessBounds(pos); return operator[](pos);}
@@ -247,7 +241,7 @@ public:
      *
      * \param pos the position to be overwritten
      * \param toset the value to be written
-     * \throw OutOfBoundsException when pos is of bounds
+     * \throw std::exception when pos is of bounds
      * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
      * \note performs a copy-on-write if needed.
      */
@@ -329,7 +323,7 @@ public:
      */
     SBuf consume(size_type n = npos);
 
-    /// gets global statistic informations
+    /// gets global statistic information
     static const SBufStats& GetStats();
 
     /** Copy SBuf contents into user-supplied C buffer.
@@ -367,24 +361,18 @@ public:
      */
     const char* rawContent() const;
 
-    /** Exports a writable pointer to the SBuf internal storage.
-     * \warning Use with EXTREME caution, this is a dangerous operation.
-     *
-     * Returns a pointer to the first unused byte in the SBuf's storage,
-     * which can be be used for appending. At least minSize bytes will
-     * be available for writing.
-     * The returned pointer must not be stored by the caller, as it will
-     * be invalidated by the first call to a non-const method call
-     * on the SBuf.
-     * This call guarantees to never return NULL.
-     * \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);
+    /// \returns a buffer suitable for appending at most `anticipatedSize` bytes
+    /// The buffer must be used "immediately" because it is invalidated by most
+    /// non-constant SBuf method calls, including such calls against other SBuf
+    /// objects that just happen to share the same underlying MemBlob storage!
+    char *rawAppendStart(size_type anticipatedSize);
+
+    /// Updates SBuf metadata to reflect appending `actualSize` bytes to the
+    /// buffer returned by the corresponding rawAppendStart() call. Throws if
+    /// rawAppendStart(actualSize) would have returned a different value now.
+    /// \param start raw buffer previously returned by rawAppendStart()
+    /// \param actualSize the number of appended bytes
+    void rawAppendFinish(const char *start, size_type actualSize);
 
     /** Obtain how much free space is available in the backing store.
      *
@@ -393,16 +381,6 @@ public:
      */
     size_type spaceSize() const { return store_->spaceSize(); }
 
-    /** Force a SBuf's size
-     * \warning use with EXTREME caution, this is a dangerous operation
-     *
-     * Adapt the SBuf internal state after external interference
-     * such as writing into it via rawSpace.
-     * \throw TextException if SBuf doesn't have exclusive ownership of store
-     * \throw SBufTooBigException if new size is bigger than available store space
-     */
-    void forceSize(size_type newSize);
-
     /** exports a null-terminated reference to the SBuf internal storage.
      * \warning ACCESSING RAW STORAGE IS DANGEROUS! DO NOT EVER USE
      *  THE RETURNED POINTER FOR WRITING
@@ -428,11 +406,10 @@ public:
     /** Get the length of the SBuf, as a signed integer
      *
      * Compatibility function for printf(3) which requires a signed int
-     * \throw SBufTooBigException if the SBuf is too big for a signed integer
+     * \throw std::exception if buffer length does not fit a signed integer
      */
     int plength() const {
-        if (length()>INT_MAX)
-            throw SBufTooBigException(__FILE__, __LINE__);
+        Must(length() <= INT_MAX);
         return static_cast<int>(length());
     }
 
@@ -447,7 +424,7 @@ public:
      * After the reserveSpace request, the SBuf is guaranteed to have at
      * least minSpace bytes of unused backing store following the currently
      * used portion and single ownership of the backing store.
-     * \throw SBufTooBigException if the user tries to allocate too big a SBuf
+     * \throw std::exception if the user tries to allocate a too big SBuf
      */
     void reserveSpace(size_type minSpace) {
         Must(minSpace <= maxSize);
@@ -461,10 +438,16 @@ public:
      * minCapacity bytes of total buffer size, including the currently-used
      * portion; it is also guaranteed that after this call this SBuf
      * has unique ownership of the underlying memory store.
-     * \throw SBufTooBigException if the user tries to allocate too big a SBuf
+     * \throw std::exception if the user tries to allocate a too big SBuf
      */
     void reserveCapacity(size_type minCapacity);
 
+    /** Accommodate caller's requirements regarding SBuf's storage if possible.
+     *
+     * \return spaceSize(), which may be zero
+     */
+    size_type reserve(const SBufReservationRequirements &requirements);
+
     /** slicing method
      *
      * Removes SBuf prefix and suffix, leaving a sequence of 'n'
@@ -577,14 +560,6 @@ public:
      */
     size_type findLastNotOf(const CharacterSet &set, size_type endPos = npos) const;
 
-    /** sscanf-alike
-     *
-     * sscanf re-implementation. Non-const, and not \0-clean.
-     * \return same as sscanf
-     * \see man sscanf(3)
-     */
-    int scanf(const char *format, ...);
-
     /// converts all characters to lower case; \see man tolower(3)
     void toLower();
 
@@ -612,6 +587,11 @@ public:
 
     // TODO: possibly implement erase() similar to std::string's erase
     // TODO: possibly implement a replace() call
+
+    /// SBuf object identifier meant for test cases and debugging.
+    /// Does not change when object does, including during assignment.
+    const InstanceId<SBuf> id;
+
 private:
 
     /**
@@ -636,14 +616,10 @@ private:
     friend class Locker;
 
     MemBlob::Pointer store_; ///< memory block, possibly shared with other SBufs
-    size_type off_; ///< our content start offset from the beginning of shared store_
-    size_type len_; ///< number of our content bytes in shared store_
+    size_type off_ = 0; ///< our content start offset from the beginning of shared store_
+    size_type len_ = 0; ///< number of our content bytes in shared store_
     static SBufStats stats; ///< class-wide statistics
 
-    /// SBuf object identifier; does not change when contents do,
-    ///   including during assignment
-    const InstanceId<SBuf> id;
-
     /** obtain prototype store
      *
      * Just-created SBufs all share to the same MemBlob.
@@ -666,7 +642,7 @@ private:
 
     /**
      * Try to guesstimate how big a MemBlob to allocate.
-     * The result is guarranteed to be to be at least the desired size.
+     * The result is guaranteed to be to be at least the desired size.
      */
     size_type estimateCapacity(size_type desired) const {return (2*desired);}
 
@@ -674,7 +650,26 @@ private:
 
     void cow(size_type minsize = npos);
 
-    void checkAccessBounds(size_type pos) const;
+    void checkAccessBounds(const size_type pos) const { Must(pos < length()); }
+
+    /** Exports a writable pointer to the SBuf internal storage.
+     * \warning Use with EXTREME caution, this is a dangerous operation.
+     *
+     * Returns a pointer to the first unused byte in the SBuf's storage,
+     * which can be be used for appending. At least minSize bytes will
+     * be available for writing.
+     * The returned pointer must not be stored by the caller, as it will
+     * be invalidated by the first call to a non-const method call
+     * on the SBuf.
+     * This call guarantees to never return nullptr.
+     * \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 std::exception if the user tries to allocate a too big SBuf
+     */
+    char *rawSpace(size_type minSize);
 
     /** Low-level append operation
      *
@@ -686,6 +681,23 @@ private:
     SBuf& lowAppend(const char * memArea, size_type areaSize);
 };
 
+/// Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
+class SBufReservationRequirements
+{
+public:
+    typedef SBuf::size_type size_type;
+
+    /*
+     * Parameters are listed in the reverse order of importance: Satisfaction of
+     * the lower-listed requirements may violate the higher-listed requirements.
+     * For example, idealSpace has no effect unless it exceeds minSpace.
+     */
+    size_type idealSpace = 0; ///< if allocating anyway, provide this much space
+    size_type minSpace = 0; ///< allocate [at least this much] if spaceSize() is smaller
+    size_type maxCapacity = SBuf::maxSize; ///< do not allocate more than this
+    bool allowShared = true; ///< whether sharing our storage with others is OK
+};
+
 /// ostream output operator
 inline std::ostream &
 operator <<(std::ostream& os, const SBuf& S)