SBuf.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "base/CharacterSet.h"
11#include "base/Raw.h"
12#include "base/RefCount.h"
13#include "debug/Stream.h"
14#include "sbuf/SBuf.h"
15#include "util.h"
16
17#include <cstring>
18#include <functional>
19#include <iostream>
20#include <sstream>
21
23
27
28SBuf::SBuf() : store_(GetStorePrototype())
29{
30 debugs(24, 8, id << " created");
31 ++stats.alloc;
32 ++stats.live;
33}
34
36 : store_(S.store_), off_(S.off_), len_(S.len_)
37{
38 debugs(24, 8, id << " created from id " << S.id);
39 ++stats.alloc;
41 ++stats.live;
42}
43
44SBuf::SBuf(const std::string &s) : store_(GetStorePrototype())
45{
46 debugs(24, 8, id << " created from std::string");
47 lowAppend(s.data(),s.length());
48 ++stats.alloc;
49 ++stats.live;
50}
51
52SBuf::SBuf(const char *S, size_type n) : store_(GetStorePrototype())
53{
54 append(S,n);
55 ++stats.alloc;
57 ++stats.live;
58}
59
60SBuf::SBuf(const char *S) : store_(GetStorePrototype())
61{
62 append(S,npos);
63 ++stats.alloc;
65 ++stats.live;
66}
67
69{
70 debugs(24, 8, id << " destructed");
71 --stats.live;
73}
74
77{
78 static MemBlob::Pointer InitialStore = new MemBlob(0);
79 return InitialStore;
80}
81
82SBuf&
84{
85 debugs(24, 7, "assigning " << id << " from " << S.id);
86 if (&S == this) //assignment to self. Noop.
87 return *this;
89 store_ = S.store_;
90 off_ = S.off_;
91 len_ = S.len_;
92 return *this;
93}
94
95SBuf&
96SBuf::assign(const char *S, size_type n)
97{
98 const Locker blobKeeper(this, S);
99 debugs(24, 6, id << " from c-string, n=" << n << ")");
100 clear();
101 return append(S, n); //bounds checked in append()
102}
103
104void
106{
107 Must(minCapacity <= maxSize);
108 cow(minCapacity);
109}
110
113{
114 debugs(24, 8, id << " was: " << off_ << '+' << len_ << '+' << spaceSize() <<
115 '=' << store_->capacity);
116
117 const bool mustRealloc = !req.allowShared && store_->LockCount() > 1;
118
119 if (!mustRealloc && spaceSize() >= req.minSpace)
120 return spaceSize(); // the caller is content with what we have
121
122 /* only reallocation can make the caller happy */
123
124 if (!mustRealloc && len_ >= req.maxCapacity)
125 return spaceSize(); // but we cannot reallocate
126
127 const size_type desiredSpace = std::max(req.minSpace, req.idealSpace);
128 const size_type newSpace = std::min(desiredSpace, maxSize - len_);
129 reserveCapacity(std::min(len_ + newSpace, req.maxCapacity));
130 debugs(24, 7, id << " now: " << off_ << '+' << len_ << '+' << spaceSize() <<
131 '=' << store_->capacity);
132 return spaceSize(); // reallocated and probably reserved enough space
133}
134
135char *
137{
138 char *space = rawSpace(anticipatedSize);
139 debugs(24, 8, id << " start appending up to " << anticipatedSize << " bytes");
140 return space;
141}
142
143void
144SBuf::rawAppendFinish(const char *start, size_type actualSize)
145{
146 Must(bufEnd() == start);
147 Must(store_->canAppend(off_ + len_, actualSize));
148 debugs(24, 8, id << " finish appending " << actualSize << " bytes");
149
150 size_type newSize = length() + actualSize;
151 Must3(newSize <= min(maxSize, store_->capacity-off_), "raw append fits", Here());
152 len_ = newSize;
153 store_->size = off_ + newSize;
154}
155
156char *
158{
159 Must(length() <= maxSize - minSpace);
160 debugs(24, 7, "reserving " << minSpace << " for " << id);
162 // we're not concerned about RefCounts here,
163 // the store knows the last-used portion. If
164 // it's available, we're effectively claiming ownership
165 // of it. If it's not, we need to go away (realloc)
166 if (store_->canAppend(off_+len_, minSpace)) {
167 debugs(24, 7, id << " not growing");
168 return bufEnd();
169 }
170 cow(minSpace+length());
171 return bufEnd();
172}
173
174void
176{
177 if (store_->LockCount() == 1)
178 store_->clear();
179 len_ = 0;
180 off_ = 0;
181 ++stats.clear;
182}
183
184SBuf&
186{
187 if (isEmpty() && store_ == GetStorePrototype())
188 return (*this = S); // optimization: avoid needless copying
189
190 const Locker blobKeeper(this, S.buf());
191 return lowAppend(S.buf(), S.length());
192}
193
194SBuf &
195SBuf::append(const char * S, size_type Ssize)
196{
197 const Locker blobKeeper(this, S);
198 if (S == nullptr)
199 return *this;
200 if (Ssize == SBuf::npos)
201 Ssize = strlen(S);
202 debugs(24, 7, "from c-string to id " << id);
203 // coverity[access_dbuff_in_call]
204 return lowAppend(S, Ssize);
205}
206
207SBuf &
208SBuf::append(const char c)
209{
210 return lowAppend(&c, 1);
211}
212
213SBuf&
214SBuf::Printf(const char *fmt, ...)
215{
216 // with printf() the fmt or an arg might be a dangerous char*
217 // NP: can't rely on vappendf() Locker because of clear()
218 const Locker blobKeeper(this, buf());
219
220 va_list args;
221 va_start(args, fmt);
222 clear();
223 vappendf(fmt, args);
224 va_end(args);
225 return *this;
226}
227
228SBuf&
229SBuf::appendf(const char *fmt, ...)
230{
231 va_list args;
232 va_start(args, fmt);
233 vappendf(fmt, args);
234 va_end(args);
235 return *this;
236}
237
238SBuf&
239SBuf::vappendf(const char *fmt, va_list vargs)
240{
241 // with (v)appendf() the fmt or an arg might be a dangerous char*
242 const Locker blobKeeper(this, buf());
243
244 Must(fmt != nullptr);
245 int sz = 0;
246 //reserve twice the format-string size, it's a likely heuristic
247 size_type requiredSpaceEstimate = strlen(fmt)*2;
248
249 char *space = rawSpace(requiredSpaceEstimate);
250 va_list ap;
251 va_copy(ap, vargs);
252 sz = vsnprintf(space, spaceSize(), fmt, ap);
253 va_end(ap);
254 Must3(sz >= 0, "vsnprintf() succeeds", Here());
255
256 /* check for possible overflow */
257 /* snprintf on Linux returns -1 on output errors, or the size
258 * that would have been written if enough space had been available */
259 /* vsnprintf is standard in C99 */
260
261 if (sz >= static_cast<int>(spaceSize())) {
262 // not enough space on the first go, we now know how much we need
263 requiredSpaceEstimate = sz*2; // TODO: tune heuristics
264 space = rawSpace(requiredSpaceEstimate);
265 sz = vsnprintf(space, spaceSize(), fmt, vargs);
266 Must3(sz >= 0, "vsnprintf() succeeds (with increased buffer space)", Here());
267 }
268
269 // data was appended, update internal state
270 len_ += sz;
271
272 /* C99 specifies that the final '\0' is not counted in vsnprintf's
273 * return value. Older compilers/libraries might instead count it */
274 /* check whether '\0' was appended and counted */
275 static bool snPrintfTerminatorChecked = false;
276 static bool snPrintfTerminatorCounted = false;
277 if (!snPrintfTerminatorChecked) {
278 char testbuf[16];
279 snPrintfTerminatorCounted = snprintf(testbuf, sizeof(testbuf),
280 "%s", "1") == 2;
281 snPrintfTerminatorChecked = true;
282 }
283 if (snPrintfTerminatorCounted) {
284 --sz;
285 --len_;
286 }
287
288 store_->size += sz;
289 ++stats.append;
290
291 return *this;
292}
293
294std::ostream&
295SBuf::print(std::ostream &os) const
296{
297 os.write(buf(), length());
298 ++stats.toStream;
299 return os;
300}
301
302std::ostream&
303SBuf::dump(std::ostream &os) const
304{
305 os << id
306 << ": ";
307 store_->dump(os);
308 os << ", offset:" << off_
309 << ", len:" << len_
310 << ") : '";
311 print(os);
312 os << '\'' << std::endl;
313 return os;
314# if 0
315 // alternate implementation, based on Raw() API.
316 os << Raw("SBuf", buf(), length()) <<
317 ". id: " << id <<
318 ", offset:" << off_ <<
319 ", len:" << len_ <<
320 ", store: ";
321 store_->dump(os);
322 os << std::endl;
323 return os;
324#endif
325}
326
327void
328SBuf::setAt(size_type pos, char toset)
329{
331 cow();
332 store_->mem[off_+pos] = toset;
333 ++stats.setChar;
334}
335
336static int
337memcasecmp(const char *b1, const char *b2, SBuf::size_type len)
338{
339 int rv=0;
340 while (len > 0) {
341 rv = tolower(*b1)-tolower(*b2);
342 if (rv != 0)
343 return rv;
344 ++b1;
345 ++b2;
346 --len;
347 }
348 return rv;
349}
350
351int
352SBuf::compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const
353{
354 if (n != npos) {
355 debugs(24, 8, "length specified. substr and recurse");
356 return substr(0,n).compare(S.substr(0,n),isCaseSensitive);
357 }
358
359 const size_type byteCompareLen = min(S.length(), length());
361 int rv = 0;
362 debugs(24, 8, "comparing length " << byteCompareLen);
363 if (isCaseSensitive == caseSensitive) {
364 rv = memcmp(buf(), S.buf(), byteCompareLen);
365 } else {
366 rv = memcasecmp(buf(), S.buf(), byteCompareLen);
367 }
368 if (rv != 0) {
369 debugs(24, 8, "result: " << rv);
370 return rv;
371 }
372 if (n <= length() || n <= S.length()) {
373 debugs(24, 8, "same contents and bounded length. Equal");
374 return 0;
375 }
376 if (length() == S.length()) {
377 debugs(24, 8, "same contents and same length. Equal");
378 return 0;
379 }
380 if (length() > S.length()) {
381 debugs(24, 8, "lhs is longer than rhs. Result is 1");
382 return 1;
383 }
384 debugs(24, 8, "rhs is longer than lhs. Result is -1");
385 return -1;
386}
387
388int
389SBuf::compare(const char *s, const SBufCaseSensitive isCaseSensitive, const size_type n) const
390{
391 // 0-length comparison is always true regardless of buffer states
392 if (!n) {
394 return 0;
395 }
396
397 // N-length compare MUST provide a non-NULL C-string pointer
398 assert(s);
399
400 // when this is a 0-length string, no need for any complexity.
401 if (!length()) {
403 return '\0' - *s;
404 }
405
406 // brute-force scan in order to avoid ever needing strlen() on a c-string.
408 const char *left = buf();
409 const char *right = s;
410 int rv = 0;
411 // what area to scan.
412 // n may be npos, but we treat that as a huge positive value
413 size_type byteCount = min(length(), n);
414
415 // loop until we find a difference, a '\0', or reach the end of area to scan
416 if (isCaseSensitive == caseSensitive) {
417 while ((rv = *left - *right++) == 0) {
418 if (*left++ == '\0' || --byteCount == 0)
419 break;
420 }
421 } else {
422 while ((rv = tolower(*left) - tolower(*right++)) == 0) {
423 if (*left++ == '\0' || --byteCount == 0)
424 break;
425 }
426 }
427
428 // If we stopped scanning because we reached the end
429 // of buf() before we reached the end of s,
430 // pretend we have a 0-terminator there to compare.
431 // NP: the loop already incremented "right" ready for this comparison
432 if (!byteCount && length() < n)
433 return '\0' - *right;
434
435 // If we found a difference within the scan area,
436 // or we found a '\0',
437 // or all n characters were identical (and none was \0).
438 return rv;
439}
440
441bool
442SBuf::startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive) const
443{
444 debugs(24, 8, id << " startsWith " << S.id << ", caseSensitive: " <<
445 isCaseSensitive);
446 if (length() < S.length()) {
447 debugs(24, 8, "no, too short");
449 return false;
450 }
451 return (compare(S, isCaseSensitive, S.length()) == 0);
452}
453
454bool
455SBuf::operator ==(const SBuf & S) const
456{
457 debugs(24, 8, id << " == " << S.id);
458 if (length() != S.length()) {
459 debugs(24, 8, "no, different lengths");
461 return false; //shortcut: must be equal length
462 }
463 if (store_ == S.store_ && off_ == S.off_) {
464 debugs(24, 8, "yes, same length and backing store");
466 return true; //shortcut: same store, offset and length
467 }
469 const bool rv = (0 == memcmp(buf(), S.buf(), length()));
470 debugs(24, 8, "returning " << rv);
471 return rv;
472}
473
474bool
475SBuf::operator !=(const SBuf & S) const
476{
477 return !(*this == S);
478}
479
480SBuf
482{
483 if (n == npos)
484 n = length();
485 else
486 n = min(n, length());
487 debugs(24, 8, id << " consume " << n);
488 SBuf rv(substr(0, n));
489 chop(n);
490 return rv;
491}
492
493const
495{
496 return stats;
497}
498
500SBuf::copy(char *dest, size_type n) const
501{
502 size_type toexport = min(n,length());
503 memcpy(dest, buf(), toexport);
504 ++stats.copyOut;
505 return toexport;
506}
507
508const char*
510{
512 return buf();
513}
514
515const char*
517{
519 /* null-terminate the current buffer, by hand-appending a \0 at its tail but
520 * without increasing its length. May COW, the side-effect is to guarantee that
521 * the MemBlob's tail is available for us to use */
522 *rawSpace(1) = '\0';
523 ++store_->size;
524 ++stats.setChar;
526 return buf();
527}
528
529SBuf&
531{
532 if (pos == npos || pos > length())
533 pos = length();
534
535 if (n == npos || (pos+n) > length())
536 n = length() - pos;
537
538 // if there will be nothing left, reset the buffer while we can
539 if (pos == length() || n == 0) {
540 clear();
541 return *this;
542 }
543
544 ++stats.chop;
545 off_ += pos;
546 len_ = n;
547 return *this;
548}
549
550SBuf&
551SBuf::trim(const SBuf &toRemove, bool atBeginning, bool atEnd)
552{
553 ++stats.trim;
554 if (atEnd) {
555 const char *p = bufEnd()-1;
556 while (!isEmpty() && memchr(toRemove.buf(), *p, toRemove.length()) != nullptr) {
557 //current end-of-buf is in the searched set
558 --len_;
559 --p;
560 }
561 }
562 if (atBeginning) {
563 const char *p = buf();
564 while (!isEmpty() && memchr(toRemove.buf(), *p, toRemove.length()) != nullptr) {
565 --len_;
566 ++off_;
567 ++p;
568 }
569 }
570 if (isEmpty())
571 clear();
572 return *this;
573}
574
575SBuf
577{
578 SBuf rv(*this);
579 rv.chop(pos, n); //stats handled by callee
580 return rv;
581}
582
584SBuf::find(char c, size_type startPos) const
585{
586 ++stats.find;
587
588 if (startPos == npos) // can't find anything if we look past end of SBuf
589 return npos;
590
591 // std::string returns npos if needle is outside hay
592 if (startPos > length())
593 return npos;
594
595 const void *i = memchr(buf()+startPos, (int)c, (size_type)length()-startPos);
596
597 if (i == nullptr)
598 return npos;
599
600 return (static_cast<const char *>(i)-buf());
601}
602
604SBuf::find(const SBuf &needle, size_type startPos) const
605{
606 if (startPos == npos) { // can't find anything if we look past end of SBuf
607 ++stats.find;
608 return npos;
609 }
610
611 // std::string allows needle to overhang hay but not start outside
612 if (startPos > length()) {
613 ++stats.find;
614 return npos;
615 }
616
617 // for empty needle std::string returns startPos
618 if (needle.length() == 0) {
619 ++stats.find;
620 return startPos;
621 }
622
623 // if needle length is 1 use the char search
624 if (needle.length() == 1)
625 return find(needle[0], startPos);
626
627 ++stats.find;
628
629 char *start = buf()+startPos;
630 char *lastPossible = buf()+length()-needle.length()+1;
631 char needleBegin = needle[0];
632
633 debugs(24, 7, "looking for " << needle << "starting at " << startPos <<
634 " in id " << id);
635 while (start < lastPossible) {
636 char *tmp;
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");
642 return npos;
643 }
644 // lastPossible guarantees no out-of-bounds with memcmp()
645 if (0 == memcmp(needle.buf(), tmp, needle.length())) {
646 debugs(24, 8, "Found at " << (tmp-buf()));
647 return (tmp-buf());
648 }
649 start = tmp+1;
650 }
651 debugs(24, 8, "not found");
652 return npos;
653}
654
656SBuf::rfind(const SBuf &needle, SBuf::size_type endPos) const
657{
658 // when the needle is 1 char, use the 1-char rfind()
659 if (needle.length() == 1)
660 return rfind(needle[0], endPos);
661
662 ++stats.find;
663
664 // needle is bigger than haystack, impossible find
665 if (length() < needle.length())
666 return npos;
667
668 // if startPos is npos, std::string scans from the end of hay
669 if (endPos == npos || endPos > length()-needle.length())
670 endPos = length()-needle.length();
671
672 // an empty needle found at the end of the haystack
673 if (needle.length() == 0)
674 return endPos;
675
676 char *bufBegin = buf();
677 char *cur = bufBegin+endPos;
678 const char needleBegin = needle[0];
679 while (cur >= bufBegin) {
680 if (*cur == needleBegin) {
681 if (0 == memcmp(needle.buf(), cur, needle.length())) {
682 // found
683 return (cur-buf());
684 }
685 }
686 --cur;
687 }
688 return npos;
689}
690
692SBuf::rfind(char c, SBuf::size_type endPos) const
693{
694 ++stats.find;
695
696 // shortcut: haystack is empty, can't find anything by definition
697 if (length() == 0)
698 return npos;
699
700 // on npos input std::string compares last octet of hay
701 if (endPos == npos || endPos >= length()) {
702 endPos = length();
703 } else {
704 // NP: off-by-one weirdness:
705 // endPos is an offset ... 0-based
706 // length() is a count ... 1-based
707 // memrhr() requires a 1-based count of space to scan.
708 ++endPos;
709 }
710
711 if (length() == 0)
712 return endPos;
713
714 const void *i = memrchr(buf(), (int)c, (size_type)endPos);
715
716 if (i == nullptr)
717 return npos;
718
719 return (static_cast<const char *>(i)-buf());
720}
721
723SBuf::findFirstOf(const CharacterSet &set, size_type startPos) const
724{
725 ++stats.find;
726
727 if (startPos == npos)
728 return npos;
729
730 if (startPos >= length())
731 return npos;
732
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) {
737 if (set[*cur])
738 return cur-buf();
739 ++cur;
740 }
741 debugs(24, 7, "not found");
742 return npos;
743}
744
746SBuf::findFirstNotOf(const CharacterSet &set, size_type startPos) const
747{
748 ++stats.find;
749
750 if (startPos == npos)
751 return npos;
752
753 if (startPos >= length())
754 return npos;
755
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) {
760 if (!set[*cur])
761 return cur-buf();
762 ++cur;
763 }
764 debugs(24, 7, "not found");
765 return npos;
766}
767
769SBuf::findLastOf(const CharacterSet &set, size_type endPos) const
770{
771 ++stats.find;
772
773 if (isEmpty())
774 return npos;
775
776 if (endPos == npos || endPos >= length())
777 endPos = length() - 1;
778
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) {
782 if (set[*cur])
783 return cur - start;
784 }
785 debugs(24, 7, "not found");
786 return npos;
787}
788
791{
792 ++stats.find;
793
794 if (isEmpty())
795 return npos;
796
797 if (endPos == npos || endPos >= length())
798 endPos = length() - 1;
799
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) {
803 if (!set[*cur])
804 return cur - start;
805 }
806 debugs(24, 7, "not found");
807 return npos;
808}
809
810void
812{
813 debugs(24, 8, "\"" << *this << "\"");
814 for (size_type j = 0; j < length(); ++j) {
815 const int c = (*this)[j];
816 if (isupper(c))
817 setAt(j, tolower(c));
818 }
819 debugs(24, 8, "result: \"" << *this << "\"");
821}
822
823void
825{
826 debugs(24, 8, "\"" << *this << "\"");
827 for (size_type j = 0; j < length(); ++j) {
828 const int c = (*this)[j];
829 if (islower(c))
830 setAt(j, toupper(c));
831 }
832 debugs(24, 8, "result: \"" << *this << "\"");
834}
835
844void
846{
847 debugs(24, 8, id << " new size: " << newsize);
848 Must(newsize <= maxSize);
849 // TODO: Consider realloc(3)ing in some cases instead.
850 MemBlob::Pointer newbuf = new MemBlob(newsize);
851 if (length() > 0) {
852 newbuf->append(buf(), length());
854 } else {
856 }
857 store_ = newbuf;
858 off_ = 0;
859 debugs(24, 7, id << " new store capacity: " << store_->capacity);
860}
861
862SBuf&
863SBuf::lowAppend(const char * memArea, size_type areaSize)
864{
865 rawSpace(areaSize); //called method also checks n <= maxSize()
866 store_->append(memArea, areaSize);
867 len_ += areaSize;
868 ++stats.append;
869 return *this;
870}
871
877void
879{
880 debugs(24, 8, id << " new size:" << newsize);
881 if (newsize == npos || newsize < length())
882 newsize = length();
883
884 if (store_->LockCount() == 1) {
885 // MemBlob::size reflects past owners. Refresh to maximize spaceSize().
887
888 const auto availableSpace = spaceSize();
889 const auto neededSpace = newsize - length();
890 if (neededSpace <= availableSpace) {
891 debugs(24, 8, id << " no cow needed; have " << availableSpace);
893 return;
894 }
895 // consume idle leading space if doing so avoids reallocation
896 // this case is typical for fill-consume-fill-consume-... I/O buffers
897 if (neededSpace <= availableSpace + off_) {
898 debugs(24, 8, id << " no cow after shifting " << off_ << " to get " << (availableSpace + off_));
900 off_ = 0;
901 ++stats.cowShift;
902 assert(neededSpace <= spaceSize());
903 return;
904 }
905 }
906 reAlloc(newsize);
907}
908
#define Here()
source code location of the caller
Definition: Here.h:15
int cur
Definition: ModDevPoll.cc:74
InstanceIdDefinitions(SBuf, "SBuf")
static int memcasecmp(const char *b1, const char *b2, SBuf::size_type len)
Definition: SBuf.cc:337
SBufCaseSensitive
Definition: SBuf.h:36
@ caseSensitive
Definition: SBuf.h:37
#define Must3(condition, description, location)
Definition: TextException.h:65
#define Must(condition)
Definition: TextException.h:71
#define assert(EX)
Definition: assert.h:19
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:18
const char * name
optional set label for debugging (default: "anonymous")
Definition: CharacterSet.h:72
char * mem
raw allocated memory block
Definition: MemBlob.h:112
void append(const char *source, const size_type n)
Definition: MemBlob.cc:116
void syncSize(const size_type n)
Definition: MemBlob.cc:128
size_type size
maximum allocated memory in use by callers
Definition: MemBlob.h:114
void clear()
extends the available space to the entire allocated blob
Definition: MemBlob.h:97
bool canAppend(const size_type off, const size_type n) const
Definition: MemBlob.h:73
std::ostream & dump(std::ostream &os) const
dump debugging information
Definition: MemBlob.cc:155
void consume(const size_type n)
Definition: MemBlob.cc:137
size_type capacity
size of the raw allocated memory block
Definition: MemBlob.h:113
Definition: Raw.h:21
Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
Definition: SBuf.h:697
bool allowShared
whether sharing our storage with others is OK
Definition: SBuf.h:709
size_type minSpace
allocate [at least this much] if spaceSize() is smaller
Definition: SBuf.h:707
size_type maxCapacity
do not allocate more than this
Definition: SBuf.h:708
size_type idealSpace
if allocating anyway, provide this much space
Definition: SBuf.h:706
uint64_t trim
number of trim operations
Definition: Stats.h:52
uint64_t append
number of append operations
Definition: Stats.h:41
uint64_t cowShift
number of cow() calls requiring just a memmove(3) inside an old buffer
Definition: Stats.h:56
uint64_t nulTerminate
number of c_str() terminations
Definition: Stats.h:50
uint64_t cowJustAlloc
number of cow() calls requiring just a new empty buffer
Definition: Stats.h:57
uint64_t rawAccess
number of accesses to raw contents
Definition: Stats.h:49
uint64_t assignFast
number of no-copy assignment operations
Definition: Stats.h:39
uint64_t cowAllocCopy
number of cow() calls requiring copying into a new buffer
Definition: Stats.h:58
uint64_t setChar
number of calls to setAt
Definition: Stats.h:44
uint64_t caseChange
number of toUpper and toLower operations
Definition: Stats.h:54
uint64_t cowAvoided
number of cow() calls requiring no expensive operations
Definition: Stats.h:55
uint64_t compareFast
number of comparison operations not requiring data scan
Definition: Stats.h:47
uint64_t chop
number of chop operations
Definition: Stats.h:51
uint64_t clear
number of clear operations
Definition: Stats.h:40
static void RecordSBufSizeAtDestruct(size_t)
Record the size a SBuf had when it was destructed.
Definition: Stats.cc:20
uint64_t toStream
number of write operations to ostreams
Definition: Stats.h:43
uint64_t compareSlow
number of comparison operations requiring data scan
Definition: Stats.h:46
uint64_t allocCopy
number of calls to SBuf copy-constructor
Definition: Stats.h:37
uint64_t alloc
number of calls to SBuf constructors
Definition: Stats.h:36
uint64_t find
number of find operations
Definition: Stats.h:53
uint64_t live
number of currently-allocated SBuf
Definition: Stats.h:59
uint64_t copyOut
number of data-copies to other forms of buffers
Definition: Stats.h:48
uint64_t allocFromCString
number of copy-allocations from c-strings
Definition: Stats.h:38
Definition: SBuf.h:94
char * rawAppendStart(size_type anticipatedSize)
Definition: SBuf.cc:136
void toUpper()
converts all characters to upper case;
Definition: SBuf.cc:824
const char * rawContent() const
Definition: SBuf.cc:509
static const size_type npos
Definition: SBuf.h:99
SBuf consume(size_type n=npos)
Definition: SBuf.cc:481
SBuf & vappendf(const char *fmt, va_list vargs)
Definition: SBuf.cc:239
const char * c_str()
Definition: SBuf.cc:516
~SBuf()
Definition: SBuf.cc:68
SBuf & chop(size_type pos, size_type n=npos)
Definition: SBuf.cc:530
void reserveCapacity(size_type minCapacity)
Definition: SBuf.cc:105
size_type len_
number of our content bytes in shared store_
Definition: SBuf.h:631
static const SBufStats & GetStats()
gets global statistic information
Definition: SBuf.cc:494
static MemBlob::Pointer GetStorePrototype()
Definition: SBuf.cc:76
SBuf & lowAppend(const char *memArea, size_type areaSize)
Definition: SBuf.cc:863
const InstanceId< SBuf > id
Definition: SBuf.h:604
void reAlloc(size_type newsize)
Definition: SBuf.cc:845
char * buf() const
Definition: SBuf.h:645
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:415
static SBufStats stats
class-wide statistics
Definition: SBuf.h:632
SBuf()
create an empty (zero-size) SBuf
Definition: SBuf.cc:28
size_type rfind(char c, size_type endPos=npos) const
Definition: SBuf.cc:692
size_type reserve(const SBufReservationRequirements &requirements)
Definition: SBuf.cc:112
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
Definition: SBuf.cc:746
SBuf & trim(const SBuf &toRemove, bool atBeginning=true, bool atEnd=true)
Definition: SBuf.cc:551
size_type spaceSize() const
Definition: SBuf.h:393
size_type find(char c, size_type startPos=0) const
Definition: SBuf.cc:584
size_type findFirstOf(const CharacterSet &set, size_type startPos=0) const
Definition: SBuf.cc:723
bool operator!=(const SBuf &S) const
Definition: SBuf.cc:475
size_type copy(char *dest, size_type n) const
Definition: SBuf.cc:500
bool isEmpty() const
Definition: SBuf.h:431
bool operator==(const SBuf &S) const
Definition: SBuf.cc:455
size_type findLastNotOf(const CharacterSet &set, size_type endPos=npos) const
Definition: SBuf.cc:790
char * rawSpace(size_type minSize)
Definition: SBuf.cc:157
std::ostream & dump(std::ostream &os) const
Definition: SBuf.cc:303
void cow(size_type minsize=npos)
Definition: SBuf.cc:878
void checkAccessBounds(const size_type pos) const
Definition: SBuf.h:664
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
MemBlob::Pointer store_
memory block, possibly shared with other SBufs
Definition: SBuf.h:629
size_type findLastOf(const CharacterSet &set, size_type endPos=npos) const
Definition: SBuf.cc:769
size_type off_
our content start offset from the beginning of shared store_
Definition: SBuf.h:630
SBuf & Printf(const char *fmt,...)
Definition: SBuf.cc:214
bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive=caseSensitive) const
Definition: SBuf.cc:442
void clear()
Definition: SBuf.cc:175
SBuf substr(size_type pos, size_type n=npos) const
Definition: SBuf.cc:576
std::ostream & print(std::ostream &os) const
print the SBuf contents to the supplied ostream
Definition: SBuf.cc:295
MemBlob::size_type size_type
Definition: SBuf.h:96
void rawAppendFinish(const char *start, size_type actualSize)
Definition: SBuf.cc:144
SBuf & assign(const SBuf &S)
Definition: SBuf.cc:83
void setAt(size_type pos, char toset)
Definition: SBuf.cc:328
void toLower()
converts all characters to lower case;
Definition: SBuf.cc:811
int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const
Definition: SBuf.cc:352
char * bufEnd() const
Definition: SBuf.h:652
static const size_type maxSize
Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
Definition: SBuf.h:102
SBuf & appendf(const char *fmt,...)
Definition: SBuf.cc:229
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
void * memrchr(const void *s, int c, size_t n)
Definition: memrchr.cc:36
void const char int sz
Definition: stub_cbdata.cc:16

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors