]> git.ipfire.org Git - thirdparty/squid.git/blob - src/SBuf.h
Cleanup: un-wrap C++ header includes
[thirdparty/squid.git] / src / SBuf.h
1 /*
2 * SQUID Web Proxy Cache http://www.squid-cache.org/
3 * ----------------------------------------------------------
4 *
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.
13 *
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.
18 *
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.
23 *
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.
27 */
28
29 #ifndef SQUID_SBUF_H
30 #define SQUID_SBUF_H
31
32 #include "base/InstanceId.h"
33 #include "MemBlob.h"
34 #include "SBufExceptions.h"
35 #include "SquidString.h"
36
37 #include <climits>
38 #include <cstdarg>
39 #include <iosfwd>
40 #if HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43
44 /* SBuf placeholder for printf */
45 #ifndef SQUIDSBUFPH
46 #define SQUIDSBUFPH "%.*s"
47 #define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent()
48 #endif /* SQUIDSBUFPH */
49
50 // TODO: move within SBuf and rename
51 typedef enum {
52 caseSensitive,
53 caseInsensitive
54 } SBufCaseSensitive;
55
56 /**
57 * Container for various SBuf class-wide statistics.
58 *
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.
62 */
63 class SBufStats
64 {
65 public:
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
88
89 ///Dump statistics to an ostream.
90 std::ostream& dump(std::ostream &os) const;
91 SBufStats();
92
93 SBufStats& operator +=(const SBufStats&);
94 };
95
96 class CharacterSet;
97
98 /**
99 * A String or Buffer.
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.
103 */
104 class SBuf
105 {
106 public:
107 typedef MemBlob::size_type size_type;
108 static const size_type npos = 0xffffffff; // max(uint32_t)
109
110 /// Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
111 static const size_type maxSize = 0xfffffff;
112
113 /// create an empty (zero-size) SBuf
114 SBuf();
115 SBuf(const SBuf &S);
116
117 /** Constructor: import c-style string
118 *
119 * Create a new SBuf containing a COPY of the contents of the
120 * c-string
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
126 */
127 explicit SBuf(const char *S, size_type n = npos);
128
129 /** Constructor: import SquidString, copying contents.
130 *
131 * This method will be removed once SquidString has gone.
132 */
133 explicit SBuf(const String &S);
134
135 /// Constructor: import std::string. Contents are copied.
136 explicit SBuf(const std::string &s);
137
138 ~SBuf();
139
140 /** Explicit assignment.
141 *
142 * Current SBuf will share backing store with the assigned one.
143 */
144 SBuf& assign(const SBuf &S);
145
146 /** Assignment operator.
147 *
148 * Current SBuf will share backing store with the assigned one.
149 */
150 SBuf& operator =(const SBuf & S) {return assign(S);}
151
152 /** Import a c-string into a SBuf, copying the data.
153 *
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())
161 */
162 SBuf& assign(const char *S, size_type n = npos);
163
164 /** Assignment operator. Copy a NULL-terminated c-style string into a SBuf.
165 *
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.
168 * \note not \0-clean
169 */
170 SBuf& operator =(const char *S) {return assign(S);}
171
172 /** reset the SBuf as if it was just created.
173 *
174 * Resets the SBuf to empty, memory is freed lazily.
175 */
176 void clear();
177
178 /** Append operation
179 *
180 * Append the supplied SBuf to the current one; extend storage as needed.
181 */
182 SBuf& append(const SBuf & S);
183
184 /** Append operation for C-style strings.
185 *
186 * Append the supplied c-string to the SBuf; extend storage
187 * as needed.
188 *
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,
192 * Ssize is ignored.
193 * \note to append a std::string use the pattern
194 * cstr_append(stdstr.data(), stdstd.length())
195 */
196 SBuf& append(const char * S, size_type Ssize = npos);
197
198 /** Assignment operation with printf(3)-style definition
199 * \note arguments may be evaluated more than once, be careful
200 * of side-effects
201 */
202 SBuf& Printf(const char *fmt, ...);
203
204 /** Append operation with printf-style arguments
205 * \note arguments may be evaluated more than once, be careful
206 * of side-effects
207 */
208 SBuf& appendf(const char *fmt, ...);
209
210 /** Append operation, with vsprintf(3)-style arguments.
211 * \note arguments may be evaluated more than once, be careful
212 * of side-effects
213 */
214 SBuf& vappendf(const char *fmt, va_list vargs);
215
216 /// print the SBuf contents to the supplied ostream
217 std::ostream& print(std::ostream &os) const;
218
219 /** print SBuf contents and debug information about the SBuf to an ostream
220 *
221 * Debug function, dumps to a stream informations on the current SBuf,
222 * including low-level details and statistics.
223 */
224 std::ostream& dump(std::ostream &os) const;
225
226 /** random-access read to any char within the SBuf
227 *
228 * does not check access bounds. If you need that, use at()
229 */
230 char operator [](size_type pos) const {++stats.getChar; return store_->mem[off_+pos];}
231
232 /** random-access read to any char within the SBuf.
233 *
234 * \throw OutOfBoundsException when access is out of bounds
235 * \note bounds is 0 <= pos < length(); caller must pay attention to signedness
236 */
237 char at(size_type pos) const {checkAccessBounds(pos); return operator[](pos);}
238
239 /** direct-access set a byte at a specified operation.
240 *
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.
246 */
247 void setAt(size_type pos, char toset);
248
249 /** compare to other SBuf, str(case)cmp-style
250 *
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
256 */
257 int compare(const SBuf &S, SBufCaseSensitive isCaseSensitive, size_type n = npos) const;
258
259 /// shorthand version for compare
260 inline int cmp(const SBuf &S, size_type n = npos) const {
261 return compare(S,caseSensitive,n);
262 }
263
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);
267 }
268
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
273 */
274 bool startsWith(const SBuf &S, SBufCaseSensitive isCaseSensitive = caseSensitive) const;
275
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);}
282
283 /** Consume bytes at the head of the SBuf
284 *
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.
291 */
292 SBuf consume(size_type n = npos);
293
294 /// gets global statistic informations
295 static const SBufStats& GetStats();
296
297 /** Copy SBuf contents into user-supplied C buffer.
298 *
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.
302 */
303 size_type copy(char *dest, size_type n) const;
304
305 /** exports a pointer to the SBuf internal storage.
306 * \warning ACCESSING RAW STORAGE IS DANGEROUS!
307 *
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.
317 * \see c_str
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
321 * it. For example:
322 * \code
323 * SBuf foo("some string");
324 * const char *bar = foo.rawContent();
325 * doSomething(bar); //safe
326 * foo.append(" other string");
327 * doSomething(bar); //unsafe
328 * \endcode
329 */
330 const char* rawContent() const;
331
332 /** Exports a writable pointer to the SBuf internal storage.
333 * \warning Use with EXTREME caution, this is a dangerous operation.
334 *
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
340 * on the SBuf.
341 * This call guarantees to never return NULL.
342 * \see reserveSpace
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
348 */
349 char *rawSpace(size_type minSize);
350
351 /** Obtain how much free space is available in the backing store.
352 *
353 * \note: unless the client just cow()ed, it is not guaranteed that
354 * the free space can be used.
355 */
356 size_type spaceSize() const { return store_->spaceSize(); }
357
358 /** Force a SBuf's size
359 * \warning use with EXTREME caution, this is a dangerous operation
360 *
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
365 */
366 void forceSize(size_type newSize);
367
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
371 *
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.
379 * \see rawContent
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
384 */
385 const char* c_str();
386
387 /// Returns the number of bytes stored in SBuf.
388 size_type length() const {return len_;}
389
390 /** Get the length of the SBuf, as a signed integer
391 *
392 * Compatibility function for printf(3) which requires a signed int
393 * \throw SBufTooBigException if the SBuf is too big for a signed integer
394 */
395 int plength() const {
396 if (length()>INT_MAX)
397 throw SBufTooBigException(__FILE__, __LINE__);
398 return static_cast<int>(length());
399 }
400
401 /** Check whether the SBuf is empty
402 *
403 * \return true if length() == 0
404 */
405 bool isEmpty() const {return (len_==0);}
406
407 /** Request to guarantee the SBuf's free store space.
408 *
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
413 */
414 void reserveSpace(size_type minSpace) {
415 Must(minSpace <= maxSize);
416 Must(length() <= maxSize - minSpace);
417 reserveCapacity(length()+minSpace);
418 }
419
420 /** Request to guarantee the SBuf's store capacity
421 *
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
427 */
428 void reserveCapacity(size_type minCapacity);
429
430 /** slicing method
431 *
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
442 * \see substr, trim
443 */
444 SBuf& chop(size_type pos, size_type n = npos);
445
446 /** Remove characters in the toremove set at the beginning, end or both
447 *
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
452 */
453 SBuf& trim(const SBuf &toRemove, bool atBeginning = true, bool atEnd = true);
454
455 /** Extract a part of the current SBuf.
456 *
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.
459 * \see trim, chop
460 */
461 SBuf substr(size_type pos, size_type n = npos) const;
462
463 /** Find first occurrence of character in SBuf
464 *
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
470 */
471 size_type find(char c, size_type startPos = 0) const;
472
473 /** Find first occurrence of SBuf in SBuf.
474 *
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
480 */
481 size_type find(const SBuf & str, size_type startPos = 0) const;
482
483 /** Find last occurrence of character in SBuf
484 *
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
489 */
490 size_type rfind(char c, size_type endPos = npos) const;
491
492 /** Find last occurrence of SBuf in SBuf
493 *
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
499 */
500 size_type rfind(const SBuf &str, size_type endPos = npos) const;
501
502 /** Find first occurrence of character of set in SBuf
503 *
504 * Finds the first occurrence of ANY of the characters in the supplied set in
505 * the SBuf.
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
509 *
510 * TODO: rename to camelCase
511 */
512 size_type findFirstOf(const CharacterSet &set, size_type startPos = 0) const;
513
514 /** Find first occurrence character NOT in character set
515 *
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
519 *
520 * TODO: rename to camelCase
521 */
522 size_type findFirstNotOf(const CharacterSet &set, size_type startPos = 0) const;
523
524 /** sscanf-alike
525 *
526 * sscanf re-implementation. Non-const, and not \0-clean.
527 * \return same as sscanf
528 * \see man sscanf(3)
529 */
530 int scanf(const char *format, ...);
531
532 /** Lower-case SBuf
533 *
534 * Returns a lower-cased COPY of the SBuf
535 * \see man tolower(3)
536 */
537 SBuf toLower() const;
538
539 /** Upper-case SBuf
540 *
541 * Returns an upper-cased COPY of the SBuf
542 * \see man toupper(3)
543 */
544 SBuf toUpper() const;
545
546 /** String export function
547 * converts the SBuf to a legacy String, by copy.
548 * \deprecated
549 */
550 String toString() const;
551
552 /// std::string export function
553 std::string toStdString() const { return std::string(buf(),length()); }
554
555 // TODO: possibly implement erase() similar to std::string's erase
556 // TODO: possibly implement a replace() call
557 private:
558
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
563
564 /// SBuf object identifier; does not change when contents do,
565 /// including during assignment
566 const InstanceId<SBuf> id;
567
568 /** obtain prototype store
569 *
570 * Just-created SBufs all share to the same MemBlob.
571 * This call instantiates and returns it.
572 */
573 static MemBlob::Pointer GetStorePrototype();
574
575 /**
576 * obtains a char* to the beginning of this SBuf in memory.
577 * \note the obtained string is NOT null-terminated.
578 */
579 char * buf() const {return (store_->mem+off_);}
580
581 /** returns the pointer to the first char after this SBuf end
582 *
583 * No checks are made that the space returned is safe, checking that is
584 * up to the caller.
585 */
586 char * bufEnd() const {return (store_->mem+off_+len_);}
587
588 /**
589 * Try to guesstimate how big a MemBlob to allocate.
590 * The result is guarranteed to be to be at least the desired size.
591 */
592 size_type estimateCapacity(size_type desired) const {return (2*desired);}
593
594 void reAlloc(size_type newsize);
595
596 void cow(size_type minsize = npos);
597
598 void checkAccessBounds(size_type pos) const;
599
600 /** Low-level append operation
601 *
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.
606 */
607 SBuf& lowAppend(const char * memArea, size_type areaSize);
608 };
609
610 /// ostream output operator
611 inline std::ostream &
612 operator <<(std::ostream& os, const SBuf& S)
613 {
614 return S.print(os);
615 }
616
617 #endif /* SQUID_SBUF_H */