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