2 * SQUID Web Proxy Cache http://www.squid-cache.org/
3 * ----------------------------------------------------------
5 * Squid is the result of efforts by numerous individuals from
6 * the Internet community; see the CONTRIBUTORS file for full
7 * details. Many organizations have provided support for Squid's
8 * development; see the SPONSORS file for full details. Squid is
9 * Copyrighted (C) 2001 by the Regents of the University of
10 * California; see the COPYRIGHT file for full details. Squid
11 * incorporates software developed and/or copyrighted by other
12 * sources; see the CREDITS file for full details.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 #include "base/InstanceId.h"
34 #include "SBufExceptions.h"
35 #include "SquidString.h"
44 /* SBuf placeholder for printf */
46 #define SQUIDSBUFPH "%.*s"
47 #define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent()
48 #endif /* SQUIDSBUFPH */
50 // TODO: move within SBuf and rename
57 * Container for various SBuf class-wide statistics.
59 * The stats are not completely accurate; they're mostly meant to
60 * understand whether Squid is leaking resources
61 * and whether SBuf is paying off the expected gains.
66 uint64_t alloc
; ///<number of calls to SBuf constructors
67 uint64_t allocCopy
; ///<number of calls to SBuf copy-constructor
68 uint64_t allocFromString
; ///<number of copy-allocations from Strings
69 uint64_t allocFromCString
; ///<number of copy-allocations from c-strings
70 uint64_t assignFast
; ///<number of no-copy assignment operations
71 uint64_t clear
; ///<number of clear operations
72 uint64_t append
; ///<number of append operations
73 uint64_t toStream
; ///<number of write operations to ostreams
74 uint64_t setChar
; ///<number of calls to setAt
75 uint64_t getChar
; ///<number of calls to at() and operator[]
76 uint64_t compareSlow
; ///<number of comparison operations requiring data scan
77 uint64_t compareFast
; ///<number of comparison operations not requiring data scan
78 uint64_t copyOut
; ///<number of data-copies to other forms of buffers
79 uint64_t rawAccess
; ///<number of accesses to raw contents
80 uint64_t chop
; ///<number of chop operations
81 uint64_t trim
; ///<number of trim operations
82 uint64_t find
; ///<number of find operations
83 uint64_t scanf
; ///<number of scanf operations
84 uint64_t caseChange
; ///<number of toUpper and toLower operations
85 uint64_t cowFast
; ///<number of cow operations not actually requiring a copy
86 uint64_t cowSlow
; ///<number of cow operations requiring a copy
87 uint64_t live
; ///<number of currently-allocated SBuf
89 ///Dump statistics to an ostream.
90 std::ostream
& dump(std::ostream
&os
) const;
93 SBufStats
& operator +=(const SBufStats
&);
100 * Features: refcounted backing store, cheap copy and sub-stringing
101 * operations, copy-on-write to isolate change operations to each instance.
102 * Where possible, we're trying to mimic std::string's interface.
107 typedef MemBlob::size_type size_type
;
108 static const size_type npos
= 0xffffffff; // max(uint32_t)
110 /// Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
111 static const size_type maxSize
= 0xfffffff;
113 /// create an empty (zero-size) SBuf
117 /** Constructor: import c-style string
119 * Create a new SBuf containing a COPY of the contents of the
121 * \param S the c string to be copied
122 * \param n how many bytes to import into the SBuf. If it is npos
123 * or unspecified, imports to end-of-cstring
124 * \note it is the caller's responsibility not to go out of bounds
125 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
127 explicit SBuf(const char *S
, size_type n
= npos
);
129 /** Constructor: import SquidString, copying contents.
131 * This method will be removed once SquidString has gone.
133 explicit SBuf(const String
&S
);
135 /// Constructor: import std::string. Contents are copied.
136 explicit SBuf(const std::string
&s
);
140 /** Explicit assignment.
142 * Current SBuf will share backing store with the assigned one.
144 SBuf
& assign(const SBuf
&S
);
146 /** Assignment operator.
148 * Current SBuf will share backing store with the assigned one.
150 SBuf
& operator =(const SBuf
& S
) {return assign(S
);}
152 /** Import a c-string into a SBuf, copying the data.
154 * It is the caller's duty to free the imported string, if needed.
155 * \param S the c string to be copied
156 * \param n how many bytes to import into the SBuf. If it is npos
157 * or unspecified, imports to end-of-cstring
158 * \note it is the caller's responsibility not to go out of bounds
159 * \note to assign a std::string use the pattern:
160 * assign(stdstr.data(), stdstd.length())
162 SBuf
& assign(const char *S
, size_type n
= npos
);
164 /** Assignment operator. Copy a NULL-terminated c-style string into a SBuf.
166 * Copy a c-style string into a SBuf. Shortcut for SBuf.assign(S)
167 * It is the caller's duty to free the imported string, if needed.
170 SBuf
& operator =(const char *S
) {return assign(S
);}
172 /** reset the SBuf as if it was just created.
174 * Resets the SBuf to empty, memory is freed lazily.
180 * Append the supplied SBuf to the current one; extend storage as needed.
182 SBuf
& append(const SBuf
& S
);
184 /** Append operation for C-style strings.
186 * Append the supplied c-string to the SBuf; extend storage
189 * \param S the c string to be copied. Can be NULL.
190 * \param Ssize how many bytes to import into the SBuf. If it is npos
191 * or unspecified, imports to end-of-cstring. If S is NULL,
193 * \note to append a std::string use the pattern
194 * cstr_append(stdstr.data(), stdstd.length())
196 SBuf
& append(const char * S
, size_type Ssize
= npos
);
198 /** Assignment operation with printf(3)-style definition
199 * \note arguments may be evaluated more than once, be careful
202 SBuf
& Printf(const char *fmt
, ...);
204 /** Append operation with printf-style arguments
205 * \note arguments may be evaluated more than once, be careful
208 SBuf
& appendf(const char *fmt
, ...);
210 /** Append operation, with vsprintf(3)-style arguments.
211 * \note arguments may be evaluated more than once, be careful
214 SBuf
& vappendf(const char *fmt
, va_list vargs
);
216 /// print the SBuf contents to the supplied ostream
217 std::ostream
& print(std::ostream
&os
) const;
219 /** print SBuf contents and debug information about the SBuf to an ostream
221 * Debug function, dumps to a stream informations on the current SBuf,
222 * including low-level details and statistics.
224 std::ostream
& dump(std::ostream
&os
) const;
226 /** random-access read to any char within the SBuf
228 * does not check access bounds. If you need that, use at()
230 char operator [](size_type pos
) const {++stats
.getChar
; return store_
->mem
[off_
+pos
];}
232 /** random-access read to any char within the SBuf.
234 * \throw OutOfBoundsException when access is out of bounds
235 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
237 char at(size_type pos
) const {checkAccessBounds(pos
); return operator[](pos
);}
239 /** direct-access set a byte at a specified operation.
241 * \param pos the position to be overwritten
242 * \param toset the value to be written
243 * \throw OutOfBoundsException when pos is of bounds
244 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
245 * \note performs a copy-on-write if needed.
247 void setAt(size_type pos
, char toset
);
249 /** compare to other SBuf, str(case)cmp-style
251 * \param isCaseSensitive one of caseSensitive or caseInsensitive
252 * \param n compare up to this many bytes. if npos (default), compare whole SBufs
253 * \retval >0 argument of the call is greater than called SBuf
254 * \retval <0 argument of the call is smaller than called SBuf
255 * \retval 0 argument of the call has the same contents of called SBuf
257 int compare(const SBuf
&S
, SBufCaseSensitive isCaseSensitive
, size_type n
= npos
) const;
259 /// shorthand version for compare
260 inline int cmp(const SBuf
&S
, size_type n
= npos
) const {
261 return compare(S
,caseSensitive
,n
);
264 /// shorthand version for case-insensitive comparison
265 inline int caseCmp(const SBuf
&S
, size_type n
= npos
) const {
266 return compare(S
,caseInsensitive
,n
);
269 /** check whether the entire supplied argument is a prefix of the SBuf.
270 * \param S the prefix to match against
271 * \param isCaseSensitive one of caseSensitive or caseInsensitive
272 * \retval true argument is a prefix of the SBuf
274 bool startsWith(const SBuf
&S
, SBufCaseSensitive isCaseSensitive
= caseSensitive
) const;
276 bool operator ==(const SBuf
& S
) const;
277 bool operator !=(const SBuf
& S
) const;
278 bool operator <(const SBuf
&S
) const {return (cmp(S
) < 0);}
279 bool operator >(const SBuf
&S
) const {return (cmp(S
) > 0);}
280 bool operator <=(const SBuf
&S
) const {return (cmp(S
) <= 0);}
281 bool operator >=(const SBuf
&S
) const {return (cmp(S
) >= 0);}
283 /** Consume bytes at the head of the SBuf
285 * Consume N chars at SBuf head, or to SBuf's end,
286 * whichever is shorter. If more bytes are consumed than available,
287 * the SBuf is emptied
288 * \param n how many bytes to remove; could be zero.
289 * npos (or no argument) means 'to the end of SBuf'
290 * \return a new SBuf containing the consumed bytes.
292 SBuf
consume(size_type n
= npos
);
294 /// gets global statistic informations
295 static const SBufStats
& GetStats();
297 /** Copy SBuf contents into user-supplied C buffer.
299 * Export a copy of the SBuf's contents into the user-supplied
300 * buffer, up to the user-supplied-length. No zero-termination is performed
301 * \return num the number of actually-copied chars.
303 size_type
copy(char *dest
, size_type n
) const;
305 /** exports a pointer to the SBuf internal storage.
306 * \warning ACCESSING RAW STORAGE IS DANGEROUS!
308 * Returns a ead-only pointer to SBuf's content. No terminating null
309 * character is appended (use c_str() for that).
310 * The returned value points to an internal location whose contents
311 * are guaranteed to remain unchanged only until the next call
312 * to a non-constant member function of the SBuf object. Such a
313 * call may be implicit (e.g., when SBuf is destroyed
314 * upon leaving the current context).
315 * This is a very UNSAFE way of accessing the data.
316 * This call never returns NULL.
318 * \note the memory management system guarantees that the exported region
319 * of memory will remain valid if the caller keeps holding
320 * a valid reference to the SBuf object and does not write or append to
323 * SBuf foo("some string");
324 * const char *bar = foo.rawContent();
325 * doSomething(bar); //safe
326 * foo.append(" other string");
327 * doSomething(bar); //unsafe
330 const char* rawContent() const;
332 /** Exports a writable pointer to the SBuf internal storage.
333 * \warning Use with EXTREME caution, this is a dangerous operation.
335 * Returns a pointer to the first unused byte in the SBuf's storage,
336 * which can be be used for appending. At least minSize bytes will
337 * be available for writing.
338 * The returned pointer must not be stored by the caller, as it will
339 * be invalidated by the first call to a non-const method call
341 * This call guarantees to never return NULL.
343 * \note Unlike reserveSpace(), this method does not guarantee exclusive
344 * buffer ownership. It is instead optimized for a one writer
345 * (appender), many readers scenario by avoiding unnecessary
346 * copying and allocations.
347 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
349 char *rawSpace(size_type minSize
);
351 /** Obtain how much free space is available in the backing store.
353 * \note: unless the client just cow()ed, it is not guaranteed that
354 * the free space can be used.
356 size_type
spaceSize() const { return store_
->spaceSize(); }
358 /** Force a SBuf's size
359 * \warning use with EXTREME caution, this is a dangerous operation
361 * Adapt the SBuf internal state after external interference
362 * such as writing into it via rawSpace.
363 * \throw TextException if SBuf doesn't have exclusive ownership of store
364 * \throw SBufTooBigException if new size is bigger than available store space
366 void forceSize(size_type newSize
);
368 /** exports a null-terminated reference to the SBuf internal storage.
369 * \warning ACCESSING RAW STORAGE IS DANGEROUS! DO NOT EVER USE
370 * THE RETURNED POINTER FOR WRITING
372 * The returned value points to an internal location whose contents
373 * are guaranteed to remain unchanged only until the next call
374 * to a non-constant member function of the SBuf object. Such a
375 * call may be implicit (e.g., when SBuf is destroyed
376 * upon leaving the current context).
377 * This is a very UNSAFE way of accessing the data.
378 * This call never returns NULL.
380 * \note the memory management system guarantees that the exported region
381 * of memory will remain valid will remain valid only if the
382 * caller keeps holding a valid reference to the SBuf object and
383 * does not write or append to it
387 /// Returns the number of bytes stored in SBuf.
388 size_type
length() const {return len_
;}
390 /** Get the length of the SBuf, as a signed integer
392 * Compatibility function for printf(3) which requires a signed int
393 * \throw SBufTooBigException if the SBuf is too big for a signed integer
395 int plength() const {
396 if (length()>INT_MAX
)
397 throw SBufTooBigException(__FILE__
, __LINE__
);
398 return static_cast<int>(length());
401 /** Check whether the SBuf is empty
403 * \return true if length() == 0
405 bool isEmpty() const {return (len_
==0);}
407 /** Request to guarantee the SBuf's free store space.
409 * After the reserveSpace request, the SBuf is guaranteed to have at
410 * least minSpace bytes of unused backing store following the currently
411 * used portion and single ownership of the backing store.
412 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
414 void reserveSpace(size_type minSpace
) {
415 Must(minSpace
<= maxSize
);
416 Must(length() <= maxSize
- minSpace
);
417 reserveCapacity(length()+minSpace
);
420 /** Request to guarantee the SBuf's store capacity
422 * After this method is called, the SBuf is guaranteed to have at least
423 * minCapacity bytes of total buffer size, including the currently-used
424 * portion; it is also guaranteed that after this call this SBuf
425 * has unique ownership of the underlying memory store.
426 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
428 void reserveCapacity(size_type minCapacity
);
432 * Removes SBuf prefix and suffix, leaving a sequence of 'n'
433 * bytes starting from position 'pos', first byte is at pos 0.
434 * It is an in-place-modifying version of substr.
435 * \param pos start sub-stringing from this byte. If it is
436 * npos or it is greater than the SBuf length, the SBuf is cleared and
437 * an empty SBuf is returned.
438 * \param n maximum number of bytes of the resulting SBuf.
439 * npos means "to end of SBuf".
440 * if it is 0, the SBuf is cleared and an empty SBuf is returned.
441 * if it overflows the end of the SBuf, it is capped to the end of SBuf
444 SBuf
& chop(size_type pos
, size_type n
= npos
);
446 /** Remove characters in the toremove set at the beginning, end or both
448 * \param toremove characters to be removed. Stops chomping at the first
449 * found char not in the set
450 * \param atBeginning if true (default), strips at the beginning of the SBuf
451 * \param atEnd if true (default), strips at the end of the SBuf
453 SBuf
& trim(const SBuf
&toRemove
, bool atBeginning
= true, bool atEnd
= true);
455 /** Extract a part of the current SBuf.
457 * Return a fresh a fresh copy of a portion the current SBuf, which is
458 * left untouched. The same parameter convetions apply as for chop.
461 SBuf
substr(size_type pos
, size_type n
= npos
) const;
463 /** Find first occurrence of character in SBuf
465 * Returns the index in the SBuf of the first occurrence of char c.
466 * \return npos if the char was not found
467 * \param startPos if specified, ignore any occurrences before that position
468 * if startPos is npos or greater than length() npos is always returned
469 * if startPos is less than zero, it is ignored
471 size_type
find(char c
, size_type startPos
= 0) const;
473 /** Find first occurrence of SBuf in SBuf.
475 * Returns the index in the SBuf of the first occurrence of the
476 * sequence contained in the str argument.
477 * \param startPos if specified, ignore any occurrences before that position
478 * if startPos is npos or greater than length() npos is always returned
479 * \return npos if the SBuf was not found
481 size_type
find(const SBuf
& str
, size_type startPos
= 0) const;
483 /** Find last occurrence of character in SBuf
485 * Returns the index in the SBuf of the last occurrence of char c.
486 * \return npos if the char was not found
487 * \param endPos if specified, ignore any occurrences after that position.
488 * if npos or greater than length(), the whole SBuf is considered
490 size_type
rfind(char c
, size_type endPos
= npos
) const;
492 /** Find last occurrence of SBuf in SBuf
494 * Returns the index in the SBuf of the last occurrence of the
495 * sequence contained in the str argument.
496 * \return npos if the sequence was not found
497 * \param endPos if specified, ignore any occurrences after that position
498 * if npos or greater than length(), the whole SBuf is considered
500 size_type
rfind(const SBuf
&str
, size_type endPos
= npos
) const;
502 /** Find first occurrence of character of set in SBuf
504 * Finds the first occurrence of ANY of the characters in the supplied set in
506 * \return npos if no character in the set could be found
507 * \param startPos if specified, ignore any occurrences before that position
508 * if npos, then npos is always returned
510 * TODO: rename to camelCase
512 size_type
findFirstOf(const CharacterSet
&set
, size_type startPos
= 0) const;
514 /** Find first occurrence character NOT in character set
516 * \return npos if all characters in the SBuf are from set
517 * \param startPos if specified, ignore any occurrences before that position
518 * if npos, then npos is always returned
520 * TODO: rename to camelCase
522 size_type
findFirstNotOf(const CharacterSet
&set
, size_type startPos
= 0) const;
526 * sscanf re-implementation. Non-const, and not \0-clean.
527 * \return same as sscanf
530 int scanf(const char *format
, ...);
534 * Returns a lower-cased COPY of the SBuf
535 * \see man tolower(3)
537 SBuf
toLower() const;
541 * Returns an upper-cased COPY of the SBuf
542 * \see man toupper(3)
544 SBuf
toUpper() const;
546 /** String export function
547 * converts the SBuf to a legacy String, by copy.
550 String
toString() const;
552 /// std::string export function
553 std::string
toStdString() const { return std::string(buf(),length()); }
555 // TODO: possibly implement erase() similar to std::string's erase
556 // TODO: possibly implement a replace() call
559 MemBlob::Pointer store_
; ///< memory block, possibly shared with other SBufs
560 size_type off_
; ///< our content start offset from the beginning of shared store_
561 size_type len_
; ///< number of our content bytes in shared store_
562 static SBufStats stats
; ///< class-wide statistics
564 /// SBuf object identifier; does not change when contents do,
565 /// including during assignment
566 const InstanceId
<SBuf
> id
;
568 /** obtain prototype store
570 * Just-created SBufs all share to the same MemBlob.
571 * This call instantiates and returns it.
573 static MemBlob::Pointer
GetStorePrototype();
576 * obtains a char* to the beginning of this SBuf in memory.
577 * \note the obtained string is NOT null-terminated.
579 char * buf() const {return (store_
->mem
+off_
);}
581 /** returns the pointer to the first char after this SBuf end
583 * No checks are made that the space returned is safe, checking that is
586 char * bufEnd() const {return (store_
->mem
+off_
+len_
);}
589 * Try to guesstimate how big a MemBlob to allocate.
590 * The result is guarranteed to be to be at least the desired size.
592 size_type
estimateCapacity(size_type desired
) const {return (2*desired
);}
594 void reAlloc(size_type newsize
);
596 void cow(size_type minsize
= npos
);
598 void checkAccessBounds(size_type pos
) const;
600 /** Low-level append operation
602 * Takes as input a contiguous area of memory and appends its contents
603 * to the SBuf, taking care of memory management. Does no bounds checking
604 * on the supplied memory buffer, it is the duty of the caller to ensure
605 * that the supplied area is valid.
607 SBuf
& lowAppend(const char * memArea
, size_type areaSize
);
610 /// ostream output operator
611 inline std::ostream
&
612 operator <<(std::ostream
& os
, const SBuf
& S
)
617 #endif /* SQUID_SBUF_H */