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);
44SBuf::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_));
#define Here()
source code location of the caller
InstanceIdDefinitions(SBuf, "SBuf")
static int memcasecmp(const char *b1, const char *b2, SBuf::size_type len)
#define Must3(condition, description, location)
optimized set of C chars, with quick membership test and merge support
const char * name
optional set label for debugging (default: "anonymous")
char * mem
raw allocated memory block
void append(const char *source, const size_type n)
void syncSize(const size_type n)
size_type size
maximum allocated memory in use by callers
void clear()
extends the available space to the entire allocated blob
bool canAppend(const size_type off, const size_type n) const
std::ostream & dump(std::ostream &os) const
dump debugging information
void consume(const size_type n)
size_type capacity
size of the raw allocated memory block
Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
bool allowShared
whether sharing our storage with others is OK
size_type minSpace
allocate [at least this much] if spaceSize() is smaller
size_type maxCapacity
do not allocate more than this
size_type idealSpace
if allocating anyway, provide this much space
uint64_t trim
number of trim operations
uint64_t append
number of append operations
uint64_t cowShift
number of cow() calls requiring just a memmove(3) inside an old buffer
uint64_t nulTerminate
number of c_str() terminations
uint64_t cowJustAlloc
number of cow() calls requiring just a new empty buffer
uint64_t rawAccess
number of accesses to raw contents
uint64_t assignFast
number of no-copy assignment operations
uint64_t cowAllocCopy
number of cow() calls requiring copying into a new buffer
uint64_t setChar
number of calls to setAt
uint64_t caseChange
number of toUpper and toLower operations
uint64_t cowAvoided
number of cow() calls requiring no expensive operations
uint64_t compareFast
number of comparison operations not requiring data scan
uint64_t chop
number of chop operations
uint64_t clear
number of clear operations
static void RecordSBufSizeAtDestruct(size_t)
Record the size a SBuf had when it was destructed.
uint64_t toStream
number of write operations to ostreams
uint64_t compareSlow
number of comparison operations requiring data scan
uint64_t allocCopy
number of calls to SBuf copy-constructor
uint64_t alloc
number of calls to SBuf constructors
uint64_t find
number of find operations
uint64_t live
number of currently-allocated SBuf
uint64_t copyOut
number of data-copies to other forms of buffers
uint64_t allocFromCString
number of copy-allocations from c-strings
char * rawAppendStart(size_type anticipatedSize)
void toUpper()
converts all characters to upper case;
const char * rawContent() const
static const size_type npos
SBuf consume(size_type n=npos)
SBuf & vappendf(const char *fmt, va_list vargs)
SBuf & chop(size_type pos, size_type n=npos)
void reserveCapacity(size_type minCapacity)
size_type len_
number of our content bytes in shared store_
static const SBufStats & GetStats()
gets global statistic information
static MemBlob::Pointer GetStorePrototype()
SBuf & lowAppend(const char *memArea, size_type areaSize)
const InstanceId< SBuf > id
void reAlloc(size_type newsize)
size_type length() const
Returns the number of bytes stored in SBuf.
static SBufStats stats
class-wide statistics
SBuf & appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
SBuf()
create an empty (zero-size) SBuf
size_type rfind(char c, size_type endPos=npos) const
size_type reserve(const SBufReservationRequirements &requirements)
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
SBuf & trim(const SBuf &toRemove, bool atBeginning=true, bool atEnd=true)
size_type spaceSize() const
size_type find(char c, size_type startPos=0) const
size_type findFirstOf(const CharacterSet &set, size_type startPos=0) const
bool operator!=(const SBuf &S) const
size_type copy(char *dest, size_type n) const
bool operator==(const SBuf &S) const
size_type findLastNotOf(const CharacterSet &set, size_type endPos=npos) const
char * rawSpace(size_type minSize)
std::ostream & dump(std::ostream &os) const
void cow(size_type minsize=npos)
void checkAccessBounds(const size_type pos) const
SBuf & append(const SBuf &S)
MemBlob::Pointer store_
memory block, possibly shared with other SBufs
size_type findLastOf(const CharacterSet &set, size_type endPos=npos) const
size_type off_
our content start offset from the beginning of shared store_
bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive=caseSensitive) const
SBuf substr(size_type pos, size_type n=npos) const
std::ostream & print(std::ostream &os) const
print the SBuf contents to the supplied ostream
MemBlob::size_type size_type
void rawAppendFinish(const char *start, size_type actualSize)
SBuf & assign(const SBuf &S)
void setAt(size_type pos, char toset)
void toLower()
converts all characters to lower case;
int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const
static const size_type maxSize
Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
void * memrchr(const void *s, int c, size_t n)