Go to the documentation of this file.
   30     debugs(24, 8, 
id << 
" created");
 
   36     : store_(S.store_), off_(S.off_), len_(S.len_)
 
   38     debugs(24, 8, 
id << 
" created from id " << S.
id);
 
   44 SBuf::SBuf(
const std::string &s) : store_(GetStorePrototype())
 
   46     debugs(24, 8, 
id << 
" created from std::string");
 
   70     debugs(24, 8, 
id << 
" destructed");
 
   85     debugs(24, 7, 
"assigning " << 
id << 
" from " <<  S.
id);
 
   98     const Locker blobKeeper(
this, S);
 
   99     debugs(24, 6, 
id << 
" from c-string, n=" << n << 
")");
 
  138     char *space = 
rawSpace(anticipatedSize);
 
  139     debugs(24, 8, 
id << 
" start appending up to " << anticipatedSize << 
" bytes");
 
  148     debugs(24, 8, 
id << 
" finish appending " << actualSize << 
" bytes");
 
  160     debugs(24, 7, 
"reserving " << minSpace << 
" for " << 
id);
 
  167         debugs(24, 7, 
id << 
" not growing");
 
  177     if (
store_->LockCount() == 1)
 
  197     const Locker blobKeeper(
this, S);
 
  202     debugs(24, 7, 
"from c-string to id " << 
id);
 
  244     Must(fmt != 
nullptr);
 
  247     size_type requiredSpaceEstimate = strlen(fmt)*2;
 
  249     char *space = 
rawSpace(requiredSpaceEstimate);
 
  252     sz = vsnprintf(space, 
spaceSize(), fmt, ap);
 
  254     Must3(sz >= 0, 
"vsnprintf() succeeds", 
Here());
 
  261     if (sz >= 
static_cast<int>(
spaceSize())) {
 
  263         requiredSpaceEstimate = sz*2; 
 
  264         space = 
rawSpace(requiredSpaceEstimate);
 
  265         sz = vsnprintf(space, 
spaceSize(), fmt, vargs);
 
  266         Must3(sz >= 0, 
"vsnprintf() succeeds (with increased buffer space)", 
Here());
 
  275     static bool snPrintfTerminatorChecked = 
false;
 
  276     static bool snPrintfTerminatorCounted = 
false;
 
  277     if (!snPrintfTerminatorChecked) {
 
  279         snPrintfTerminatorCounted = snprintf(testbuf, 
sizeof(testbuf),
 
  281         snPrintfTerminatorChecked = 
true;
 
  283     if (snPrintfTerminatorCounted) {
 
  308     os << 
", offset:" << 
off_ 
  312     os << 
'\'' << std::endl;
 
  318        ", offset:" << 
off_ <<
 
  341         rv = tolower(*b1)-tolower(*b2);
 
  355         debugs(24, 8, 
"length specified. substr and recurse");
 
  362     debugs(24, 8, 
"comparing length " << byteCompareLen);
 
  364         rv = memcmp(
buf(), S.
buf(), byteCompareLen);
 
  369         debugs(24, 8, 
"result: " << rv);
 
  373         debugs(24, 8, 
"same contents and bounded length. Equal");
 
  377         debugs(24, 8, 
"same contents and same length. Equal");
 
  381         debugs(24, 8, 
"lhs is longer than rhs. Result is 1");
 
  384     debugs(24, 8, 
"rhs is longer than lhs. Result is -1");
 
  408     const char *left = 
buf();
 
  409     const char *right = s;
 
  417         while ((rv = *left - *right++) == 0) {
 
  418             if (*left++ == 
'\0' || --byteCount == 0)
 
  422         while ((rv = tolower(*left) - tolower(*right++)) == 0) {
 
  423             if (*left++ == 
'\0' || --byteCount == 0)
 
  432     if (!byteCount && 
length() < n)
 
  433         return '\0' - *right;
 
  444     debugs(24, 8, 
id << 
" startsWith " << S.
id << 
", caseSensitive: " <<
 
  447         debugs(24, 8, 
"no, too short");
 
  457     debugs(24, 8, 
id << 
" == " << S.
id);
 
  459         debugs(24, 8, 
"no, different lengths");
 
  464         debugs(24, 8, 
"yes, same length and backing store");
 
  469     const bool rv = (0 == memcmp(
buf(), S.
buf(), 
length()));
 
  470     debugs(24, 8, 
"returning " << rv);
 
  477     return !(*
this == S);
 
  487     debugs(24, 8, 
id << 
" consume " << n);
 
  503     memcpy(dest, 
buf(), toexport);
 
  539     if (pos == 
length() || n == 0) {
 
  555         const char *p = 
bufEnd()-1;
 
  556         while (!
isEmpty() && memchr(toRemove.
buf(), *p, toRemove.
length()) != 
nullptr) {
 
  563         const char *p = 
buf();
 
  564         while (!
isEmpty() && memchr(toRemove.
buf(), *p, toRemove.
length()) != 
nullptr) {
 
  588     if (startPos == 
npos) 
 
  600     return (
static_cast<const char *
>(i)-
buf());
 
  606     if (startPos == 
npos) { 
 
  612     if (startPos > 
length()) {
 
  618     if (needle.
length() == 0) {
 
  625         return find(needle[0], startPos);
 
  629     char *start = 
buf()+startPos;
 
  631     char needleBegin = needle[0];
 
  633     debugs(24, 7, 
"looking for " << needle << 
"starting at " << startPos <<
 
  635     while (start < lastPossible) {
 
  637         debugs(24, 8, 
" begin=" << (
void *) start <<
 
  638                ", lastPossible=" << (
void*) lastPossible );
 
  639         tmp = 
static_cast<char *
>(memchr(start, needleBegin, lastPossible-start));
 
  640         if (tmp == 
nullptr) {
 
  641             debugs(24, 8, 
"First byte not found");
 
  645         if (0 == memcmp(needle.
buf(), tmp, needle.
length())) {
 
  646             debugs(24, 8, 
"Found at " << (tmp-
buf()));
 
  651     debugs(24, 8, 
"not found");
 
  660         return rfind(needle[0], endPos);
 
  676     char *bufBegin = 
buf();
 
  677     char *
cur = bufBegin+endPos;
 
  678     const char needleBegin = needle[0];
 
  679     while (
cur >= bufBegin) {
 
  680         if (*
cur == needleBegin) {
 
  719     return (
static_cast<const char *
>(i)-
buf());
 
  727     if (startPos == 
npos)
 
  733     debugs(24, 7, 
"first of characterset " << set.
name << 
" in id " << 
id);
 
  734     char *
cur = 
buf()+startPos;
 
  735     const char *bufend = 
bufEnd();
 
  736     while (
cur < bufend) {
 
  741     debugs(24, 7, 
"not found");
 
  750     if (startPos == 
npos)
 
  756     debugs(24, 7, 
"first not of characterset " << set.
name << 
" in id " << 
id);
 
  757     char *
cur = 
buf()+startPos;
 
  758     const char *bufend = 
bufEnd();
 
  759     while (
cur < bufend) {
 
  764     debugs(24, 7, 
"not found");
 
  779     debugs(24, 7, 
"last of characterset " << set.
name << 
" in id " << 
id);
 
  780     const char *start = 
buf();
 
  781     for (
const char *
cur = start + endPos; 
cur >= start; --
cur) {
 
  785     debugs(24, 7, 
"not found");
 
  800     debugs(24, 7, 
"last not of characterset " << set.
name << 
" in id " << 
id);
 
  801     const char *start = 
buf();
 
  802     for (
const char *
cur = start + endPos; 
cur >= start; --
cur) {
 
  806     debugs(24, 7, 
"not found");
 
  813     debugs(24, 8, 
"\"" << *
this << 
"\"");
 
  815         const int c = (*this)[j];
 
  817             setAt(j, tolower(c));
 
  819     debugs(24, 8, 
"result: \"" << *
this << 
"\"");
 
  826     debugs(24, 8, 
"\"" << *
this << 
"\"");
 
  828         const int c = (*this)[j];
 
  830             setAt(j, toupper(c));
 
  832     debugs(24, 8, 
"result: \"" << *
this << 
"\"");
 
  847     debugs(24, 8, 
id << 
" new size: " << newsize);
 
  880     debugs(24, 8, 
id << 
" new size:" << newsize);
 
  884     if (
store_->LockCount() == 1) {
 
  889         const auto neededSpace = newsize - 
length();
 
  890         if (neededSpace <= availableSpace) {
 
  891             debugs(24, 8, 
id << 
" no cow needed; have " << availableSpace);
 
  897         if (neededSpace <= availableSpace + 
off_) {
 
  898             debugs(24, 8, 
id << 
" no cow after shifting " << 
off_ << 
" to get " << (availableSpace + 
off_));
 
  
void syncSize(const size_type n)
void * memrchr(const void *s, int c, size_t n)
size_type find(char c, size_type startPos=0) const
#define Here()
source code location of the caller
void push_back(char)
Append a single character. The character may be NUL (\0).
const char * name
optional set label for debugging (default: "anonymous")
size_type idealSpace
if allocating anyway, provide this much space
SBuf & assign(const SBuf &S)
uint64_t toStream
number of write operations to ostreams
uint64_t alloc
number of calls to SBuf constructors
uint64_t chop
number of chop operations
size_type len_
number of our content bytes in shared store_
void checkAccessBounds(const size_type pos) const
static MemBlob::Pointer GetStorePrototype()
SBuf & lowAppend(const char *memArea, size_type areaSize)
uint64_t compareFast
number of comparison operations not requiring data scan
SBuf & vappendf(const char *fmt, va_list vargs)
size_type maxCapacity
do not allocate more than this
void append(const_pointer source, const size_type n)
size_type size
maximum allocated memory in use by callers
int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const
Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
const A & max(A const &lhs, A const &rhs)
void rawAppendFinish(const char *start, size_type actualSize)
bool operator==(const SBuf &S) const
uint64_t live
number of currently-allocated SBuf
char * rawSpace(size_type minSize)
size_type spaceSize() const
bool canAppend(const size_type off, const size_type n) const
void toLower()
converts all characters to lower case;
bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive=caseSensitive) const
bool allowShared
whether sharing our storage with others is OK
value_type * mem
raw allocated memory block
#define Must3(condition, description, location)
static const size_type maxSize
Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
SBuf substr(size_type pos, size_type n=npos) const
InstanceIdDefinitions(SBuf, "SBuf")
size_type reserve(const SBufReservationRequirements &requirements)
SBuf & chop(size_type pos, size_type n=npos)
char * rawAppendStart(size_type anticipatedSize)
size_type rfind(char c, size_type endPos=npos) const
uint64_t append
number of append operations
void toUpper()
converts all characters to upper case;
static int memcasecmp(const char *b1, const char *b2, SBuf::size_type len)
const char * rawContent() const
SBuf consume(size_type n=npos)
MemBlob::size_type size_type
uint64_t trim
number of trim operations
std::ostream & dump(std::ostream &os) const
uint64_t cowShift
number of cow() calls requiring just a memmove(3) inside an old buffer
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
SBuf()
create an empty (zero-size) SBuf
uint64_t assignFast
number of no-copy assignment operations
uint64_t nulTerminate
number of c_str() terminations
std::ostream & print(std::ostream &os) const
print the SBuf contents to the supplied ostream
void cow(size_type minsize=npos)
SBuf & trim(const SBuf &toRemove, bool atBeginning=true, bool atEnd=true)
size_type length() const
Returns the number of bytes stored in SBuf.
size_type off_
our content start offset from the beginning of shared store_
static SBufStats stats
class-wide statistics
SBuf & append(const SBuf &S)
size_type findLastOf(const CharacterSet &set, size_type endPos=npos) const
uint64_t rawAccess
number of accesses to raw contents
static const size_type npos
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
size_type minSpace
allocate [at least this much] if spaceSize() is smaller
void setAt(size_type pos, char toset)
uint64_t cowJustAlloc
number of cow() calls requiring just a new empty buffer
MemBlob::Pointer store_
memory block, possibly shared with other SBufs
size_type capacity
size of the raw allocated memory block
uint64_t cowAvoided
number of cow() calls requiring no expensive operations
void reserveCapacity(size_type minCapacity)
static const SBufStats & GetStats()
gets global statistic information
void reAlloc(size_type newsize)
uint64_t caseChange
number of toUpper and toLower operations
uint64_t find
number of find operations
bool operator!=(const SBuf &S) const
std::ostream & dump(std::ostream &os) const
dump debugging information
uint64_t clear
number of clear operations
uint64_t cowAllocCopy
number of cow() calls requiring copying into a new buffer
size_type findLastNotOf(const CharacterSet &set, size_type endPos=npos) const
optimized set of C chars, with quick membership test and merge support
void consume(const size_type n)
SBuf & appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
uint64_t allocCopy
number of calls to SBuf copy-constructor
uint64_t allocFromCString
number of copy-allocations from c-strings
const InstanceId< SBuf > id
size_type findFirstOf(const CharacterSet &set, size_type startPos=0) const
#define debugs(SECTION, LEVEL, CONTENT)
const A & min(A const &lhs, A const &rhs)
uint64_t compareSlow
number of comparison operations requiring data scan
uint64_t setChar
number of calls to setAt
size_type copy(char *dest, size_type n) const
static void RecordSBufSizeAtDestruct(size_t)
Record the size a SBuf had when it was destructed.
uint64_t copyOut
number of data-copies to other forms of buffers