Hi all,
the attached patch is a proposal for a couple of small extensions to
SBuf, which are meant to make it more API-compatible with std::string.
- it adds a "fill" operator: append(size_type n, char c)
- it aliases append(char) to push_back(char)
- it aliases reserveCapacity to reserve
Also a small fix:
- it marks the const begin() and end() methods as such
It is debateable whether reserveCapacity should be just renamed
instead of aliased; feedback is welcome.
The objective of this change will be clear in the followup rfc3986
patch, which is templatized in order to be available both to helpers
who use std::string and to squid using SBuf.
--
Francesco
=== modified file 'src/SBuf.cc'
--- src/SBuf.cc 2015-10-29 23:08:05 +0000
+++ src/SBuf.cc 2015-12-20 18:28:01 +0000
@@ -221,40 +221,49 @@ SBuf::append(const SBuf &S)
SBuf &
SBuf::append(const char * S, size_type Ssize)
{
const Locker blobKeeper(this, S);
if (S == NULL)
return *this;
if (Ssize == SBuf::npos)
Ssize = strlen(S);
debugs(24, 7, "from c-string to id " << id);
// coverity[access_dbuff_in_call]
return lowAppend(S, Ssize);
}
SBuf &
SBuf::append(const char c)
{
return lowAppend(&c, 1);
}
SBuf&
+SBuf::append(size_type n, const char c)
+{
+ reserveSpace(n);
+ for (size_type j = 0; j < n; ++j)
+ lowAppend(&c, 1);
+ return *this;
+}
+
+SBuf&
SBuf::Printf(const char *fmt, ...)
{
// with printf() the fmt or an arg might be a dangerous char*
// NP: cant rely on vappendf() Locker because of clear()
const Locker blobKeeper(this, buf());
va_list args;
va_start(args, fmt);
clear();
vappendf(fmt, args);
va_end(args);
return *this;
}
SBuf&
SBuf::appendf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vappendf(fmt, args);
=== modified file 'src/SBuf.h'
--- src/SBuf.h 2015-11-18 05:46:36 +0000
+++ src/SBuf.h 2015-12-28 11:25:13 +0000
@@ -217,40 +217,44 @@ public:
* Copy a c-style string into a SBuf. Shortcut for SBuf.assign(S)
* It is the caller's duty to free the imported string, if needed.
* \note not \0-clean
*/
SBuf& operator =(const char *S) {return assign(S);}
/** reset the SBuf as if it was just created.
*
* Resets the SBuf to empty, memory is freed lazily.
*/
void clear();
/** Append operation
*
* Append the supplied SBuf to the current one; extend storage as needed.
*/
SBuf& append(const SBuf & S);
/// Append a single character. The character may be NUL (\0).
SBuf& append(const char c);
+ SBuf& push_back(const char c) { return append(c); }
+
+ /// Append n consecutive copies of c
+ SBuf& append(size_type n, const char c);
/** Append operation for C-style strings.
*
* Append the supplied c-string to the SBuf; extend storage
* as needed.
*
* \param S the c string to be copied. Can be NULL.
* \param Ssize how many bytes to import into the SBuf. If it is npos
* or unspecified, imports to end-of-cstring. If S is NULL,
* Ssize is ignored.
* \note to append a std::string use the pattern
* cstr_append(stdstr.data(), stdstd.length())
*/
SBuf& append(const char * S, size_type Ssize);
SBuf& append(const char * S) { return append(S,npos); }
/** Assignment operation with printf(3)-style definition
* \note arguments may be evaluated more than once, be careful
* of side-effects
*/
@@ -495,40 +499,42 @@ 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
*/
void reserveSpace(size_type minSpace) {
Must(minSpace <= maxSize);
Must(length() <= maxSize - minSpace);
reserveCapacity(length()+minSpace);
}
/** 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
* 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
*/
void reserveCapacity(size_type minCapacity);
+ // API-compatibility with std::string
+ void reserve(size_type minCapacity) { reserveCapacity(minCapacity); }
/** slicing method
*
* Removes SBuf prefix and suffix, leaving a sequence of 'n'
* bytes starting from position 'pos', first byte is at pos 0.
* It is an in-place-modifying version of substr.
* \param pos start sub-stringing from this byte. If it is
* npos or it is greater than the SBuf length, the SBuf is cleared and
* an empty SBuf is returned.
* \param n maximum number of bytes of the resulting SBuf.
* npos means "to end of SBuf".
* if it is 0, the SBuf is cleared and an empty SBuf is returned.
* if it overflows the end of the SBuf, it is capped to the end of SBuf
* \see substr, trim
*/
SBuf& chop(size_type pos, size_type n = npos);
/** Remove characters in the toremove set at the beginning, end or both
*
* \param toremove characters to be removed. Stops chomping at the first
@@ -631,53 +637,53 @@ public:
* \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();
/// converts all characters to upper case; \see man toupper(3)
void toUpper();
/** String export function
* converts the SBuf to a legacy String, by copy.
* \deprecated
*/
String toString() const;
/// std::string export function
std::string toStdString() const { return std::string(buf(),length()); }
- iterator begin() {
+ iterator begin() const {
return iterator(*this, 0);
}
- iterator end() {
+ iterator end() const {
return iterator(*this, length());
}
- reverse_iterator rbegin() {
+ reverse_iterator rbegin() const {
return reverse_iterator(*this, length());
}
- reverse_iterator rend() {
+ reverse_iterator rend() const {
return reverse_iterator(*this, 0);
}
// TODO: possibly implement erase() similar to std::string's erase
// TODO: possibly implement a replace() call
private:
/**
* Keeps SBuf's MemBlob alive in a blob-destroying context where
* a seemingly unrelated memory pointer may belong to the same blob.
* For [an extreme] example, consider: a.append(a).
* Compared to an SBuf temporary, this class is optimized to
* preserve blobs only if needed and to reduce debugging noise.
*/
class Locker
{
public:
Locker(SBuf *parent, const char *otherBuffer) {
// lock if otherBuffer intersects the parents buffer area
const MemBlob *blob = parent->store_.getRaw();
_______________________________________________
squid-dev mailing list
[email protected]
http://lists.squid-cache.org/listinfo/squid-dev