]> git.ipfire.org Git - thirdparty/squid.git/blame - src/sbuf/SBuf.h
Add SBuf::push_back() (#1621)
[thirdparty/squid.git] / src / sbuf / SBuf.h
CommitLineData
412da427 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
412da427 3 *
bbc27441
AJ
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.
412da427
FC
7 */
8
46707063
FC
9/* DEBUG: section 24 SBuf */
10
412da427
FC
11#ifndef SQUID_SBUF_H
12#define SQUID_SBUF_H
13
14#include "base/InstanceId.h"
ebaabe74 15#include "base/TextException.h"
675b8408 16#include "debug/Stream.h"
2745fea5 17#include "globals.h"
19e97cf0 18#include "sbuf/forward.h"
65e41a45 19#include "sbuf/MemBlob.h"
b268925c 20#include "sbuf/Stats.h"
412da427 21
62842d40 22#include <climits>
074d6a40 23#include <iosfwd>
8a3e1749 24#include <iterator>
412da427
FC
25#if HAVE_UNISTD_H
26#include <unistd.h>
27#endif
412da427 28
496a9e97 29/* SBuf placeholder for printf */
412da427
FC
30#ifndef SQUIDSBUFPH
31#define SQUIDSBUFPH "%.*s"
32#define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent()
33#endif /* SQUIDSBUFPH */
34
6a17a36d 35// TODO: move within SBuf and rename
412da427
FC
36typedef enum {
37 caseSensitive,
38 caseInsensitive
39} SBufCaseSensitive;
40
4685b0c4 41class CharacterSet;
8a3e1749 42
7a79f6d8 43/** Forward input const_iterator for SBufs
02620563
FC
44 *
45 * Please note that any operation on the underlying SBuf may invalidate
46 * all iterators over it, resulting in undefined behavior by them.
47 */
c3f0885d 48class SBufIterator
8a3e1749
FC
49{
50public:
c3f0885d
FC
51 // iterator traits
52 using iterator_category = std::input_iterator_tag;
53 using value_type = char;
54 using difference_type = std::ptrdiff_t;
55 using pointer = char*;
56 using reference = char&;
57
8a3e1749
FC
58 friend class SBuf;
59 typedef MemBlob::size_type size_type;
60 bool operator==(const SBufIterator &s) const;
61 bool operator!=(const SBufIterator &s) const;
62
7a79f6d8 63 const char &operator*() const { return *iter; }
8a3e1749
FC
64 SBufIterator& operator++() { ++iter; return *this; }
65
66protected:
67 SBufIterator(const SBuf &, size_type);
68
6bc1ca30 69 const char *iter = nullptr;
8a3e1749
FC
70};
71
7a79f6d8 72/** Reverse input const_iterator for SBufs
02620563
FC
73 *
74 * Please note that any operation on the underlying SBuf may invalidate
75 * all iterators over it, resulting in undefined behavior by them.
76 */
8a3e1749
FC
77class SBufReverseIterator : public SBufIterator
78{
79 friend class SBuf;
80public:
81 SBufReverseIterator& operator++() { --iter; return *this;}
7a79f6d8 82 const char &operator*() const { return *(iter-1); }
8a3e1749
FC
83protected:
84 SBufReverseIterator(const SBuf &s, size_type sz) : SBufIterator(s,sz) {}
85};
4685b0c4 86
412da427
FC
87/**
88 * A String or Buffer.
89 * Features: refcounted backing store, cheap copy and sub-stringing
90 * operations, copy-on-write to isolate change operations to each instance.
91 * Where possible, we're trying to mimic std::string's interface.
92 */
93class SBuf
94{
95public:
7cbd3256 96 typedef MemBlob::size_type size_type;
7a79f6d8
AJ
97 typedef SBufIterator const_iterator;
98 typedef SBufReverseIterator const_reverse_iterator;
1cca3b78 99 using value_type = char;
50827187 100 static const size_type npos = 0xffffffff; // max(uint32_t)
412da427
FC
101
102 /// Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
103 static const size_type maxSize = 0xfffffff;
104
105 /// create an empty (zero-size) SBuf
106 SBuf();
107 SBuf(const SBuf &S);
e1c19450 108 SBuf(SBuf&& S) : store_(std::move(S.store_)), off_(S.off_), len_(S.len_) {
e5469196 109 ++stats.moves;
6bc1ca30
AJ
110 S.store_ = nullptr; //RefCount supports nullptr, and S is about to be destructed
111 S.off_ = S.len_ = 0;
f49df3f5 112 }
412da427
FC
113
114 /** Constructor: import c-style string
115 *
116 * Create a new SBuf containing a COPY of the contents of the
117 * c-string
118 * \param S the c string to be copied
7cbd3256 119 * \param n how many bytes to import into the SBuf. If it is npos
412da427
FC
120 * or unspecified, imports to end-of-cstring
121 * \note it is the caller's responsibility not to go out of bounds
50827187 122 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
412da427 123 */
976cbfaf 124 explicit SBuf(const char *S, size_type n);
eb9d358b 125 explicit SBuf(const char *S);
412da427 126
496a9e97
FC
127 /// Constructor: import std::string. Contents are copied.
128 explicit SBuf(const std::string &s);
412da427
FC
129
130 ~SBuf();
62842d40 131
412da427
FC
132 /** Explicit assignment.
133 *
134 * Current SBuf will share backing store with the assigned one.
135 */
136 SBuf& assign(const SBuf &S);
62842d40 137
412da427
FC
138 /** Assignment operator.
139 *
140 * Current SBuf will share backing store with the assigned one.
141 */
62842d40 142 SBuf& operator =(const SBuf & S) {return assign(S);}
ef9d1c02
FC
143 SBuf& operator =(SBuf &&S) {
144 ++stats.moves;
145 if (this != &S) {
146 store_ = std::move(S.store_);
147 off_ = S.off_;
148 len_ = S.len_;
aee3523a 149 S.store_ = nullptr; //RefCount supports NULL, and S is about to be destructed
ef9d1c02
FC
150 S.off_ = 0;
151 S.len_ = 0;
152 }
153 return *this;
154 }
412da427 155
e227da8d
AR
156 // XXX: assign(s,n)/append(s,n) calls do not assign or append a c-string as
157 // documented -- they do not stop at the first NUL character! They assign or
158 // append the entire raw memory area, including any embedded NUL characters.
159
412da427
FC
160 /** Import a c-string into a SBuf, copying the data.
161 *
162 * It is the caller's duty to free the imported string, if needed.
163 * \param S the c string to be copied
7cbd3256 164 * \param n how many bytes to import into the SBuf. If it is npos
412da427
FC
165 * or unspecified, imports to end-of-cstring
166 * \note it is the caller's responsibility not to go out of bounds
7cbd3256
FC
167 * \note to assign a std::string use the pattern:
168 * assign(stdstr.data(), stdstd.length())
412da427 169 */
976cbfaf 170 SBuf& assign(const char *S, size_type n);
ef9d1c02 171 SBuf& assign(const char *S) {return assign(S,npos);}
412da427
FC
172
173 /** Assignment operator. Copy a NULL-terminated c-style string into a SBuf.
174 *
175 * Copy a c-style string into a SBuf. Shortcut for SBuf.assign(S)
176 * It is the caller's duty to free the imported string, if needed.
7cbd3256 177 * \note not \0-clean
412da427 178 */
62842d40 179 SBuf& operator =(const char *S) {return assign(S);}
412da427 180
412da427
FC
181 /** reset the SBuf as if it was just created.
182 *
183 * Resets the SBuf to empty, memory is freed lazily.
184 */
185 void clear();
186
187 /** Append operation
188 *
189 * Append the supplied SBuf to the current one; extend storage as needed.
190 */
191 SBuf& append(const SBuf & S);
192
1cca3b78
FC
193 /// \copydoc push_back(char)
194 SBuf& append(const char c) { push_back(c); return *this; }
195
e7ce227f 196 /// Append a single character. The character may be NUL (\0).
1cca3b78 197 void push_back(char);
e7ce227f 198
412da427
FC
199 /** Append operation for C-style strings.
200 *
201 * Append the supplied c-string to the SBuf; extend storage
202 * as needed.
203 *
204 * \param S the c string to be copied. Can be NULL.
a452bc8b
FC
205 * \param Ssize how many bytes to import into the SBuf. If it is npos
206 * or unspecified, imports to end-of-cstring. If S is NULL,
207 * Ssize is ignored.
7cbd3256
FC
208 * \note to append a std::string use the pattern
209 * cstr_append(stdstr.data(), stdstd.length())
412da427 210 */
976cbfaf 211 SBuf& append(const char * S, size_type Ssize);
ef9d1c02 212 SBuf& append(const char * S) { return append(S,npos); }
412da427
FC
213
214 /** Assignment operation with printf(3)-style definition
215 * \note arguments may be evaluated more than once, be careful
216 * of side-effects
217 */
543bff10 218 SBuf& Printf(const char *fmt, ...) PRINTF_FORMAT_ARG2;
412da427
FC
219
220 /** Append operation with printf-style arguments
221 * \note arguments may be evaluated more than once, be careful
222 * of side-effects
223 */
543bff10 224 SBuf& appendf(const char *fmt, ...) PRINTF_FORMAT_ARG2;
496a9e97 225
412da427
FC
226 /** Append operation, with vsprintf(3)-style arguments.
227 * \note arguments may be evaluated more than once, be careful
228 * of side-effects
229 */
230 SBuf& vappendf(const char *fmt, va_list vargs);
231
496a9e97 232 /// print the SBuf contents to the supplied ostream
412da427
FC
233 std::ostream& print(std::ostream &os) const;
234
496a9e97 235 /** print SBuf contents and debug information about the SBuf to an ostream
412da427 236 *
2f8abb64 237 * Debug function, dumps to a stream information on the current SBuf,
412da427
FC
238 * including low-level details and statistics.
239 */
240 std::ostream& dump(std::ostream &os) const;
241
242 /** random-access read to any char within the SBuf
243 *
244 * does not check access bounds. If you need that, use at()
245 */
fdd1982c 246 char operator [](size_type pos) const {++stats.getChar; return store_->mem[off_+pos];}
412da427
FC
247
248 /** random-access read to any char within the SBuf.
249 *
ebaabe74 250 * \throw std::exception when access is out of bounds
50827187 251 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
412da427 252 */
fdd1982c 253 char at(size_type pos) const {checkAccessBounds(pos); return operator[](pos);}
412da427
FC
254
255 /** direct-access set a byte at a specified operation.
256 *
257 * \param pos the position to be overwritten
258 * \param toset the value to be written
ebaabe74 259 * \throw std::exception when pos is of bounds
50827187 260 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
412da427
FC
261 * \note performs a copy-on-write if needed.
262 */
263 void setAt(size_type pos, char toset);
264
265 /** compare to other SBuf, str(case)cmp-style
266 *
267 * \param isCaseSensitive one of caseSensitive or caseInsensitive
7cbd3256 268 * \param n compare up to this many bytes. if npos (default), compare whole SBufs
412da427
FC
269 * \retval >0 argument of the call is greater than called SBuf
270 * \retval <0 argument of the call is smaller than called SBuf
271 * \retval 0 argument of the call has the same contents of called SBuf
272 */
976cbfaf
FC
273 int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const;
274 int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive) const {
ef9d1c02 275 return compare(S, isCaseSensitive, npos);
976cbfaf 276 }
7cbd3256 277
1284f77c 278 /// shorthand version for compare()
976cbfaf 279 inline int cmp(const SBuf &S, const size_type n) const {
7cbd3256
FC
280 return compare(S,caseSensitive,n);
281 }
976cbfaf 282 inline int cmp(const SBuf &S) const {
ef9d1c02 283 return compare(S,caseSensitive,npos);
976cbfaf 284 }
7cbd3256 285
1284f77c 286 /// shorthand version for case-insensitive compare()
976cbfaf 287 inline int caseCmp(const SBuf &S, const size_type n) const {
1284f77c
AJ
288 return compare(S,caseInsensitive,n);
289 }
976cbfaf 290 inline int caseCmp(const SBuf &S) const {
ef9d1c02 291 return compare(S,caseInsensitive,npos);
976cbfaf 292 }
1284f77c
AJ
293
294 /// Comparison with a C-string.
976cbfaf
FC
295 int compare(const char *s, const SBufCaseSensitive isCaseSensitive, const size_type n) const;
296 int compare(const char *s, const SBufCaseSensitive isCaseSensitive) const {
ef9d1c02 297 return compare(s,isCaseSensitive,npos);
976cbfaf 298 }
1284f77c
AJ
299
300 /// Shorthand version for C-string compare().
976cbfaf 301 inline int cmp(const char *S, const size_type n) const {
1284f77c
AJ
302 return compare(S,caseSensitive,n);
303 }
976cbfaf 304 inline int cmp(const char *S) const {
ef9d1c02 305 return compare(S,caseSensitive,npos);
976cbfaf 306 }
1284f77c
AJ
307
308 /// Shorthand version for case-insensitive C-string compare().
976cbfaf 309 inline int caseCmp(const char *S, const size_type n) const {
7cbd3256
FC
310 return compare(S,caseInsensitive,n);
311 }
976cbfaf 312 inline int caseCmp(const char *S) const {
ef9d1c02 313 return compare(S,caseInsensitive,npos);
976cbfaf 314 }
412da427
FC
315
316 /** check whether the entire supplied argument is a prefix of the SBuf.
317 * \param S the prefix to match against
318 * \param isCaseSensitive one of caseSensitive or caseInsensitive
319 * \retval true argument is a prefix of the SBuf
320 */
1284f77c 321 bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive = caseSensitive) const;
412da427 322
412da427
FC
323 bool operator ==(const SBuf & S) const;
324 bool operator !=(const SBuf & S) const;
7cbd3256
FC
325 bool operator <(const SBuf &S) const {return (cmp(S) < 0);}
326 bool operator >(const SBuf &S) const {return (cmp(S) > 0);}
327 bool operator <=(const SBuf &S) const {return (cmp(S) <= 0);}
328 bool operator >=(const SBuf &S) const {return (cmp(S) >= 0);}
412da427
FC
329
330 /** Consume bytes at the head of the SBuf
331 *
332 * Consume N chars at SBuf head, or to SBuf's end,
333 * whichever is shorter. If more bytes are consumed than available,
334 * the SBuf is emptied
335 * \param n how many bytes to remove; could be zero.
7cbd3256 336 * npos (or no argument) means 'to the end of SBuf'
412da427
FC
337 * \return a new SBuf containing the consumed bytes.
338 */
339 SBuf consume(size_type n = npos);
340
2f8abb64 341 /// gets global statistic information
412da427
FC
342 static const SBufStats& GetStats();
343
344 /** Copy SBuf contents into user-supplied C buffer.
345 *
346 * Export a copy of the SBuf's contents into the user-supplied
347 * buffer, up to the user-supplied-length. No zero-termination is performed
348 * \return num the number of actually-copied chars.
349 */
350 size_type copy(char *dest, size_type n) const;
351
352 /** exports a pointer to the SBuf internal storage.
353 * \warning ACCESSING RAW STORAGE IS DANGEROUS!
354 *
496a9e97
FC
355 * Returns a ead-only pointer to SBuf's content. No terminating null
356 * character is appended (use c_str() for that).
412da427
FC
357 * The returned value points to an internal location whose contents
358 * are guaranteed to remain unchanged only until the next call
359 * to a non-constant member function of the SBuf object. Such a
360 * call may be implicit (e.g., when SBuf is destroyed
361 * upon leaving the current context).
362 * This is a very UNSAFE way of accessing the data.
363 * This call never returns NULL.
364 * \see c_str
365 * \note the memory management system guarantees that the exported region
366 * of memory will remain valid if the caller keeps holding
367 * a valid reference to the SBuf object and does not write or append to
368 * it. For example:
369 * \code
370 * SBuf foo("some string");
371 * const char *bar = foo.rawContent();
372 * doSomething(bar); //safe
373 * foo.append(" other string");
374 * doSomething(bar); //unsafe
375 * \endcode
376 */
377 const char* rawContent() const;
378
672337d1
CT
379 /// \returns a buffer suitable for appending at most `anticipatedSize` bytes
380 /// The buffer must be used "immediately" because it is invalidated by most
381 /// non-constant SBuf method calls, including such calls against other SBuf
382 /// objects that just happen to share the same underlying MemBlob storage!
383 char *rawAppendStart(size_type anticipatedSize);
384
385 /// Updates SBuf metadata to reflect appending `actualSize` bytes to the
386 /// buffer returned by the corresponding rawAppendStart() call. Throws if
387 /// rawAppendStart(actualSize) would have returned a different value now.
388 /// \param start raw buffer previously returned by rawAppendStart()
389 /// \param actualSize the number of appended bytes
390 void rawAppendFinish(const char *start, size_type actualSize);
412da427 391
50827187 392 /** Obtain how much free space is available in the backing store.
8aa34dad 393 *
50827187
FC
394 * \note: unless the client just cow()ed, it is not guaranteed that
395 * the free space can be used.
8aa34dad
FC
396 */
397 size_type spaceSize() const { return store_->spaceSize(); }
398
412da427
FC
399 /** exports a null-terminated reference to the SBuf internal storage.
400 * \warning ACCESSING RAW STORAGE IS DANGEROUS! DO NOT EVER USE
401 * THE RETURNED POINTER FOR WRITING
402 *
403 * The returned value points to an internal location whose contents
404 * are guaranteed to remain unchanged only until the next call
405 * to a non-constant member function of the SBuf object. Such a
406 * call may be implicit (e.g., when SBuf is destroyed
407 * upon leaving the current context).
408 * This is a very UNSAFE way of accessing the data.
409 * This call never returns NULL.
410 * \see rawContent
411 * \note the memory management system guarantees that the exported region
496a9e97
FC
412 * of memory will remain valid will remain valid only if the
413 * caller keeps holding a valid reference to the SBuf object and
414 * does not write or append to it
412da427
FC
415 */
416 const char* c_str();
417
496a9e97 418 /// Returns the number of bytes stored in SBuf.
62842d40 419 size_type length() const {return len_;}
412da427
FC
420
421 /** Get the length of the SBuf, as a signed integer
422 *
423 * Compatibility function for printf(3) which requires a signed int
ebaabe74 424 * \throw std::exception if buffer length does not fit a signed integer
412da427 425 */
62842d40 426 int plength() const {
ebaabe74 427 Must(length() <= INT_MAX);
62842d40
FC
428 return static_cast<int>(length());
429 }
412da427
FC
430
431 /** Check whether the SBuf is empty
432 *
433 * \return true if length() == 0
434 */
62842d40 435 bool isEmpty() const {return (len_==0);}
412da427 436
8aa34dad 437 /** Request to guarantee the SBuf's free store space.
412da427
FC
438 *
439 * After the reserveSpace request, the SBuf is guaranteed to have at
7cbd3256 440 * least minSpace bytes of unused backing store following the currently
ac7947fd 441 * used portion and single ownership of the backing store.
ebaabe74 442 * \throw std::exception if the user tries to allocate a too big SBuf
412da427 443 */
e842ecce 444 void reserveSpace(size_type minSpace) {
6fd0701a 445 Must(minSpace <= maxSize);
a44b8b80 446 Must(length() <= maxSize - minSpace);
e842ecce
FC
447 reserveCapacity(length()+minSpace);
448 }
412da427 449
8aa34dad 450 /** Request to guarantee the SBuf's store capacity
412da427
FC
451 *
452 * After this method is called, the SBuf is guaranteed to have at least
7cbd3256 453 * minCapacity bytes of total buffer size, including the currently-used
577bcebc
FC
454 * portion; it is also guaranteed that after this call this SBuf
455 * has unique ownership of the underlying memory store.
ebaabe74 456 * \throw std::exception if the user tries to allocate a too big SBuf
412da427
FC
457 */
458 void reserveCapacity(size_type minCapacity);
459
19e97cf0
AR
460 /** Accommodate caller's requirements regarding SBuf's storage if possible.
461 *
462 * \return spaceSize(), which may be zero
463 */
464 size_type reserve(const SBufReservationRequirements &requirements);
465
412da427
FC
466 /** slicing method
467 *
496a9e97
FC
468 * Removes SBuf prefix and suffix, leaving a sequence of 'n'
469 * bytes starting from position 'pos', first byte is at pos 0.
470 * It is an in-place-modifying version of substr.
412da427 471 * \param pos start sub-stringing from this byte. If it is
496a9e97 472 * npos or it is greater than the SBuf length, the SBuf is cleared and
50827187 473 * an empty SBuf is returned.
412da427 474 * \param n maximum number of bytes of the resulting SBuf.
7cbd3256 475 * npos means "to end of SBuf".
496a9e97 476 * if it is 0, the SBuf is cleared and an empty SBuf is returned.
496a9e97
FC
477 * if it overflows the end of the SBuf, it is capped to the end of SBuf
478 * \see substr, trim
412da427
FC
479 */
480 SBuf& chop(size_type pos, size_type n = npos);
481
482 /** Remove characters in the toremove set at the beginning, end or both
483 *
484 * \param toremove characters to be removed. Stops chomping at the first
485 * found char not in the set
486 * \param atBeginning if true (default), strips at the beginning of the SBuf
487 * \param atEnd if true (default), strips at the end of the SBuf
488 */
489 SBuf& trim(const SBuf &toRemove, bool atBeginning = true, bool atEnd = true);
490
491 /** Extract a part of the current SBuf.
492 *
496a9e97
FC
493 * Return a fresh a fresh copy of a portion the current SBuf, which is
494 * left untouched. The same parameter convetions apply as for chop.
495 * \see trim, chop
412da427
FC
496 */
497 SBuf substr(size_type pos, size_type n = npos) const;
498
499 /** Find first occurrence of character in SBuf
500 *
501 * Returns the index in the SBuf of the first occurrence of char c.
7cbd3256 502 * \return npos if the char was not found
412da427 503 * \param startPos if specified, ignore any occurrences before that position
496a9e97 504 * if startPos is npos or greater than length() npos is always returned
7cbd3256 505 * if startPos is less than zero, it is ignored
412da427
FC
506 */
507 size_type find(char c, size_type startPos = 0) const;
508
509 /** Find first occurrence of SBuf in SBuf.
510 *
511 * Returns the index in the SBuf of the first occurrence of the
512 * sequence contained in the str argument.
513 * \param startPos if specified, ignore any occurrences before that position
496a9e97 514 * if startPos is npos or greater than length() npos is always returned
7cbd3256 515 * \return npos if the SBuf was not found
412da427
FC
516 */
517 size_type find(const SBuf & str, size_type startPos = 0) const;
518
519 /** Find last occurrence of character in SBuf
520 *
521 * Returns the index in the SBuf of the last occurrence of char c.
7cbd3256 522 * \return npos if the char was not found
412da427 523 * \param endPos if specified, ignore any occurrences after that position.
496a9e97 524 * if npos or greater than length(), the whole SBuf is considered
412da427
FC
525 */
526 size_type rfind(char c, size_type endPos = npos) const;
527
528 /** Find last occurrence of SBuf in SBuf
529 *
530 * Returns the index in the SBuf of the last occurrence of the
531 * sequence contained in the str argument.
7cbd3256 532 * \return npos if the sequence was not found
412da427 533 * \param endPos if specified, ignore any occurrences after that position
496a9e97 534 * if npos or greater than length(), the whole SBuf is considered
412da427
FC
535 */
536 size_type rfind(const SBuf &str, size_type endPos = npos) const;
537
538 /** Find first occurrence of character of set in SBuf
539 *
540 * Finds the first occurrence of ANY of the characters in the supplied set in
541 * the SBuf.
7cbd3256 542 * \return npos if no character in the set could be found
412da427 543 * \param startPos if specified, ignore any occurrences before that position
7cbd3256 544 * if npos, then npos is always returned
c8046ec7
FC
545 *
546 * TODO: rename to camelCase
412da427 547 */
810a5427 548 size_type findFirstOf(const CharacterSet &set, size_type startPos = 0) const;
3c1106a0 549
c571034b
AR
550 /** Find last occurrence of character of set in SBuf
551 *
552 * Finds the last occurrence of ANY of the characters in the supplied set in
553 * the SBuf.
554 * \return npos if no character in the set could be found
555 * \param endPos if specified, ignore any occurrences after that position
556 * if npos, the entire SBuf is searched
557 */
558 size_type findLastOf(const CharacterSet &set, size_type endPos = npos) const;
559
3c1106a0
FC
560 /** Find first occurrence character NOT in character set
561 *
c8046ec7 562 * \return npos if all characters in the SBuf are from set
3c1106a0
FC
563 * \param startPos if specified, ignore any occurrences before that position
564 * if npos, then npos is always returned
c8046ec7
FC
565 *
566 * TODO: rename to camelCase
3c1106a0 567 */
810a5427 568 size_type findFirstNotOf(const CharacterSet &set, size_type startPos = 0) const;
412da427 569
c571034b
AR
570 /** Find last occurrence character NOT in character set
571 *
572 * \return npos if all characters in the SBuf are from set
573 * \param endPos if specified, ignore any occurrences after that position
574 * if npos, then the entire SBuf is searched
575 */
576 size_type findLastNotOf(const CharacterSet &set, size_type endPos = npos) const;
577
37cf7314
AR
578 /// converts all characters to lower case; \see man tolower(3)
579 void toLower();
412da427 580
37cf7314
AR
581 /// converts all characters to upper case; \see man toupper(3)
582 void toUpper();
412da427 583
7cbd3256
FC
584 /// std::string export function
585 std::string toStdString() const { return std::string(buf(),length()); }
586
7a79f6d8
AJ
587 const_iterator begin() const {
588 return const_iterator(*this, 0);
8a3e1749
FC
589 }
590
7a79f6d8
AJ
591 const_iterator end() const {
592 return const_iterator(*this, length());
8a3e1749
FC
593 }
594
7a79f6d8
AJ
595 const_reverse_iterator rbegin() const {
596 return const_reverse_iterator(*this, length());
8a3e1749
FC
597 }
598
7a79f6d8
AJ
599 const_reverse_iterator rend() const {
600 return const_reverse_iterator(*this, 0);
8a3e1749
FC
601 }
602
496a9e97
FC
603 // TODO: possibly implement erase() similar to std::string's erase
604 // TODO: possibly implement a replace() call
f39f94d2
AR
605
606 /// SBuf object identifier meant for test cases and debugging.
607 /// Does not change when object does, including during assignment.
608 const InstanceId<SBuf> id;
609
412da427
FC
610private:
611
eaa5d9b3
AJ
612 /**
613 * Keeps SBuf's MemBlob alive in a blob-destroying context where
614 * a seemingly unrelated memory pointer may belong to the same blob.
615 * For [an extreme] example, consider: a.append(a).
616 * Compared to an SBuf temporary, this class is optimized to
617 * preserve blobs only if needed and to reduce debugging noise.
618 */
4a0fcd9b
AJ
619 class Locker
620 {
621 public:
eaa5d9b3
AJ
622 Locker(SBuf *parent, const char *otherBuffer) {
623 // lock if otherBuffer intersects the parents buffer area
624 const MemBlob *blob = parent->store_.getRaw();
625 if (blob->mem <= otherBuffer && otherBuffer < (blob->mem + blob->capacity))
626 locket = blob;
4a0fcd9b
AJ
627 }
628 private:
629 MemBlob::Pointer locket;
630 };
631 friend class Locker;
632
412da427 633 MemBlob::Pointer store_; ///< memory block, possibly shared with other SBufs
6bc1ca30
AJ
634 size_type off_ = 0; ///< our content start offset from the beginning of shared store_
635 size_type len_ = 0; ///< number of our content bytes in shared store_
412da427
FC
636 static SBufStats stats; ///< class-wide statistics
637
62842d40
FC
638 /** obtain prototype store
639 *
640 * Just-created SBufs all share to the same MemBlob.
641 * This call instantiates and returns it.
642 */
643 static MemBlob::Pointer GetStorePrototype();
644
645 /**
646 * obtains a char* to the beginning of this SBuf in memory.
647 * \note the obtained string is NOT null-terminated.
648 */
649 char * buf() const {return (store_->mem+off_);}
650
651 /** returns the pointer to the first char after this SBuf end
652 *
653 * No checks are made that the space returned is safe, checking that is
654 * up to the caller.
655 */
656 char * bufEnd() const {return (store_->mem+off_+len_);}
657
658 /**
659 * Try to guesstimate how big a MemBlob to allocate.
2f8abb64 660 * The result is guaranteed to be to be at least the desired size.
62842d40 661 */
fdd1982c 662 size_type estimateCapacity(size_type desired) const {return (2*desired);}
412da427 663
412da427
FC
664 void reAlloc(size_type newsize);
665
a452bc8b 666 void cow(size_type minsize = npos);
412da427 667
ebaabe74 668 void checkAccessBounds(const size_type pos) const { Must(pos < length()); }
62842d40 669
672337d1
CT
670 /** Exports a writable pointer to the SBuf internal storage.
671 * \warning Use with EXTREME caution, this is a dangerous operation.
672 *
673 * Returns a pointer to the first unused byte in the SBuf's storage,
674 * which can be be used for appending. At least minSize bytes will
675 * be available for writing.
676 * The returned pointer must not be stored by the caller, as it will
677 * be invalidated by the first call to a non-const method call
678 * on the SBuf.
679 * This call guarantees to never return nullptr.
680 * \see reserveSpace
681 * \note Unlike reserveSpace(), this method does not guarantee exclusive
682 * buffer ownership. It is instead optimized for a one writer
683 * (appender), many readers scenario by avoiding unnecessary
684 * copying and allocations.
ebaabe74 685 * \throw std::exception if the user tries to allocate a too big SBuf
672337d1
CT
686 */
687 char *rawSpace(size_type minSize);
688
7cbd3256
FC
689 /** Low-level append operation
690 *
691 * Takes as input a contiguous area of memory and appends its contents
692 * to the SBuf, taking care of memory management. Does no bounds checking
693 * on the supplied memory buffer, it is the duty of the caller to ensure
694 * that the supplied area is valid.
695 */
696 SBuf& lowAppend(const char * memArea, size_type areaSize);
412da427
FC
697};
698
19e97cf0
AR
699/// Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
700class SBufReservationRequirements
701{
702public:
703 typedef SBuf::size_type size_type;
704
705 /*
706 * Parameters are listed in the reverse order of importance: Satisfaction of
707 * the lower-listed requirements may violate the higher-listed requirements.
ecf0d881 708 * For example, idealSpace has no effect unless it exceeds minSpace.
19e97cf0
AR
709 */
710 size_type idealSpace = 0; ///< if allocating anyway, provide this much space
ecf0d881 711 size_type minSpace = 0; ///< allocate [at least this much] if spaceSize() is smaller
19e97cf0
AR
712 size_type maxCapacity = SBuf::maxSize; ///< do not allocate more than this
713 bool allowShared = true; ///< whether sharing our storage with others is OK
714};
715
496a9e97 716/// ostream output operator
62842d40
FC
717inline std::ostream &
718operator <<(std::ostream& os, const SBuf& S)
719{
720 return S.print(os);
721}
412da427 722
37cf7314
AR
723/// Returns a lower-cased copy of its parameter.
724inline SBuf
725ToUpper(SBuf buf)
726{
727 buf.toUpper();
728 return buf;
729}
730
731/// Returns an upper-cased copy of its parameter.
732inline SBuf
733ToLower(SBuf buf)
734{
735 buf.toLower();
736 return buf;
737}
738
3f0e38d6
AJ
739/**
740 * Copy an SBuf into a C-string.
741 *
742 * Guarantees that the output is a c-string of length
743 * no more than SBuf::length()+1 by appending a \0 byte
744 * to the C-string copy of the SBuf contents.
745 *
746 * \note The destination c-string memory MUST be of at least
747 * length()+1 bytes.
748 *
749 * No protection is added to prevent \0 bytes within the string.
750 * Unexpectedly short strings are a problem for the receiver
751 * to deal with if it cares.
752 *
753 * Unlike SBuf::c_str() does not alter the SBuf in any way.
754 */
755inline void
756SBufToCstring(char *d, const SBuf &s)
757{
758 s.copy(d, s.length());
759 d[s.length()] = '\0'; // 0-terminate the destination
760 debugs(1, DBG_DATA, "built c-string '" << d << "' from " << s);
761}
762
763/**
764 * Copy an SBuf into a C-string.
765 *
766 * \see SBufToCstring(char *d, const SBuf &s)
767 *
768 * \returns A dynamically allocated c-string based on SBuf.
769 * Use xfree() / safe_free() to release the c-string.
770 */
771inline char *
772SBufToCstring(const SBuf &s)
773{
774 char *d = static_cast<char*>(xmalloc(s.length()+1));
775 SBufToCstring(d, s);
776 return d;
777}
778
8a3e1749
FC
779inline
780SBufIterator::SBufIterator(const SBuf &s, size_type pos)
02620563 781 : iter(s.rawContent()+pos)
8a3e1749
FC
782{}
783
784inline bool
785SBufIterator::operator==(const SBufIterator &s) const
786{
787 // note: maybe the sbuf comparison is unnecessary?
02620563 788 return iter == s.iter;
8a3e1749
FC
789}
790
791inline bool
792SBufIterator::operator!=(const SBufIterator &s) const
793{
794 // note: maybe the sbuf comparison is unnecessary?
02620563 795 return iter != s.iter;
8a3e1749
FC
796}
797
412da427 798#endif /* SQUID_SBUF_H */
132d9943 799