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