2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 24 SBuf */
14 #include "base/InstanceId.h"
17 #include "sbuf/MemBlob.h"
18 #include "SBufExceptions.h"
19 #include "SquidString.h"
29 /* SBuf placeholder for printf */
31 #define SQUIDSBUFPH "%.*s"
32 #define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent()
33 #endif /* SQUIDSBUFPH */
35 // TODO: move within SBuf and rename
42 * Container for various SBuf class-wide statistics.
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.
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
58 uint64_t moves
; ///<number of move constructions/assignments
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
66 uint64_t nulTerminate
; ///<number of c_str() terminations
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
76 ///Dump statistics to an ostream.
77 std::ostream
& dump(std::ostream
&os
) const;
80 SBufStats
& operator +=(const SBufStats
&);
86 /** Forward input const_iterator for SBufs
88 * Please note that any operation on the underlying SBuf may invalidate
89 * all iterators over it, resulting in undefined behavior by them.
91 class SBufIterator
: public std::iterator
<std::input_iterator_tag
, char>
95 typedef MemBlob::size_type size_type
;
96 bool operator==(const SBufIterator
&s
) const;
97 bool operator!=(const SBufIterator
&s
) const;
99 const char &operator*() const { return *iter
; }
100 SBufIterator
& operator++() { ++iter
; return *this; }
103 SBufIterator(const SBuf
&, size_type
);
108 /** Reverse input const_iterator for SBufs
110 * Please note that any operation on the underlying SBuf may invalidate
111 * all iterators over it, resulting in undefined behavior by them.
113 class SBufReverseIterator
: public SBufIterator
117 SBufReverseIterator
& operator++() { --iter
; return *this;}
118 const char &operator*() const { return *(iter
-1); }
120 SBufReverseIterator(const SBuf
&s
, size_type sz
) : SBufIterator(s
,sz
) {}
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.
132 typedef MemBlob::size_type size_type
;
133 typedef SBufIterator const_iterator
;
134 typedef SBufReverseIterator const_reverse_iterator
;
135 static const size_type npos
= 0xffffffff; // max(uint32_t)
137 /// Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
138 static const size_type maxSize
= 0xfffffff;
140 /// create an empty (zero-size) SBuf
143 #if __cplusplus >= 201103L
144 SBuf(SBuf
&& S
) : store_(std::move(S
.store_
)), off_(S
.off_
), len_(S
.len_
) {
146 S
.store_
=NULL
; //RefCount supports NULL, and S is about to be destructed
152 /** Constructor: import c-style string
154 * Create a new SBuf containing a COPY of the contents of the
156 * \param S the c string to be copied
157 * \param n how many bytes to import into the SBuf. If it is npos
158 * or unspecified, imports to end-of-cstring
159 * \note it is the caller's responsibility not to go out of bounds
160 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
162 explicit SBuf(const char *S
, size_type n
);
163 explicit SBuf(const char *S
);
165 /** Constructor: import SquidString, copying contents.
167 * This method will be removed once SquidString has gone.
169 explicit SBuf(const String
&S
);
171 /// Constructor: import std::string. Contents are copied.
172 explicit SBuf(const std::string
&s
);
176 /** Explicit assignment.
178 * Current SBuf will share backing store with the assigned one.
180 SBuf
& assign(const SBuf
&S
);
182 /** Assignment operator.
184 * Current SBuf will share backing store with the assigned one.
186 SBuf
& operator =(const SBuf
& S
) {return assign(S
);}
187 #if __cplusplus >= 201103L
188 SBuf
& operator =(SBuf
&&S
) {
191 store_
= std::move(S
.store_
);
194 S
.store_
= NULL
; //RefCount supports NULL, and S is about to be destructed
202 /** Import a c-string into a SBuf, copying the data.
204 * It is the caller's duty to free the imported string, if needed.
205 * \param S the c string to be copied
206 * \param n how many bytes to import into the SBuf. If it is npos
207 * or unspecified, imports to end-of-cstring
208 * \note it is the caller's responsibility not to go out of bounds
209 * \note to assign a std::string use the pattern:
210 * assign(stdstr.data(), stdstd.length())
212 SBuf
& assign(const char *S
, size_type n
);
213 SBuf
& assign(const char *S
) {return assign(S
,npos
);}
215 /** Assignment operator. Copy a NULL-terminated c-style string into a SBuf.
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.
221 SBuf
& operator =(const char *S
) {return assign(S
);}
223 /** reset the SBuf as if it was just created.
225 * Resets the SBuf to empty, memory is freed lazily.
231 * Append the supplied SBuf to the current one; extend storage as needed.
233 SBuf
& append(const SBuf
& S
);
235 /// Append a single character. The character may be NUL (\0).
236 SBuf
& append(const char c
);
238 /** Append operation for C-style strings.
240 * Append the supplied c-string to the SBuf; extend storage
243 * \param S the c string to be copied. Can be NULL.
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,
247 * \note to append a std::string use the pattern
248 * cstr_append(stdstr.data(), stdstd.length())
250 SBuf
& append(const char * S
, size_type Ssize
);
251 SBuf
& append(const char * S
) { return append(S
,npos
); }
253 /** Assignment operation with printf(3)-style definition
254 * \note arguments may be evaluated more than once, be careful
257 SBuf
& Printf(const char *fmt
, ...);
259 /** Append operation with printf-style arguments
260 * \note arguments may be evaluated more than once, be careful
263 SBuf
& appendf(const char *fmt
, ...);
265 /** Append operation, with vsprintf(3)-style arguments.
266 * \note arguments may be evaluated more than once, be careful
269 SBuf
& vappendf(const char *fmt
, va_list vargs
);
271 /// print the SBuf contents to the supplied ostream
272 std::ostream
& print(std::ostream
&os
) const;
274 /** print SBuf contents and debug information about the SBuf to an ostream
276 * Debug function, dumps to a stream informations on the current SBuf,
277 * including low-level details and statistics.
279 std::ostream
& dump(std::ostream
&os
) const;
281 /** random-access read to any char within the SBuf
283 * does not check access bounds. If you need that, use at()
285 char operator [](size_type pos
) const {++stats
.getChar
; return store_
->mem
[off_
+pos
];}
287 /** random-access read to any char within the SBuf.
289 * \throw OutOfBoundsException when access is out of bounds
290 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
292 char at(size_type pos
) const {checkAccessBounds(pos
); return operator[](pos
);}
294 /** direct-access set a byte at a specified operation.
296 * \param pos the position to be overwritten
297 * \param toset the value to be written
298 * \throw OutOfBoundsException when pos is of bounds
299 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
300 * \note performs a copy-on-write if needed.
302 void setAt(size_type pos
, char toset
);
304 /** compare to other SBuf, str(case)cmp-style
306 * \param isCaseSensitive one of caseSensitive or caseInsensitive
307 * \param n compare up to this many bytes. if npos (default), compare whole SBufs
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
312 int compare(const SBuf
&S
, const SBufCaseSensitive isCaseSensitive
, const size_type n
) const;
313 int compare(const SBuf
&S
, const SBufCaseSensitive isCaseSensitive
) const {
314 return compare(S
, isCaseSensitive
, npos
);
317 /// shorthand version for compare()
318 inline int cmp(const SBuf
&S
, const size_type n
) const {
319 return compare(S
,caseSensitive
,n
);
321 inline int cmp(const SBuf
&S
) const {
322 return compare(S
,caseSensitive
,npos
);
325 /// shorthand version for case-insensitive compare()
326 inline int caseCmp(const SBuf
&S
, const size_type n
) const {
327 return compare(S
,caseInsensitive
,n
);
329 inline int caseCmp(const SBuf
&S
) const {
330 return compare(S
,caseInsensitive
,npos
);
333 /// Comparison with a C-string.
334 int compare(const char *s
, const SBufCaseSensitive isCaseSensitive
, const size_type n
) const;
335 int compare(const char *s
, const SBufCaseSensitive isCaseSensitive
) const {
336 return compare(s
,isCaseSensitive
,npos
);
339 /// Shorthand version for C-string compare().
340 inline int cmp(const char *S
, const size_type n
) const {
341 return compare(S
,caseSensitive
,n
);
343 inline int cmp(const char *S
) const {
344 return compare(S
,caseSensitive
,npos
);
347 /// Shorthand version for case-insensitive C-string compare().
348 inline int caseCmp(const char *S
, const size_type n
) const {
349 return compare(S
,caseInsensitive
,n
);
351 inline int caseCmp(const char *S
) const {
352 return compare(S
,caseInsensitive
,npos
);
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
360 bool startsWith(const SBuf
&S
, const SBufCaseSensitive isCaseSensitive
= caseSensitive
) const;
362 bool operator ==(const SBuf
& S
) const;
363 bool operator !=(const SBuf
& S
) const;
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);}
369 /** Consume bytes at the head of the SBuf
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.
375 * npos (or no argument) means 'to the end of SBuf'
376 * \return a new SBuf containing the consumed bytes.
378 SBuf
consume(size_type n
= npos
);
380 /// gets global statistic informations
381 static const SBufStats
& GetStats();
383 /** Copy SBuf contents into user-supplied C buffer.
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.
389 size_type
copy(char *dest
, size_type n
) const;
391 /** exports a pointer to the SBuf internal storage.
392 * \warning ACCESSING RAW STORAGE IS DANGEROUS!
394 * Returns a ead-only pointer to SBuf's content. No terminating null
395 * character is appended (use c_str() for that).
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.
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
409 * SBuf foo("some string");
410 * const char *bar = foo.rawContent();
411 * doSomething(bar); //safe
412 * foo.append(" other string");
413 * doSomething(bar); //unsafe
416 const char* rawContent() const;
418 /** Exports a writable pointer to the SBuf internal storage.
419 * \warning Use with EXTREME caution, this is a dangerous operation.
421 * Returns a pointer to the first unused byte in the SBuf's storage,
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
425 * be invalidated by the first call to a non-const method call
427 * This call guarantees to never return NULL.
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.
433 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
435 char *rawSpace(size_type minSize
);
437 /** Obtain how much free space is available in the backing store.
439 * \note: unless the client just cow()ed, it is not guaranteed that
440 * the free space can be used.
442 size_type
spaceSize() const { return store_
->spaceSize(); }
444 /** Force a SBuf's size
445 * \warning use with EXTREME caution, this is a dangerous operation
447 * Adapt the SBuf internal state after external interference
448 * such as writing into it via rawSpace.
449 * \throw TextException if SBuf doesn't have exclusive ownership of store
450 * \throw SBufTooBigException if new size is bigger than available store space
452 void forceSize(size_type newSize
);
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
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.
466 * \note the memory management system guarantees that the exported region
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
473 /// Returns the number of bytes stored in SBuf.
474 size_type
length() const {return len_
;}
476 /** Get the length of the SBuf, as a signed integer
478 * Compatibility function for printf(3) which requires a signed int
479 * \throw SBufTooBigException if the SBuf is too big for a signed integer
481 int plength() const {
482 if (length()>INT_MAX
)
483 throw SBufTooBigException(__FILE__
, __LINE__
);
484 return static_cast<int>(length());
487 /** Check whether the SBuf is empty
489 * \return true if length() == 0
491 bool isEmpty() const {return (len_
==0);}
493 /** Request to guarantee the SBuf's free store space.
495 * After the reserveSpace request, the SBuf is guaranteed to have at
496 * least minSpace bytes of unused backing store following the currently
497 * used portion and single ownership of the backing store.
498 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
500 void reserveSpace(size_type minSpace
) {
501 Must(minSpace
<= maxSize
);
502 Must(length() <= maxSize
- minSpace
);
503 reserveCapacity(length()+minSpace
);
506 /** Request to guarantee the SBuf's store capacity
508 * After this method is called, the SBuf is guaranteed to have at least
509 * minCapacity bytes of total buffer size, including the currently-used
510 * portion; it is also guaranteed that after this call this SBuf
511 * has unique ownership of the underlying memory store.
512 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
514 void reserveCapacity(size_type minCapacity
);
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.
521 * \param pos start sub-stringing from this byte. If it is
522 * npos or it is greater than the SBuf length, the SBuf is cleared and
523 * an empty SBuf is returned.
524 * \param n maximum number of bytes of the resulting SBuf.
525 * npos means "to end of SBuf".
526 * if it is 0, the SBuf is cleared and an empty SBuf is returned.
527 * if it overflows the end of the SBuf, it is capped to the end of SBuf
530 SBuf
& chop(size_type pos
, size_type n
= npos
);
532 /** Remove characters in the toremove set at the beginning, end or both
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
539 SBuf
& trim(const SBuf
&toRemove
, bool atBeginning
= true, bool atEnd
= true);
541 /** Extract a part of the current SBuf.
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.
547 SBuf
substr(size_type pos
, size_type n
= npos
) const;
549 /** Find first occurrence of character in SBuf
551 * Returns the index in the SBuf of the first occurrence of char c.
552 * \return npos if the char was not found
553 * \param startPos if specified, ignore any occurrences before that position
554 * if startPos is npos or greater than length() npos is always returned
555 * if startPos is less than zero, it is ignored
557 size_type
find(char c
, size_type startPos
= 0) const;
559 /** Find first occurrence of SBuf in SBuf.
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
564 * if startPos is npos or greater than length() npos is always returned
565 * \return npos if the SBuf was not found
567 size_type
find(const SBuf
& str
, size_type startPos
= 0) const;
569 /** Find last occurrence of character in SBuf
571 * Returns the index in the SBuf of the last occurrence of char c.
572 * \return npos if the char was not found
573 * \param endPos if specified, ignore any occurrences after that position.
574 * if npos or greater than length(), the whole SBuf is considered
576 size_type
rfind(char c
, size_type endPos
= npos
) const;
578 /** Find last occurrence of SBuf in SBuf
580 * Returns the index in the SBuf of the last occurrence of the
581 * sequence contained in the str argument.
582 * \return npos if the sequence was not found
583 * \param endPos if specified, ignore any occurrences after that position
584 * if npos or greater than length(), the whole SBuf is considered
586 size_type
rfind(const SBuf
&str
, size_type endPos
= npos
) const;
588 /** Find first occurrence of character of set in SBuf
590 * Finds the first occurrence of ANY of the characters in the supplied set in
592 * \return npos if no character in the set could be found
593 * \param startPos if specified, ignore any occurrences before that position
594 * if npos, then npos is always returned
596 * TODO: rename to camelCase
598 size_type
findFirstOf(const CharacterSet
&set
, size_type startPos
= 0) const;
600 /** Find last occurrence of character of set in SBuf
602 * Finds the last occurrence of ANY of the characters in the supplied set in
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
608 size_type
findLastOf(const CharacterSet
&set
, size_type endPos
= npos
) const;
610 /** Find first occurrence character NOT in character set
612 * \return npos if all characters in the SBuf are from set
613 * \param startPos if specified, ignore any occurrences before that position
614 * if npos, then npos is always returned
616 * TODO: rename to camelCase
618 size_type
findFirstNotOf(const CharacterSet
&set
, size_type startPos
= 0) const;
620 /** Find last occurrence character NOT in character set
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
626 size_type
findLastNotOf(const CharacterSet
&set
, size_type endPos
= npos
) const;
630 * sscanf re-implementation. Non-const, and not \0-clean.
631 * \return same as sscanf
634 int scanf(const char *format
, ...);
636 /// converts all characters to lower case; \see man tolower(3)
639 /// converts all characters to upper case; \see man toupper(3)
642 /** String export function
643 * converts the SBuf to a legacy String, by copy.
646 String
toString() const;
648 /// std::string export function
649 std::string
toStdString() const { return std::string(buf(),length()); }
651 const_iterator
begin() const {
652 return const_iterator(*this, 0);
655 const_iterator
end() const {
656 return const_iterator(*this, length());
659 const_reverse_iterator
rbegin() const {
660 return const_reverse_iterator(*this, length());
663 const_reverse_iterator
rend() const {
664 return const_reverse_iterator(*this, 0);
667 // TODO: possibly implement erase() similar to std::string's erase
668 // TODO: possibly implement a replace() call
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.
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
))
688 MemBlob::Pointer locket
;
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
697 /// SBuf object identifier; does not change when contents do,
698 /// including during assignment
699 const InstanceId
<SBuf
> id
;
701 /** obtain prototype store
703 * Just-created SBufs all share to the same MemBlob.
704 * This call instantiates and returns it.
706 static MemBlob::Pointer
GetStorePrototype();
709 * obtains a char* to the beginning of this SBuf in memory.
710 * \note the obtained string is NOT null-terminated.
712 char * buf() const {return (store_
->mem
+off_
);}
714 /** returns the pointer to the first char after this SBuf end
716 * No checks are made that the space returned is safe, checking that is
719 char * bufEnd() const {return (store_
->mem
+off_
+len_
);}
722 * Try to guesstimate how big a MemBlob to allocate.
723 * The result is guarranteed to be to be at least the desired size.
725 size_type
estimateCapacity(size_type desired
) const {return (2*desired
);}
727 void reAlloc(size_type newsize
);
729 void cow(size_type minsize
= npos
);
731 void checkAccessBounds(size_type pos
) const;
733 /** Low-level append operation
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.
740 SBuf
& lowAppend(const char * memArea
, size_type areaSize
);
743 /// ostream output operator
744 inline std::ostream
&
745 operator <<(std::ostream
& os
, const SBuf
& S
)
750 /// Returns a lower-cased copy of its parameter.
758 /// Returns an upper-cased copy of its parameter.
767 * Copy an SBuf into a C-string.
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.
773 * \note The destination c-string memory MUST be of at least
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.
780 * Unlike SBuf::c_str() does not alter the SBuf in any way.
783 SBufToCstring(char *d
, const SBuf
&s
)
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
);
791 * Copy an SBuf into a C-string.
793 * \see SBufToCstring(char *d, const SBuf &s)
795 * \returns A dynamically allocated c-string based on SBuf.
796 * Use xfree() / safe_free() to release the c-string.
799 SBufToCstring(const SBuf
&s
)
801 char *d
= static_cast<char*>(xmalloc(s
.length()+1));
807 SBufIterator::SBufIterator(const SBuf
&s
, size_type pos
)
808 : iter(s
.rawContent()+pos
)
812 SBufIterator::operator==(const SBufIterator
&s
) const
814 // note: maybe the sbuf comparison is unnecessary?
815 return iter
== s
.iter
;
819 SBufIterator::operator!=(const SBufIterator
&s
) const
821 // note: maybe the sbuf comparison is unnecessary?
822 return iter
!= s
.iter
;
825 #endif /* SQUID_SBUF_H */