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