Merge lp:~kinkie/squid/stringng into lp:squid/v4
- stringng
- Merge into 4
Status: | Needs review |
---|---|
Proposed branch: | lp:~kinkie/squid/stringng |
Merge into: | lp:squid/v4 |
Diff against target: |
4264 lines (+3906/-57) 26 files modified
include/util.h (+1/-1) src/Makefile.am (+58/-11) src/MemBlob.cc (+11/-0) src/MemBlob.h (+2/-0) src/OutOfBoundsException.h (+22/-0) src/SBuf.cc (+887/-0) src/SBuf.cci (+174/-0) src/SBuf.h (+571/-0) src/SBufExceptions.cc (+72/-0) src/SBufExceptions.h (+65/-0) src/SBufExtras.cc (+104/-0) src/SBufExtras.h (+66/-0) src/SBufList.cc (+56/-0) src/SBufList.h (+62/-0) src/SBufStream.h (+141/-0) src/SBufTokenizer.cc (+68/-0) src/SBufTokenizer.h (+149/-0) src/SBufUtil.cc (+64/-0) src/SBufUtil.h (+51/-0) src/SquidString.h (+0/-38) src/StrList.h (+65/-7) src/icmp/Makefile.am (+19/-0) src/tests/SBufFindTest.cc (+418/-0) src/tests/SBufFindTest.h (+85/-0) src/tests/testSBuf.cc (+603/-0) src/tests/testSBuf.h (+92/-0) |
To merge this branch: | bzr merge lp:~kinkie/squid/stringng |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alex Rousskov | Pending | ||
Review via email: mp+70503@code.launchpad.net |
Commit message
Description of the change
String-Buffer class, sporting
- refcounted backing store
- efficient substring operations
- mempools and cachemgr integration
- tokenizer
- ostream interface
- 9552. By Francesco Chemolli
-
Merged from trunk
- 9553. By Francesco Chemolli
-
Fixed unit tests linkage
- 9554. By Francesco Chemolli
-
Merged from trunk
- 9555. By Francesco Chemolli
-
Fixed leftover merge issue
- 9556. By Francesco Chemolli
-
fix merge issue
- 9557. By Francesco Chemolli
-
fix main Makefile.am
- 9558. By Francesco Chemolli
-
Merged from trunk
- 9559. By Francesco Chemolli
-
Updated to reflect latest changes to RefCount API.
- 9560. By Francesco Chemolli
-
Fix src/Makefile.am typo
- 9561. By Francesco Chemolli
-
renamed SBuf::findAny to find_first_of for consistency with std::string
- 9562. By Francesco Chemolli
-
Fixed code formatting in Sbuf
Removed terminate() visibility, functionality now merged into c_str() - 9563. By Francesco Chemolli
-
Review and cleanup.
- 9564. By Francesco Chemolli
-
Merged from trunk
- 9565. By Francesco Chemolli
-
Merged from trunk
- 9566. By Francesco Chemolli
-
Automated source formatting
- 9567. By Francesco Chemolli
-
Removed SBufSplit, clarified that StrList is incomplete work in progress
- 9568. By Francesco Chemolli
-
Updated debug messages in SBuf
- 9569. By Francesco Chemolli
-
Improved SBuf unit tests (thanks Amos). Building but tests failing
- 9570. By Francesco Chemolli
-
Fixed SBuf unit tests. To be completed
- 9571. By Francesco Chemolli
-
Improved SBuf unit tests
- 9572. By Francesco Chemolli
-
Updated debug messages to current standards in SBuf
- 9573. By Francesco Chemolli
-
Inlined simple SBufTokenizer methods
- 9574. By Francesco Chemolli
-
Merged from trunk
- 9575. By Francesco Chemolli
-
Changed some parameters in StrList to const &
- 9576. By Francesco Chemolli
-
Removed duplicates from src/Makefile.am
- 9577. By Francesco Chemolli
-
Removed some junk that crept in in a merge
- 9578. By Francesco Chemolli
-
Merged from trunk
- 9579. By Francesco Chemolli
-
Reordered private and protected data members in OutOfBoundsExce
ption - 9580. By Francesco Chemolli
-
Applied a more consistent formatting to infix operators in SBuf.cc
Bumped some debugs level statements from DBG_DATA to a more standards-consistent level 8 - 9581. By Francesco Chemolli
-
Normalized formatting of infix operators and spacing after commas
- 9582. By Francesco Chemolli
-
Renamed some parameters for consistency.
Simplified SBuf constructor. - 9583. By Francesco Chemolli
-
CamelCased some SBuf parameters
- 9584. By Francesco Chemolli
-
Fixed SBuf::append(), better layering in SBuf::clear(), removed instance of HERE
- 9585. By Francesco Chemolli
-
Clarified parameters, improved some find() corner cases.
- 9586. By Francesco Chemolli
-
improved some SBuf::find() corner cases, improved documentation~
- 9587. By Francesco Chemolli
-
Renamed SBuf::reserve to SBuf::reserveSpace and created a new SBuf::reserve which matches std::string
- 9588. By Francesco Chemolli
-
Increased robustness of SBuf size constraints, clarified documentation
- 9589. By Francesco Chemolli
-
Clarified SBuf documentation
- 9590. By Francesco Chemolli
-
Reverted changes, SBuf uses reserveSpace now. Clarified parameter names
- 9591. By Francesco Chemolli
-
Improved bounds-checking on size parameters.
Moved some variable declarations only when actually needed. - 9592. By Francesco Chemolli
-
Made some SBuf::find corner-cases behave more like std::string
Simplified and corrected SBuf::rfind
Increased accuracy and coverage of SBuf unit tests. - 9593. By Francesco Chemolli
-
Reimplemented SBuf::find, increased consistency with std::string
- 9594. By Francesco Chemolli
-
Expanded unit tests for SBuf::find
- 9595. By Francesco Chemolli
-
Improved SBuf::rfind and its unit test
- 9596. By Francesco Chemolli
-
One more SBuf::rfind unit test
- 9597. By Francesco Chemolli
-
Added unit test for SBuf::rfind, renamed unclear variable in rfind
- 9598. By Francesco Chemolli
-
reworked SBuf::find_
first_of, wrote unit test for it. - 9599. By Francesco Chemolli
-
Merged from trunk
- 9600. By Francesco Chemolli
-
Fixed headers, made some variables const in SBuf.cc
- 9601. By Francesco Chemolli
-
Sorted headers in SBuf files, de-inlined SBuf::reAlloc
- 9602. By Francesco Chemolli
-
Simplified and corrected SBuf::rawSpace
- 9603. By Francesco Chemolli
-
Renamed SBuf::StoreProt
otype to InitialStore - 9604. By Francesco Chemolli
-
Changed SBuf::InitialStore to a static function variable
- 9605. By Francesco Chemolli
-
Removed misleading comment
- 9606. By Francesco Chemolli
-
Changed SBuf exceptions constructors to explicit
- 9607. By Francesco Chemolli
-
Reverted unwanted spacing changes in mem.cc
- 9608. By Francesco Chemolli
-
Clarified and corrected OutOfBoundsExce
ption - 9609. By Francesco Chemolli
-
Simplified OutOfBoundsExce
ption's error message handling - 9610. By Francesco Chemolli
-
Merged from trunk
- 9611. By Francesco Chemolli
-
Merged from trunk, fixed shadowing problem
- 9612. By Francesco Chemolli
-
Changed testSBuf a bit to clarify some tests better
- 9613. By Francesco Chemolli
-
Merge SBuf::rfind fixes from Amos Jeffries
- 9614. By Francesco Chemolli
-
Merged from trunk
- 9615. By Francesco Chemolli
-
Merged SBuf work by Amos Jeffries and Alex Rousskov, including comprehensive find() testsuite.
- 9616. By Francesco Chemolli
-
Changed the behavior of SBuf::find to match the inconsistencies of std::string
- 9617. By Francesco Chemolli
-
Make SBuf::find consistent, highlighting a bug in some versions of GNU c++stdlib
- 9618. By Francesco Chemolli
-
Apply parameter and constant name conventions more consistently.
Document and enforce consistent behavior in handling startPos for SBuf::find methods
Remove useless includes from testSBuf.h - 9619. By Francesco Chemolli
-
Fix bug in SBuf::compare when max comparison length is specified.
- 9620. By Francesco Chemolli
-
Deinlined cow(), inlined commonCompareCh
ecksPost( )
Added store-size checks to forceSize()
Improved \0-cleanliness in compare()
Implemented cmp() and casecmp() as shorthand versions of compare()
Improved documentation
Added more unit tests - 9621. By Francesco Chemolli
-
Implemented \0-cleanliness for comparison operations
Added more unit-tests. - 9622. By Francesco Chemolli
-
Merged from trunk
- 9623. By Francesco Chemolli
-
Fix linking issue in minimum layer
Unmerged revisions
- 9623. By Francesco Chemolli
-
Fix linking issue in minimum layer
- 9622. By Francesco Chemolli
-
Merged from trunk
- 9621. By Francesco Chemolli
-
Implemented \0-cleanliness for comparison operations
Added more unit-tests. - 9620. By Francesco Chemolli
-
Deinlined cow(), inlined commonCompareCh
ecksPost( )
Added store-size checks to forceSize()
Improved \0-cleanliness in compare()
Implemented cmp() and casecmp() as shorthand versions of compare()
Improved documentation
Added more unit tests - 9619. By Francesco Chemolli
-
Fix bug in SBuf::compare when max comparison length is specified.
- 9618. By Francesco Chemolli
-
Apply parameter and constant name conventions more consistently.
Document and enforce consistent behavior in handling startPos for SBuf::find methods
Remove useless includes from testSBuf.h - 9617. By Francesco Chemolli
-
Make SBuf::find consistent, highlighting a bug in some versions of GNU c++stdlib
- 9616. By Francesco Chemolli
-
Changed the behavior of SBuf::find to match the inconsistencies of std::string
- 9615. By Francesco Chemolli
-
Merged SBuf work by Amos Jeffries and Alex Rousskov, including comprehensive find() testsuite.
- 9614. By Francesco Chemolli
-
Merged from trunk
Preview Diff
1 | === modified file 'include/util.h' |
2 | --- include/util.h 2012-10-09 09:23:00 +0000 |
3 | +++ include/util.h 2013-07-04 15:56:30 +0000 |
4 | @@ -102,7 +102,7 @@ |
5 | extern const char *gb_to_str(const gb_t *); |
6 | extern void gb_flush(gb_t *); /* internal, do not use this */ |
7 | |
8 | -/* |
9 | +/** |
10 | * Returns the amount of known allocated memory |
11 | */ |
12 | int statMemoryAccounted(void); |
13 | |
14 | === modified file 'src/Makefile.am' |
15 | --- src/Makefile.am 2013-06-20 09:56:11 +0000 |
16 | +++ src/Makefile.am 2013-07-04 15:56:30 +0000 |
17 | @@ -24,7 +24,18 @@ |
18 | SBUF_SOURCE= \ |
19 | base/InstanceId.h \ |
20 | MemBlob.h \ |
21 | - MemBlob.cc |
22 | + MemBlob.cc \ |
23 | + OutOfBoundsException.h \ |
24 | + SBuf.h \ |
25 | + SBuf.cc \ |
26 | + SBufExceptions.h \ |
27 | + SBufExceptions.cc \ |
28 | + SBufTokenizer.h \ |
29 | + SBufTokenizer.cc \ |
30 | + SBufList.h \ |
31 | + SBufList.cc \ |
32 | + SBufUtil.h \ |
33 | + SBufUtil.cc |
34 | |
35 | LOADABLE_MODULES_SOURCES = \ |
36 | LoadableModule.h \ |
37 | @@ -142,7 +153,7 @@ |
38 | UNLINKDSOURCE = unlinkd.h unlinkd.cc |
39 | UNLINKD = unlinkd |
40 | else |
41 | -UNLINKDSOURCE = unlinkd.h |
42 | +UNLINKDSOURCE = |
43 | UNLINKD = |
44 | endif |
45 | |
46 | @@ -290,7 +301,6 @@ |
47 | client_db.cc \ |
48 | client_side.h \ |
49 | client_side.cc \ |
50 | - client_side.h \ |
51 | client_side_reply.cc \ |
52 | client_side_reply.h \ |
53 | client_side_request.cc \ |
54 | @@ -298,7 +308,6 @@ |
55 | ClientInfo.h \ |
56 | BodyPipe.cc \ |
57 | BodyPipe.h \ |
58 | - ClientInfo.h \ |
59 | ClientRequestContext.h \ |
60 | clientStream.cc \ |
61 | clientStream.h \ |
62 | @@ -390,6 +399,7 @@ |
63 | HttpHeaderFieldInfo.h \ |
64 | HttpHeaderTools.h \ |
65 | HttpHeaderTools.cc \ |
66 | + StrList.h \ |
67 | HttpBody.h \ |
68 | HttpBody.cc \ |
69 | HttpControlMsg.h \ |
70 | @@ -428,7 +438,6 @@ |
71 | mem.cc \ |
72 | mem_node.cc \ |
73 | mem_node.h \ |
74 | - Mem.h \ |
75 | MemBuf.cc \ |
76 | MemObject.cc \ |
77 | MemObject.h \ |
78 | @@ -470,6 +479,8 @@ |
79 | send-announce.h \ |
80 | send-announce.cc \ |
81 | $(SBUF_SOURCE) \ |
82 | + SBufExtras.h \ |
83 | + SBufExtras.cc \ |
84 | $(SNMP_SOURCE) \ |
85 | SquidMath.h \ |
86 | SquidMath.cc \ |
87 | @@ -482,7 +493,6 @@ |
88 | StatHist.h \ |
89 | StatHist.cc \ |
90 | String.cc \ |
91 | - StrList.h \ |
92 | StrList.cc \ |
93 | stmem.cc \ |
94 | stmem.h \ |
95 | @@ -592,7 +602,8 @@ |
96 | StoreEntryStream.h \ |
97 | String.cci \ |
98 | SquidString.h \ |
99 | - SquidTime.h |
100 | + SquidTime.h \ |
101 | + SBuf.cci |
102 | |
103 | BUILT_SOURCES = \ |
104 | cf_gen_defines.cci \ |
105 | @@ -1076,7 +1087,7 @@ |
106 | TESTSOURCES= \ |
107 | tests/STUB.h \ |
108 | test_tools.cc \ |
109 | - globals.cc |
110 | + globals.cc |
111 | |
112 | check_PROGRAMS+=\ |
113 | tests/testBoilerplate \ |
114 | @@ -1091,6 +1102,7 @@ |
115 | tests/testStore \ |
116 | tests/testString \ |
117 | tests/testURL \ |
118 | + tests/testSBuf \ |
119 | tests/testConfigParser \ |
120 | tests/testStatHist \ |
121 | tests/testVector \ |
122 | @@ -1241,6 +1253,7 @@ |
123 | HttpHeaderFieldInfo.h \ |
124 | HttpHeaderTools.h \ |
125 | HttpHeaderTools.cc \ |
126 | + StrList.h \ |
127 | HttpHdrContRange.cc \ |
128 | HttpHdrRange.cc \ |
129 | HttpHeaderFieldStat.h \ |
130 | @@ -1264,7 +1277,6 @@ |
131 | StatCounters.cc \ |
132 | StatCounters.h \ |
133 | StatHist.h \ |
134 | - StrList.h \ |
135 | StrList.cc \ |
136 | tests/stub_StatHist.cc \ |
137 | stmem.cc \ |
138 | @@ -1472,6 +1484,7 @@ |
139 | HttpHeaderFieldInfo.h \ |
140 | HttpHeaderTools.h \ |
141 | HttpHeaderTools.cc \ |
142 | + StrList.h \ |
143 | HttpHeaderFieldStat.h \ |
144 | HttpHdrCc.h \ |
145 | HttpHdrCc.cc \ |
146 | @@ -1534,7 +1547,6 @@ |
147 | StatCounters.h \ |
148 | StatCounters.cc \ |
149 | StatHist.h \ |
150 | - StrList.h \ |
151 | StrList.cc \ |
152 | tests/stub_StatHist.cc \ |
153 | stmem.cc \ |
154 | @@ -2207,7 +2219,6 @@ |
155 | StatCounters.cc \ |
156 | StatHist.h \ |
157 | StatHist.cc \ |
158 | - Mem.h \ |
159 | stmem.cc \ |
160 | repl_modules.h \ |
161 | store.cc \ |
162 | @@ -3825,6 +3836,42 @@ |
163 | $(REPL_OBJS) \ |
164 | $(SQUID_CPPUNIT_LA) |
165 | |
166 | +tests_testSBuf_SOURCES= \ |
167 | + tests/testSBuf.h \ |
168 | + tests/testSBuf.cc \ |
169 | + tests/testMain.cc \ |
170 | + tests/SBufFindTest.h \ |
171 | + tests/SBufFindTest.cc \ |
172 | + $(SBUF_SOURCE) \ |
173 | + SBufStream.h \ |
174 | + time.cc \ |
175 | + mem.cc \ |
176 | + tests/stub_debug.cc \ |
177 | + tests/stub_fatal.cc \ |
178 | + tests/stub_HelperChildConfig.cc \ |
179 | + tests/stub_cache_cf.cc \ |
180 | + tests/stub_cache_manager.cc \ |
181 | + tests/stub_store.cc \ |
182 | + tests/stub_store_stats.cc \ |
183 | + tests/stub_tools.cc \ |
184 | + SquidString.h \ |
185 | + String.cc \ |
186 | + wordlist.cc \ |
187 | + MemBuf.cc |
188 | +nodist_tests_testSBuf_SOURCES=$(TESTSOURCES) |
189 | +tests_testSBuf_LDFLAGS = $(LIBADD_DL) |
190 | +tests_testSBuf_LDADD=\ |
191 | + $(SQUID_CPPUNIT_LIBS) \ |
192 | + $(SQUID_CPPUNIT_LA) \ |
193 | + $(COMPAT_LIB) \ |
194 | + libsquid.la \ |
195 | + ip/libip.la \ |
196 | + mgr/libmgr.la \ |
197 | + base/libbase.la \ |
198 | + $(top_builddir)/lib/libmiscutil.la \ |
199 | + $(COMMON_LIBS) |
200 | +tests_testSBuf_DEPENDENCIES= $(SQUID_CPPUNIT_LA) |
201 | + |
202 | tests_testConfigParser_SOURCES = \ |
203 | ClientInfo.h \ |
204 | Mem.h \ |
205 | |
206 | === modified file 'src/MemBlob.cc' |
207 | --- src/MemBlob.cc 2012-11-15 22:12:03 +0000 |
208 | +++ src/MemBlob.cc 2013-07-04 15:56:30 +0000 |
209 | @@ -46,6 +46,17 @@ |
210 | MemBlobStats::MemBlobStats(): alloc(0), live(0), append(0), liveBytes(0) |
211 | {} |
212 | |
213 | +MemBlobStats& |
214 | +MemBlobStats::operator += (const MemBlobStats& s) |
215 | +{ |
216 | + alloc+=s.alloc; |
217 | + live+=s.live; |
218 | + append+=s.append; |
219 | + liveBytes+=s.liveBytes; |
220 | + |
221 | + return *this; |
222 | +} |
223 | + |
224 | std::ostream& |
225 | MemBlobStats::dump(std::ostream &os) const |
226 | { |
227 | |
228 | === modified file 'src/MemBlob.h' |
229 | --- src/MemBlob.h 2012-10-29 04:59:58 +0000 |
230 | +++ src/MemBlob.h 2013-07-04 15:56:30 +0000 |
231 | @@ -46,6 +46,8 @@ |
232 | /// dumps class-wide statistics |
233 | std::ostream& dump(std::ostream& os) const; |
234 | |
235 | + MemBlobStats& operator += (const MemBlobStats&); |
236 | + |
237 | public: |
238 | uint64_t alloc; ///< number of MemBlob instances created so far |
239 | uint64_t live; ///< number of MemBlob instances currently alive |
240 | |
241 | === added file 'src/OutOfBoundsException.h' |
242 | --- src/OutOfBoundsException.h 1970-01-01 00:00:00 +0000 |
243 | +++ src/OutOfBoundsException.h 2013-07-04 15:56:30 +0000 |
244 | @@ -0,0 +1,22 @@ |
245 | +#ifndef _SQUID_SRC_OUTOFBOUNDSEXCEPTION_H |
246 | +#define _SQUID_SRC_OUTOFBOUNDSEXCEPTION_H |
247 | + |
248 | +#include "base/TextException.h" |
249 | +#include "SBuf.h" |
250 | + |
251 | +/** |
252 | + * Exception raised when the user is going out of bounds when accessing |
253 | + * a char within the SBuf |
254 | + */ |
255 | +class OutOfBoundsException : public TextException |
256 | +{ |
257 | +public: |
258 | + OutOfBoundsException(const SBuf &buf, SBuf::size_type &pos, const char *aFileName = 0, int aLineNo = -1); |
259 | + virtual ~OutOfBoundsException() throw(); |
260 | + |
261 | +protected: |
262 | + SBuf _buf; |
263 | + SBuf::size_type _pos; |
264 | +}; |
265 | + |
266 | +#endif /* _SQUID_SRC_OUTOFBOUNDSEXCEPTION_H */ |
267 | |
268 | === added file 'src/SBuf.cc' |
269 | --- src/SBuf.cc 1970-01-01 00:00:00 +0000 |
270 | +++ src/SBuf.cc 2013-07-04 15:56:30 +0000 |
271 | @@ -0,0 +1,887 @@ |
272 | +/* |
273 | + * SBuf.cc (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
274 | + * |
275 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
276 | + * ---------------------------------------------------------- |
277 | + * |
278 | + * Squid is the result of efforts by numerous individuals from |
279 | + * the Internet community; see the CONTRIBUTORS file for full |
280 | + * details. Many organizations have provided support for Squid's |
281 | + * development; see the SPONSORS file for full details. Squid is |
282 | + * Copyrighted (C) 2001 by the Regents of the University of |
283 | + * California; see the COPYRIGHT file for full details. Squid |
284 | + * incorporates software developed and/or copyrighted by other |
285 | + * sources; see the CREDITS file for full details. |
286 | + * |
287 | + * This program is free software; you can redistribute it and/or modify |
288 | + * it under the terms of the GNU General Public License as published by |
289 | + * the Free Software Foundation; either version 2 of the License, or |
290 | + * (at your option) any later version. |
291 | + * |
292 | + * This program is distributed in the hope that it will be useful, |
293 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
294 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
295 | + * GNU General Public License for more details. |
296 | + * |
297 | + * You should have received a copy of the GNU General Public License |
298 | + * along with this program; if not, write to the Free Software |
299 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
300 | + */ |
301 | + |
302 | +#include "squid.h" |
303 | +#include "base/RefCount.h" |
304 | +#include "Debug.h" |
305 | +#include "OutOfBoundsException.h" |
306 | +#include "SBuf.h" |
307 | +#include "SBufExceptions.h" |
308 | +#include "util.h" |
309 | + |
310 | +#if HAVE_STRING_H |
311 | +#include <string.h> |
312 | +#endif |
313 | + |
314 | +#if HAVE_SSTREAM |
315 | +#include <sstream> |
316 | +#endif |
317 | + |
318 | +#if HAVE_IOSTREAM |
319 | +#include <iostream> |
320 | +#endif |
321 | + |
322 | +#ifdef VA_COPY |
323 | +#undef VA_COPY |
324 | +#endif |
325 | +#if defined HAVE_VA_COPY |
326 | +#define VA_COPY va_copy |
327 | +#elif defined HAVE___VA_COPY |
328 | +#define VA_COPY __va_copy |
329 | +#endif |
330 | + |
331 | +InstanceIdDefinitions(SBuf, "SBuf"); |
332 | + |
333 | +SBufStats SBuf::stats; |
334 | +const SBuf::size_type SBuf::npos; |
335 | +const SBuf::size_type SBuf::maxSize; |
336 | + |
337 | + |
338 | +SBufStats::SBufStats() |
339 | + : alloc(0), allocCopy(0), allocFromString(0), allocFromCString(0), |
340 | + assignFast(0), clear(0), append(0), toStream(0), setChar(0), |
341 | + getChar(0), compareSlow(0), compareFast(0), copyOut(0), |
342 | + rawAccess(0), chop(0), trim(0), find(0), scanf(0), |
343 | + caseChange(0), cowFast(0), cowSlow(0), live(0) |
344 | +{} |
345 | + |
346 | +SBufStats& |
347 | +SBufStats::operator +=(const SBufStats& ss) |
348 | +{ |
349 | + alloc += ss.alloc; |
350 | + allocCopy += ss.allocCopy; |
351 | + allocFromString += ss.allocFromString; |
352 | + allocFromCString += ss.allocFromCString; |
353 | + assignFast += ss.assignFast; |
354 | + clear += ss.clear; |
355 | + append += ss.append; |
356 | + toStream += ss.toStream; |
357 | + setChar += ss.setChar; |
358 | + getChar += ss.getChar; |
359 | + compareSlow += ss.compareSlow; |
360 | + compareFast += ss.compareFast; |
361 | + copyOut += ss.copyOut; |
362 | + rawAccess += ss.rawAccess; |
363 | + chop += ss.chop; |
364 | + trim += ss.trim; |
365 | + find += ss.find; |
366 | + scanf += ss.scanf; |
367 | + caseChange += ss.caseChange; |
368 | + cowFast += ss.cowFast; |
369 | + cowSlow += ss.cowSlow; |
370 | + live += ss.live; |
371 | + |
372 | + return *this; |
373 | +} |
374 | + |
375 | +SBuf::SBuf() |
376 | + : store_(GetStorePrototype()), off_(0), len_(0) |
377 | +{ |
378 | + debugs(24, 8, id << " created"); |
379 | + ++stats.alloc; |
380 | + ++stats.live; |
381 | +} |
382 | + |
383 | +SBuf::SBuf(const SBuf &S) |
384 | + : store_(S.store_), off_(S.off_), len_(S.len_) |
385 | +{ |
386 | + debugs(24, 8, id << " created from id " << S.id); |
387 | + ++stats.alloc; |
388 | + ++stats.allocCopy; |
389 | + ++stats.live; |
390 | +} |
391 | + |
392 | +SBuf::SBuf(const String &S) |
393 | + : store_(GetStorePrototype()), off_(0), len_(0) |
394 | +{ |
395 | + debugs(24, 8, id << " created from string"); |
396 | + assign(S.rawBuf(), 0, S.size()); |
397 | + ++stats.alloc; |
398 | + ++stats.allocFromString; |
399 | + ++stats.live; |
400 | +} |
401 | + |
402 | +SBuf::SBuf(const char *S, size_type pos, size_type n) |
403 | + : store_(GetStorePrototype()), off_(0), len_(0) |
404 | +{ |
405 | + append(S,pos,n); //bounds checked in append() |
406 | + ++stats.alloc; |
407 | + ++stats.allocFromCString; |
408 | + ++stats.live; |
409 | +} |
410 | + |
411 | +SBuf::~SBuf() |
412 | +{ |
413 | + debugs(24, 8, id << " destructed"); |
414 | + --stats.live; |
415 | +} |
416 | + |
417 | +SBuf& |
418 | +SBuf::assign(const SBuf &S) |
419 | +{ |
420 | + debugs(24, 7, "assigning " << id << " from " << S.id); |
421 | + if (&S == this) //assignment to self. Noop. |
422 | + return *this; |
423 | + ++stats.assignFast; |
424 | + store_ = S.store_; |
425 | + off_ = S.off_; |
426 | + len_ = S.len_; |
427 | + return *this; |
428 | +} |
429 | + |
430 | +SBuf& |
431 | +SBuf::assign(const char *S, size_type pos, size_type n) |
432 | +{ |
433 | + debugs(24, 6, id << " from c-string, pos=" << pos << "n=" << n << ")"); |
434 | + clear(); |
435 | + return append(S, pos, n); //bounds checked in append() |
436 | +} |
437 | + |
438 | +void |
439 | +SBuf::reserveCapacity(size_type minCapacity) |
440 | +{ |
441 | + Must(0 <= minCapacity && minCapacity <= maxSize); |
442 | + reserveSpace(minCapacity-length()); |
443 | +} |
444 | + |
445 | +void |
446 | +SBuf::reserveSpace(size_type minSpace) |
447 | +{ |
448 | + Must(0 <= minSpace && minSpace <= maxSize); |
449 | + debugs(24, 7, "reserving " << minSpace << " for " << id); |
450 | + // we're not concerned about RefCounts here, |
451 | + // the store knows the last-used portion. If |
452 | + // it's available, we're effectively claiming ownership |
453 | + // of it. If it's not, we need to go away (realloc) |
454 | + if (store_->canAppend(off_+len_, minSpace)) { |
455 | + debugs(24, 7, "not growing"); |
456 | + return; |
457 | + } |
458 | + // TODO: we may try to memmove before realloc'ing in order to avoid |
459 | + // one allocation operation, if we're the sole owners of a MemBlob. |
460 | + // Maybe some heuristic on off_ and length()? |
461 | + reAlloc(estimateCapacity(minSpace+length())); |
462 | +} |
463 | + |
464 | +void |
465 | +SBuf::clear() |
466 | +{ |
467 | +#if 0 |
468 | + //enabling this code path, the store will be freed and reinitialized |
469 | + store_ = GetStorePrototype(); //uncomment to actually free storage upon clear() |
470 | +#else |
471 | + //enabling this code path, we try to release the store without deallocating it. |
472 | + // will be lazily reallocated if needed. |
473 | + if (store_->LockCount() == 1) |
474 | + store_->clear(); |
475 | +#endif |
476 | + len_ = 0; |
477 | + off_ = 0; |
478 | + ++stats.clear; |
479 | +} |
480 | + |
481 | +SBuf& |
482 | +SBuf::append(const SBuf &S) |
483 | +{ |
484 | + return append(S.buf(), 0, S.length()); |
485 | +} |
486 | + |
487 | +SBuf& |
488 | +SBuf::append(const char * S, size_type pos, size_type n) |
489 | +{ |
490 | + Must(pos == npos || pos >= 0); |
491 | + Must(n == npos || n >= 0); |
492 | + |
493 | + if (S == NULL) |
494 | + return *this; |
495 | + if (n == npos) |
496 | + n = strlen(S)-pos; |
497 | + |
498 | + debugs(24, 7, "from c-string to id " << id); |
499 | + |
500 | + reserveSpace(n); //called method also checks n <= maxSize() |
501 | + const char *actual_start = S+pos; |
502 | + store_->append(actual_start, n); |
503 | + len_ += n; |
504 | + ++stats.append; |
505 | + return *this; |
506 | +} |
507 | + |
508 | +SBuf& |
509 | +SBuf::append(const std::string &str, SBuf::size_type pos, SBuf::size_type n) |
510 | +{ |
511 | + return append(str.data(), pos, n); //bounds checked in append() |
512 | +} |
513 | + |
514 | +SBuf& |
515 | +SBuf::assign(const std::string &str, size_type pos, size_type n) |
516 | +{ |
517 | + clear(); |
518 | + return append(str, pos, n); //bounds checked in append() |
519 | +} |
520 | + |
521 | +SBuf& |
522 | +SBuf::Printf(const char *fmt, ...) |
523 | +{ |
524 | + va_list args; |
525 | + va_start(args, fmt); |
526 | + clear(); |
527 | + vappendf(fmt, args); |
528 | + va_end(args); |
529 | + return *this; |
530 | +} |
531 | + |
532 | +SBuf& |
533 | +SBuf::appendf(const char *fmt, ...) |
534 | +{ |
535 | + va_list args; |
536 | + va_start(args, fmt); |
537 | + vappendf(fmt, args); |
538 | + va_end(args); |
539 | + return *this; |
540 | +} |
541 | + |
542 | +SBuf& |
543 | +SBuf::vappendf(const char *fmt, va_list vargs) |
544 | +{ |
545 | +#ifdef VA_COPY |
546 | + va_list ap; |
547 | +#endif |
548 | + int sz = 0; |
549 | + |
550 | + Must(fmt != NULL); |
551 | + |
552 | + //we can assume that we'll need to append at least strlen(fmt) bytes, |
553 | + //times 1.2 for instance... |
554 | + reserveSpace(strlen(fmt)*2); |
555 | + |
556 | + while (length() <= maxSize) { |
557 | +#ifdef VA_COPY |
558 | + /* Fix of bug 753r. The value of vargs is undefined |
559 | + * after vsnprintf() returns. Make a copy of vargs |
560 | + * in case we loop around and call vsnprintf() again. |
561 | + */ |
562 | + VA_COPY(ap, vargs); |
563 | + sz = vsnprintf(bufEnd(), store_->spaceSize(), fmt, ap); |
564 | + va_end(ap); |
565 | +#else /* VA_COPY */ |
566 | + sz = vsnprintf(bufEnd(), store_->spaceSize(), fmt, vargs); |
567 | +#endif /* VA_COPY*/ |
568 | + /* check for possible overflow */ |
569 | + /* snprintf on Linux returns -1 on overflows */ |
570 | + /* snprintf on FreeBSD returns at least free_space on overflows */ |
571 | + |
572 | + if (sz < 0 || sz >= (int)store_->spaceSize()) |
573 | + reserveSpace(sz*2); // TODO: tune heuristics |
574 | + else |
575 | + break; |
576 | + } |
577 | + |
578 | + len_ += sz; |
579 | + // TODO: this does NOT belong here, but to class-init or autoconf |
580 | + /* on Linux and FreeBSD, '\0' is not counted in return value */ |
581 | + /* on XXX it might be counted */ |
582 | + /* check that '\0' is appended and not counted */ |
583 | + |
584 | + if (operator[](len_-1) == 0) { |
585 | + --sz; |
586 | + --len_; |
587 | + } |
588 | + |
589 | + store_->size += sz; |
590 | + ++stats.append; |
591 | + |
592 | + return *this; |
593 | +} |
594 | + |
595 | +std::ostream& |
596 | +SBuf::print(std::ostream &os) const |
597 | +{ |
598 | + os.write(buf(), length()); |
599 | + ++stats.toStream; |
600 | + return os; |
601 | +} |
602 | + |
603 | +std::ostream& |
604 | +SBuf::dump(std::ostream &os) const |
605 | +{ |
606 | + os << id |
607 | + << ": "; |
608 | + store_->dump(os); |
609 | + os << ",offset:" << off_ |
610 | + << ",len:" << len_ |
611 | + << ") : '"; |
612 | + print(os); |
613 | + os << std::endl; |
614 | + return os; |
615 | +} |
616 | + |
617 | +void |
618 | +SBuf::setAt(SBuf::size_type pos, char toset) |
619 | +{ |
620 | + checkAccessBounds(pos); |
621 | + cow(); |
622 | + store_->mem[off_+pos] = toset; |
623 | + ++stats.setChar; |
624 | +} |
625 | + |
626 | +static int |
627 | +memcasecmp(const char *b1, const char *b2, SBuf::size_type len) |
628 | +{ |
629 | + int rv=0; |
630 | + while (len > 0) { |
631 | + rv = tolower(*b1)-tolower(*b2); |
632 | + if (rv != 0) |
633 | + return rv; |
634 | + ++b1; |
635 | + ++b2; |
636 | + --len; |
637 | + } |
638 | + return rv; |
639 | +} |
640 | + |
641 | +int |
642 | +SBuf::compare(const SBuf &S, SBufCaseSensitive isCaseSensitive, size_type n) const |
643 | +{ |
644 | + Must(n == npos || n >= 0); |
645 | + size_type sz = min(S.length(), length()); |
646 | + if (n != npos) |
647 | + sz = min(n, sz); |
648 | + ++stats.compareSlow; |
649 | + int rv; |
650 | + if (isCaseSensitive == caseSensitive) { |
651 | + rv = memcmp(buf(), S.buf(), sz); |
652 | + } else { |
653 | + rv = memcasecmp(buf(), S.buf(), sz); |
654 | + } |
655 | + if (rv != 0) |
656 | + return rv; |
657 | + // the first sz bytes are equal. If the user asked to ignore the rest |
658 | + // by specifying n and no SBuf was shorter than it, the result is final |
659 | + if (n == sz) |
660 | + return 0; |
661 | + //first sz bytes equal. longest SBuf "wins" |
662 | + if (length() == S.length()) //they're REALLY the same.. |
663 | + return 0; |
664 | + if (length() > S.length()) |
665 | + return 1; |
666 | + return -1; |
667 | + |
668 | +} |
669 | + |
670 | +bool |
671 | +SBuf::startsWith(const SBuf &S, SBufCaseSensitive isCaseSensitive) const |
672 | +{ |
673 | + if (length() < S.length()) { |
674 | + ++stats.compareFast; |
675 | + return false; |
676 | + } |
677 | + return (compare(S, isCaseSensitive, S.length()) == 0); |
678 | +} |
679 | + |
680 | +bool |
681 | +SBuf::operator ==(const SBuf & S) const |
682 | +{ |
683 | + debugs(24, 8, id << " == " << S.id); |
684 | + if (length() != S.length()) { |
685 | + debugs(24, 8, "no, different lengths"); |
686 | + ++stats.compareFast; |
687 | + return false; //shortcut: must be equal length |
688 | + } |
689 | + if (store_ == S.store_ && off_ == S.off_) { |
690 | + debugs(24, 8, "yes, same length and backing store"); |
691 | + ++stats.compareFast; |
692 | + return true; //shortcut: same store, offset and length |
693 | + } |
694 | + ++stats.compareSlow; |
695 | + const bool rv = (0 == strncmp(buf(), S.buf(), length())); |
696 | + debugs(24, 8, "returning " << rv); |
697 | + return rv; |
698 | +} |
699 | + |
700 | +bool |
701 | +SBuf::operator !=(const SBuf & S) const |
702 | +{ |
703 | + return !(*this == S); |
704 | +} |
705 | + |
706 | +SBuf |
707 | +SBuf::consume(SBuf::size_type n) |
708 | +{ |
709 | + Must (n == npos || n >= 0); |
710 | + if (n == npos) |
711 | + n = length(); |
712 | + else |
713 | + n = min(n, length()); |
714 | + SBuf rv(substr(0, n)); |
715 | + chop(n); |
716 | + return rv; |
717 | +} |
718 | + |
719 | +const |
720 | +SBufStats& SBuf::GetStats() |
721 | +{ |
722 | + return stats; |
723 | +} |
724 | + |
725 | +SBuf::size_type |
726 | +SBuf::copy(char *dest, SBuf::size_type n) const |
727 | +{ |
728 | + Must(n >= 0); |
729 | + |
730 | + SBuf::size_type toexport = length(); |
731 | + if (toexport > n) |
732 | + toexport = n; |
733 | + |
734 | + memcpy(dest, buf(), toexport); |
735 | + |
736 | + ++stats.copyOut; |
737 | + return toexport; |
738 | +} |
739 | + |
740 | +const char* |
741 | +SBuf::rawContent() const |
742 | +{ |
743 | + ++stats.rawAccess; |
744 | + return buf(); |
745 | +} |
746 | + |
747 | +char * |
748 | +SBuf::rawSpace(size_type minSize) |
749 | +{ |
750 | + cow(minSize+length()); |
751 | + ++stats.rawAccess; |
752 | + return bufEnd(); |
753 | +} |
754 | + |
755 | +void |
756 | +SBuf::forceSize(SBuf::size_type newSize) |
757 | +{ |
758 | + Must(store_->LockCount() == 1); |
759 | + if (newSize > min(SBuf::maxSize,store_->capacity-off_)) |
760 | + throw SBufTooBigException(__FILE__,__LINE__); |
761 | + len_ = newSize; |
762 | + store_->size = newSize; |
763 | +} |
764 | + |
765 | +const char* |
766 | +SBuf::c_str() |
767 | +{ |
768 | + ++stats.rawAccess; |
769 | + /* null-terminate the current buffer, by hand-appending a \0 at its tail but |
770 | + * without increasing its length. May COW, the side-effect is to guarantee that |
771 | + * the MemBlob's tail is availabe for us to use */ |
772 | + *rawSpace(1) = '\0'; |
773 | + ++store_->size; |
774 | + ++stats.setChar; |
775 | + return buf(); |
776 | +} |
777 | + |
778 | +SBuf& |
779 | +SBuf::chop(SBuf::size_type pos, SBuf::size_type n) |
780 | +{ |
781 | + Must(pos >= 0); |
782 | + Must(n == npos || n >= 0); |
783 | + /* |
784 | + * TODO: possible optimization: if the SBuf is at the tail of the |
785 | + * MemBlob we could decrease the MemBlob tail-pointer so that a subsequent |
786 | + * append will reuse the freed space. |
787 | + */ |
788 | + if (pos > length() || n == 0) { |
789 | + clear(); |
790 | + return *this; |
791 | + } |
792 | + if (n == npos || (pos+n) > length()) |
793 | + n = length()-pos; |
794 | + ++stats.chop; |
795 | + off_ += pos; |
796 | + len_ = n; |
797 | + return *this; |
798 | +} |
799 | + |
800 | +SBuf& |
801 | +SBuf::trim(const SBuf &toRemove, bool atBeginning, bool atEnd) |
802 | +{ |
803 | + ++stats.trim; |
804 | + if (atEnd) { |
805 | + const char *p = bufEnd()-1; |
806 | + while (!isEmpty() && memchr(toRemove.buf(), *p, toRemove.length()) != NULL) { |
807 | + //current end-of-buf is in the searched set |
808 | + --len_; |
809 | + --p; |
810 | + } |
811 | + } |
812 | + if (atBeginning) { |
813 | + const char *p = buf(); |
814 | + while (!isEmpty() && memchr(toRemove.buf(), *p, toRemove.length()) != NULL) { |
815 | + --len_; |
816 | + ++off_; |
817 | + ++p; |
818 | + } |
819 | + } |
820 | + if (isEmpty()) |
821 | + clear(); |
822 | + return *this; |
823 | +} |
824 | + |
825 | +SBuf |
826 | +SBuf::substr(SBuf::size_type pos, SBuf::size_type n) const |
827 | +{ |
828 | + SBuf rv(*this); |
829 | + rv.chop(pos, n); //stats handled by callee |
830 | + return rv; |
831 | +} |
832 | + |
833 | +SBuf::size_type |
834 | +SBuf::find(char c, SBuf::size_type startPos) const |
835 | +{ |
836 | + ++stats.find; |
837 | + |
838 | + // std::string presents npos if needle is outside hay |
839 | + if (startPos >= length()) |
840 | + return npos; |
841 | + |
842 | + if (startPos < 0) |
843 | + return npos; |
844 | + |
845 | + // for npos with char sd::string returns npos |
846 | + // this differs from how std::string handles 1-length string |
847 | + if (startPos == npos) |
848 | + return npos; |
849 | + |
850 | + const void *i = memchr(buf()+startPos, (int)c, (size_type)length()-startPos); |
851 | + |
852 | + if (i == NULL) |
853 | + return npos; |
854 | + |
855 | + return (static_cast<const char *>(i)-buf()); |
856 | +} |
857 | + |
858 | +SBuf::size_type |
859 | +SBuf::find(const SBuf &needle, size_type startPos) const |
860 | +{ |
861 | + // std::string allows needle to overhang hay but not start outside |
862 | + if (startPos != npos && startPos > length()) { |
863 | + ++stats.find; |
864 | + return npos; |
865 | + } |
866 | + |
867 | + // for empty needle std::string returns startPos |
868 | + if (needle.length() == 0) { |
869 | + ++stats.find; |
870 | + return startPos; |
871 | + } |
872 | + |
873 | + // for npos with char* std::string scans entire hay |
874 | + // this differs from how std::string handles single char from npos |
875 | + if (startPos == npos) |
876 | + return npos; |
877 | + |
878 | + // if needle length is 1 use the char search |
879 | + if (needle.length() == 1) |
880 | + return find(needle[0], startPos); |
881 | + |
882 | + ++stats.find; |
883 | + |
884 | + char *begin = buf()+startPos; |
885 | + char *lastPossible = buf()+length()-needle.length()+1; |
886 | + char needleBegin = needle[0]; |
887 | + |
888 | + debugs(24, 7, "looking for " << needle << "starting at " << startPos << |
889 | + " in id " << id); |
890 | + while (begin < lastPossible) { |
891 | + char *tmp; |
892 | + debugs(24, 8, " begin=" << (void *) begin << |
893 | + ", lastPossible=" << (void*) lastPossible ); |
894 | + tmp = static_cast<char *>(memchr(begin, needleBegin, lastPossible-begin)); |
895 | + if (tmp == NULL) { |
896 | + debugs(24, 8 , "First byte not found"); |
897 | + return npos; |
898 | + } |
899 | + // lastPossible guarrantees no out-of-bounds with memcmp() |
900 | + if (0 == memcmp(needle.buf(), tmp, needle.length())) { |
901 | + debugs(24, 8, "Found at " << (tmp-buf())); |
902 | + return (tmp-buf()); |
903 | + } |
904 | + begin = tmp+1; |
905 | + } |
906 | + debugs(24, 8, "not found"); |
907 | + return npos; |
908 | +} |
909 | + |
910 | +SBuf::size_type |
911 | +SBuf::rfind(const SBuf &needle, SBuf::size_type endPos) const |
912 | +{ |
913 | + // when the needle is 1 char, use the 1-char rfind() |
914 | + if (needle.length() == 1) |
915 | + return rfind(needle[0], endPos); |
916 | + |
917 | + ++stats.find; |
918 | + |
919 | + // on npos input std::string scans from the end of hay |
920 | + if (endPos == npos || endPos > length()) |
921 | + endPos=length(); |
922 | + |
923 | + // on empty hay std::string returns npos |
924 | + if (length() < needle.length()) |
925 | + return npos; |
926 | + |
927 | + // on empty needle std::string returns the position the search starts |
928 | + if (needle.length() == 0) |
929 | + return endPos; |
930 | + |
931 | +/* std::string permits needle to overhang endPos |
932 | + if (endPos <= needle.length()) |
933 | + return npos; |
934 | +*/ |
935 | + |
936 | + char *bufBegin = buf(); |
937 | + char *cur = bufBegin+endPos; |
938 | + char needleBegin = needle[0]; |
939 | + while (cur >= bufBegin) { |
940 | + if (*cur == needleBegin) { |
941 | + if (0 == memcmp(needle.buf(), cur, needle.length())) { |
942 | + // found |
943 | + return (cur-buf()); |
944 | + } |
945 | + } |
946 | + --cur; |
947 | + } |
948 | + return npos; |
949 | +} |
950 | + |
951 | +SBuf::size_type |
952 | +SBuf::rfind(char c, SBuf::size_type endPos) const |
953 | +{ |
954 | + ++stats.find; |
955 | + |
956 | + // on empty hay std::string returns size of hay |
957 | + if (length() < 1) |
958 | + return npos; |
959 | + |
960 | + // on npos input std::string compares last octet of hay |
961 | + if (endPos == npos || endPos >= length()) |
962 | + endPos=length(); |
963 | + else { |
964 | + // NP: off-by-one weirdness: |
965 | + // endPos is an offset ... 0-based |
966 | + // length() is a count ... 1-based |
967 | + // memrhr() requires a 1-based count of space to scan. |
968 | + ++endPos; |
969 | + } |
970 | + |
971 | + const void *i = memrchr(buf(), (int)c, (size_type)endPos); |
972 | + |
973 | + if (i == NULL) |
974 | + return npos; |
975 | + |
976 | + return (static_cast<const char *>(i)-buf()); |
977 | +} |
978 | + |
979 | +SBuf::size_type |
980 | +SBuf::find_first_of(const SBuf &set, size_type startPos) const |
981 | +{ |
982 | + Must(startPos == npos || startPos >= 0); |
983 | + ++stats.find; |
984 | + |
985 | + if (set.length() == 0) |
986 | + return 0; |
987 | + |
988 | + debugs(24, 7, "any of '" << set << "' " << " in id " << id); |
989 | + if (startPos == npos || startPos > length()) |
990 | + return npos; |
991 | + startPos = min(startPos, length()); |
992 | + char *cur = buf()+startPos, *end = bufEnd(); |
993 | + while (cur < end) { |
994 | + if (memchr(set.buf(), *cur, set.length())) |
995 | + return (cur-buf()); |
996 | + ++cur; |
997 | + } |
998 | + debugs(24, 7, "not found"); |
999 | + return npos; |
1000 | +} |
1001 | + |
1002 | +/* |
1003 | + * TODO: borrow a sscanf implementation from Linux or similar? |
1004 | + * we'd really need a vsnscanf(3)... ? As an alternative, a |
1005 | + * light-regexp-like domain-specific syntax might be an idea. |
1006 | + */ |
1007 | +int |
1008 | +SBuf::scanf(const char *format, ...) |
1009 | +{ |
1010 | + va_list arg; |
1011 | + int rv; |
1012 | + ++stats.scanf; |
1013 | + va_start(arg, format); |
1014 | + rv = vsscanf(c_str(), format, arg); |
1015 | + va_end(arg); |
1016 | + return rv; |
1017 | +} |
1018 | + |
1019 | +std::ostream & |
1020 | +operator <<(std::ostream& os, const SBuf& S) |
1021 | +{ |
1022 | + return S.print(os); |
1023 | +} |
1024 | + |
1025 | +std::ostream & |
1026 | +SBufStats::dump(std::ostream& os) const |
1027 | +{ |
1028 | + MemBlobStats ststats = MemBlob::GetStats(); |
1029 | + os << |
1030 | + "SBuf stats:\nnumber of allocations: " << alloc << |
1031 | + "\ncopy-allocations: " << allocCopy << |
1032 | + "\ncopy-allocations from SquidString: " << allocFromString << |
1033 | + "\ncopy-allocations from C String: " << allocFromCString << |
1034 | + "\nlive references: " << live << |
1035 | + "\nno-copy assignments: " << assignFast << |
1036 | + "\nclearing operations: " << clear << |
1037 | + "\nappend operations: " << append << |
1038 | + "\ndump-to-ostream: " << toStream << |
1039 | + "\nset-char: " << setChar << |
1040 | + "\nget-char: " << getChar << |
1041 | + "\ncomparisons with data-scan: " << compareSlow << |
1042 | + "\ncomparisons not requiring data-scan: " << compareFast << |
1043 | + "\ncopy-out ops: " << copyOut << |
1044 | + "\nraw access to memory: " << rawAccess << |
1045 | + "\nchop operations: " << chop << |
1046 | + "\ntrim operations: " << trim << |
1047 | + "\nfind: " << find << |
1048 | + "\nscanf: " << scanf << |
1049 | + "\ncase-change ops: " << caseChange << |
1050 | + "\nCOW not actually requiring a copy: " << cowFast << |
1051 | + "\nCOW: " << cowSlow << |
1052 | + "\naverage store share factor: " << |
1053 | + (ststats.live != 0 ? static_cast<float>(live)/ststats.live : 0) << |
1054 | + std::endl; |
1055 | + return os; |
1056 | +} |
1057 | + |
1058 | +SBuf |
1059 | +SBuf::toLower() const |
1060 | +{ |
1061 | + debugs(24, 8, "\"" << *this << "\""); |
1062 | + SBuf rv(*this); |
1063 | + for (size_type j = 0; j < length(); ++j) { |
1064 | + const int c = (*this)[j]; |
1065 | + if (isupper(c)) |
1066 | + rv.setAt(j, tolower(c)); //will cow() if needed |
1067 | + } |
1068 | + debugs(24, 8, "result: \"" << *this << "\""); |
1069 | + ++stats.caseChange; |
1070 | + return rv; |
1071 | +} |
1072 | + |
1073 | +SBuf |
1074 | +SBuf::toUpper() const |
1075 | +{ |
1076 | + debugs(24, 8, "\"" << *this << "\""); |
1077 | + SBuf rv(*this); |
1078 | + for (size_type j = 0; j < length(); ++j) { |
1079 | + const int c = (*this)[j]; |
1080 | + if (islower(c)) |
1081 | + rv.setAt(j, toupper(c)); //will cow() if needed |
1082 | + } |
1083 | + debugs(24, 8, "result: \"" << *this << "\""); |
1084 | + ++stats.caseChange; |
1085 | + return rv; |
1086 | +} |
1087 | + |
1088 | +/** |
1089 | + * checks whether the requested 'pos' is within the bounds of the SBuf |
1090 | + * \throw OutOfBoundsException if access is out of bounds |
1091 | + */ |
1092 | +void |
1093 | +SBuf::checkAccessBounds(SBuf::size_type pos) const |
1094 | +{ |
1095 | + if (pos < 0) |
1096 | + throw OutOfBoundsException(*this, pos, __FILE__, __LINE__); |
1097 | + if (pos > length()) |
1098 | + throw OutOfBoundsException(*this, pos, __FILE__, __LINE__); |
1099 | +} |
1100 | + |
1101 | +String |
1102 | +SBuf::toString() const |
1103 | +{ |
1104 | + String rv; |
1105 | + rv.limitInit(buf(), length()); |
1106 | + ++stats.copyOut; |
1107 | + return rv; |
1108 | +} |
1109 | + |
1110 | +/* |
1111 | + * re-allocate the backing store of the SBuf. |
1112 | + * If there are contents in the SBuf, they will be copied over. |
1113 | + * NO verifications are made on the size parameters, it's up to the caller to |
1114 | + * make sure that the new size is big enough to hold the copied contents. |
1115 | + * The re-allocated storage MAY be bigger than the requested size due to size-chunking |
1116 | + * algorithms in MemBlock, it is guarranteed NOT to be smaller. |
1117 | + */ |
1118 | +void |
1119 | +SBuf::reAlloc(SBuf::size_type newsize) |
1120 | +{ |
1121 | + debugs(24, DBG_DATA, "new size: " << newsize); |
1122 | + if (newsize > maxSize) |
1123 | + throw SBufTooBigException(__FILE__, __LINE__); |
1124 | + MemBlob::Pointer newbuf = new MemBlob(newsize); |
1125 | + if (length() > 0) |
1126 | + newbuf->append(buf(), length()); |
1127 | + store_ = newbuf; |
1128 | + off_ = 0; |
1129 | + ++stats.cowSlow; |
1130 | + debugs(24, 7, "new store capacity: " << store_->capacity); |
1131 | +} |
1132 | + |
1133 | +/** |
1134 | + * copy-on-write: make sure that we are the only holder of the backing store. |
1135 | + * If not, reallocate. If a new size is specified, and it is greater than the |
1136 | + * current length, the backing store will be extended as needed |
1137 | + * \retval false no grow was needed |
1138 | + * \retval true had to copy |
1139 | + */ |
1140 | +bool |
1141 | +SBuf::cow(SBuf::size_type newsize) |
1142 | +{ |
1143 | + debugs(24, DBG_DATA, "new size:" << newsize); |
1144 | + if (newsize == npos || newsize < length()) |
1145 | + newsize = length(); |
1146 | + |
1147 | + if (store_->LockCount() == 1 && newsize == length()) { |
1148 | + debugs(24, DBG_DATA, "no cow needed"); |
1149 | + ++stats.cowFast; |
1150 | + return false; |
1151 | + } |
1152 | + reAlloc(newsize); |
1153 | + return true; |
1154 | +} |
1155 | + |
1156 | +#if !_USE_INLINE_ |
1157 | +#include "SBuf.cci" |
1158 | +#endif |
1159 | |
1160 | === added file 'src/SBuf.cci' |
1161 | --- src/SBuf.cci 1970-01-01 00:00:00 +0000 |
1162 | +++ src/SBuf.cci 2013-07-04 15:56:30 +0000 |
1163 | @@ -0,0 +1,174 @@ |
1164 | +/* |
1165 | + * SBuf.cc (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
1166 | + * |
1167 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
1168 | + * ---------------------------------------------------------- |
1169 | + * |
1170 | + * Squid is the result of efforts by numerous individuals from |
1171 | + * the Internet community; see the CONTRIBUTORS file for full |
1172 | + * details. Many organizations have provided support for Squid's |
1173 | + * development; see the SPONSORS file for full details. Squid is |
1174 | + * Copyrighted (C) 2001 by the Regents of the University of |
1175 | + * California; see the COPYRIGHT file for full details. Squid |
1176 | + * incorporates software developed and/or copyrighted by other |
1177 | + * sources; see the CREDITS file for full details. |
1178 | + * |
1179 | + * This program is free software; you can redistribute it and/or modify |
1180 | + * it under the terms of the GNU General Public License as published by |
1181 | + * the Free Software Foundation; either version 2 of the License, or |
1182 | + * (at your option) any later version. |
1183 | + * |
1184 | + * This program is distributed in the hope that it will be useful, |
1185 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1186 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1187 | + * GNU General Public License for more details. |
1188 | + * |
1189 | + * You should have received a copy of the GNU General Public License |
1190 | + * along with this program; if not, write to the Free Software |
1191 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
1192 | + */ |
1193 | + |
1194 | +#include "base/RefCount.h" |
1195 | +#include "OutOfBoundsException.h" |
1196 | +#include "SBufExceptions.h" |
1197 | + |
1198 | +#if HAVE_CLIMITS |
1199 | +#include <climits> |
1200 | +#elif HAVE_LIMITS_H |
1201 | +#include <limits.h> |
1202 | +#endif |
1203 | + |
1204 | +SBuf& |
1205 | +SBuf::operator =(const SBuf & S) |
1206 | +{ |
1207 | + return assign(S); |
1208 | +} |
1209 | + |
1210 | +SBuf& |
1211 | +SBuf::operator =(const char *S) |
1212 | +{ |
1213 | + return assign(S); |
1214 | +} |
1215 | + |
1216 | +bool |
1217 | +SBuf::operator <(const SBuf &S) const |
1218 | +{ |
1219 | + return (cmp(S) < 0); |
1220 | +} |
1221 | + |
1222 | +bool |
1223 | +SBuf::operator >(const SBuf &S) const |
1224 | +{ |
1225 | + return (cmp(S) > 0); |
1226 | +} |
1227 | + |
1228 | +bool |
1229 | +SBuf::operator <=(const SBuf &S) const |
1230 | +{ |
1231 | + return (cmp(S) <= 0); |
1232 | +} |
1233 | + |
1234 | +bool |
1235 | +SBuf::operator >=(const SBuf &S) const |
1236 | +{ |
1237 | + return (cmp(S) >= 0); |
1238 | +} |
1239 | + |
1240 | +SBuf::size_type |
1241 | +SBuf::length() const |
1242 | +{ |
1243 | + return len_; |
1244 | +} |
1245 | + |
1246 | +int |
1247 | +SBuf::plength() const |
1248 | +{ |
1249 | + if (length() > INT_MAX) |
1250 | + throw SBufTooBigException(__FILE__, __LINE__); |
1251 | + return (int)length(); |
1252 | +} |
1253 | + |
1254 | +/** |
1255 | + * obtains a char* to the beginning of this SBuf in memory. |
1256 | + * \note the obtained string is NOT null-terminated. |
1257 | + */ |
1258 | +char * |
1259 | +SBuf::buf() const |
1260 | +{ |
1261 | + return store_->mem+off_; |
1262 | +} |
1263 | + |
1264 | +/** returns the pointer to the first char after this SBuf end |
1265 | + * |
1266 | + */ |
1267 | +char * |
1268 | +SBuf::bufEnd() const |
1269 | +{ |
1270 | + return store_->mem+off_+len_; |
1271 | +} |
1272 | + |
1273 | +/** |
1274 | + * Try to guesstimate how big a MemBlob to allocate. |
1275 | + * The result is guarranteed to be to be at least the desired |
1276 | + * size. |
1277 | + */ |
1278 | +const SBuf::size_type |
1279 | +SBuf::estimateCapacity(SBuf::size_type desired) const |
1280 | +{ |
1281 | + return 2*desired; |
1282 | +} |
1283 | + |
1284 | +/** |
1285 | + * To be called after having determined that the buffers are equal up to the |
1286 | + * length of the shortest one. |
1287 | + * If the buffers' length is the same, then they're equal. Otherwise, the |
1288 | + * longest one is deemed to be greater than the other. |
1289 | + * This matches the behavior of strcmp(1) and strcasecmp(1) |
1290 | + */ |
1291 | +int |
1292 | +SBuf::commonCompareChecksPost(const SBuf &S) const |
1293 | +{ |
1294 | + if (length() == S.length()) //they're REALLY the same.. |
1295 | + return 0; |
1296 | + if (length() > S.length()) |
1297 | + return 1; |
1298 | + return -1; |
1299 | +} |
1300 | + |
1301 | +/** obtain prototype store |
1302 | + * |
1303 | + * Just-created SBufs all share to the same MemBlob. |
1304 | + * This call instantiates and returns it. |
1305 | + */ |
1306 | +MemBlob::Pointer |
1307 | +SBuf::GetStorePrototype() |
1308 | +{ |
1309 | + static MemBlob::Pointer InitialStore = NULL; |
1310 | + if (InitialStore == NULL) { |
1311 | + static char lowPrototype[] = ""; |
1312 | + InitialStore = new MemBlob(lowPrototype, 0); |
1313 | + } |
1314 | + return InitialStore; |
1315 | +} |
1316 | + |
1317 | +const char |
1318 | +SBuf::operator [](SBuf::size_type pos) const |
1319 | +{ |
1320 | + ++stats.getChar; |
1321 | + if (pos < 0 || pos >= length()) |
1322 | + return '\0'; |
1323 | + return store_->mem[off_+pos]; |
1324 | +} |
1325 | + |
1326 | +const char |
1327 | +SBuf::at(SBuf::size_type pos) const |
1328 | +{ |
1329 | + checkAccessBounds(pos); |
1330 | + return operator[](pos); |
1331 | +} |
1332 | + |
1333 | +bool |
1334 | +SBuf::isEmpty() const |
1335 | +{ |
1336 | + return (len_ == 0); |
1337 | +} |
1338 | |
1339 | === added file 'src/SBuf.h' |
1340 | --- src/SBuf.h 1970-01-01 00:00:00 +0000 |
1341 | +++ src/SBuf.h 2013-07-04 15:56:30 +0000 |
1342 | @@ -0,0 +1,571 @@ |
1343 | +/* |
1344 | + * SBuf.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
1345 | + * |
1346 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
1347 | + * ---------------------------------------------------------- |
1348 | + * |
1349 | + * Squid is the result of efforts by numerous individuals from |
1350 | + * the Internet community; see the CONTRIBUTORS file for full |
1351 | + * details. Many organizations have provided support for Squid's |
1352 | + * development; see the SPONSORS file for full details. Squid is |
1353 | + * Copyrighted (C) 2001 by the Regents of the University of |
1354 | + * California; see the COPYRIGHT file for full details. Squid |
1355 | + * incorporates software developed and/or copyrighted by other |
1356 | + * sources; see the CREDITS file for full details. |
1357 | + * |
1358 | + * This program is free software; you can redistribute it and/or modify |
1359 | + * it under the terms of the GNU General Public License as published by |
1360 | + * the Free Software Foundation; either version 2 of the License, or |
1361 | + * (at your option) any later version. |
1362 | + * |
1363 | + * This program is distributed in the hope that it will be useful, |
1364 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1365 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1366 | + * GNU General Public License for more details. |
1367 | + * |
1368 | + * You should have received a copy of the GNU General Public License |
1369 | + * along with this program; if not, write to the Free Software |
1370 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
1371 | + */ |
1372 | + |
1373 | +#ifndef SQUID_SBUF_H |
1374 | +#define SQUID_SBUF_H |
1375 | + |
1376 | +#include "base/InstanceId.h" |
1377 | +#include "Debug.h" |
1378 | +#include "MemBlob.h" |
1379 | +#include "SquidString.h" |
1380 | + |
1381 | +#if HAVE_UNISTD_H |
1382 | +#include <unistd.h> |
1383 | +#endif |
1384 | +#if HAVE_STDARG_H |
1385 | +#include <stdarg.h> |
1386 | +#endif |
1387 | +#if HAVE_IOSFWD |
1388 | +#include <iosfwd> |
1389 | +#endif |
1390 | + |
1391 | +/* squid string placeholder (for printf) */ |
1392 | +#ifndef SQUIDSBUFPH |
1393 | +#define SQUIDSBUFPH "%.*s" |
1394 | +#define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent() |
1395 | +#endif /* SQUIDSBUFPH */ |
1396 | + |
1397 | +typedef enum { |
1398 | + caseSensitive, |
1399 | + caseInsensitive |
1400 | +} SBufCaseSensitive; |
1401 | + |
1402 | +/** |
1403 | + * Container for various SBuf class-wide statistics. |
1404 | + * |
1405 | + * The stats are not completely accurate; they're mostly meant to |
1406 | + * understand whether Squid is leaking resources |
1407 | + * and whether SBuf is paying off the expected gains. |
1408 | + */ |
1409 | +class SBufStats |
1410 | +{ |
1411 | +public: |
1412 | + u_int64_t alloc; ///<number of calls to SBuf constructors |
1413 | + u_int64_t allocCopy; ///<number of calls to SBuf copy-constructor |
1414 | + u_int64_t allocFromString; ///<number of copy-allocations from Strings |
1415 | + u_int64_t allocFromCString; ///<number of copy-allocations from c-strings |
1416 | + u_int64_t assignFast; ///<number of no-copy assignment operations |
1417 | + u_int64_t clear; ///<number of clear operations |
1418 | + u_int64_t append; ///<number of append operations |
1419 | + u_int64_t toStream; ///<number of write operations to ostreams |
1420 | + u_int64_t setChar; ///<number of calls to setAt |
1421 | + u_int64_t getChar; ///<number of calls to at() and operator[] |
1422 | + u_int64_t compareSlow; ///<number of comparison operations requiring data scan |
1423 | + u_int64_t compareFast; ///<number of comparison operations not requiring data scan |
1424 | + u_int64_t copyOut; ///<number of data-copies to other forms of buffers |
1425 | + u_int64_t rawAccess; ///<number of accesses to raw contents |
1426 | + u_int64_t chop; ///<number of chop operations |
1427 | + u_int64_t trim; ///<number of trim operations |
1428 | + u_int64_t find; ///<number of find operations |
1429 | + u_int64_t scanf; ///<number of scanf operations |
1430 | + u_int64_t caseChange; ///<number of toUpper and toLower operations |
1431 | + u_int64_t cowFast; ///<number of cow operations not actually requiring a copy |
1432 | + u_int64_t cowSlow; ///<number of cow operations requiring a copy |
1433 | + u_int64_t live; ///<number of currently-allocated SBuf |
1434 | + |
1435 | + /** |
1436 | + * Dump statistics to an ostream. |
1437 | + */ |
1438 | + std::ostream& dump(std::ostream &os) const; |
1439 | + SBufStats(); |
1440 | + |
1441 | + SBufStats& operator +=(const SBufStats&); |
1442 | +}; |
1443 | + |
1444 | +/** |
1445 | + * A String or Buffer. |
1446 | + * Features: refcounted backing store, cheap copy and sub-stringing |
1447 | + * operations, copy-on-write to isolate change operations to each instance. |
1448 | + * Where possible, we're trying to mimic std::string's interface. |
1449 | + */ |
1450 | +class SBuf |
1451 | +{ |
1452 | +public: |
1453 | + typedef int32_t size_type; |
1454 | + static const size_type npos = -1; |
1455 | + |
1456 | + /// Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb. |
1457 | + static const size_type maxSize = 0xfffffff; |
1458 | + |
1459 | + /// create an empty (zero-size) SBuf |
1460 | + SBuf(); |
1461 | + SBuf(const SBuf &S); |
1462 | + |
1463 | + /** Constructor: import c-style string |
1464 | + * |
1465 | + * Create a new SBuf containing a COPY of the contents of the |
1466 | + * c-string |
1467 | + * \param S the c string to be copied |
1468 | + * \param pos how many bytes to skip at the beginning of the c-string |
1469 | + * \param n how many bytes to import into the SBuf. If it is SBuf::npos |
1470 | + * or unspecified, imports to end-of-cstring |
1471 | + * \note it is the caller's responsibility not to go out of bounds |
1472 | + * \note bounds is 0 <= pos < length() |
1473 | + */ |
1474 | + explicit SBuf(const char *S, size_type pos = 0, size_type n = npos); |
1475 | + |
1476 | + /** Constructor: import SquidString, copying contents. |
1477 | + * |
1478 | + * This method will be removed once SquidString has gone. |
1479 | + */ |
1480 | + SBuf(const String &S); |
1481 | + |
1482 | + ~SBuf(); |
1483 | + /** Explicit assignment. |
1484 | + * |
1485 | + * Current SBuf will share backing store with the assigned one. |
1486 | + */ |
1487 | + SBuf& assign(const SBuf &S); |
1488 | + /** Assignment operator. |
1489 | + * |
1490 | + * Current SBuf will share backing store with the assigned one. |
1491 | + */ |
1492 | + _SQUID_INLINE_ SBuf& operator =(const SBuf & S); |
1493 | + |
1494 | + /** Import a c-string into a SBuf, copying the data. |
1495 | + * |
1496 | + * It is the caller's duty to free the imported string, if needed. |
1497 | + * \param S the c string to be copied |
1498 | + * \param pos how many bytes to skip at the beginning of the c-string. |
1499 | + * \param n how many bytes to import into the SBuf. If it is SBuf::npos |
1500 | + * or unspecified, imports to end-of-cstring |
1501 | + * \note it is the caller's responsibility not to go out of bounds |
1502 | + * \note bounds is 0 <= pos < length() |
1503 | + */ |
1504 | + SBuf& assign(const char *S, size_type pos = 0, size_type n = npos); |
1505 | + |
1506 | + /** Assignment operator. Copy a NULL-terminated c-style string into a SBuf. |
1507 | + * |
1508 | + * Copy a c-style string into a SBuf. Shortcut for SBuf.assign(S) |
1509 | + * It is the caller's duty to free the imported string, if needed. |
1510 | + */ |
1511 | + _SQUID_INLINE_ SBuf& operator =(const char *S); |
1512 | + |
1513 | + /** Import a std::string into a SBuf. Contents are copied. |
1514 | + * |
1515 | + * \param pos skip this many bytes at the beginning of string. |
1516 | + * 0 is beginning-of-string |
1517 | + * \param n how many bytes to copy. Default is SBuf::npos, end-of-string. |
1518 | + */ |
1519 | + SBuf& assign(const std::string &s, size_type pos = 0, size_type n = npos); |
1520 | + |
1521 | + /** reset the SBuf as if it was just created. |
1522 | + * |
1523 | + * Resets the SBuf to empty, memory is freed lazily. |
1524 | + */ |
1525 | + void clear(); |
1526 | + |
1527 | + /** Append operation |
1528 | + * |
1529 | + * Append the supplied SBuf to the current one; extend storage as needed. |
1530 | + */ |
1531 | + SBuf& append(const SBuf & S); |
1532 | + |
1533 | + /** Append operation for C-style strings. |
1534 | + * |
1535 | + * Append the supplied c-string to the SBuf; extend storage |
1536 | + * as needed. |
1537 | + * |
1538 | + * \param S the c string to be copied. Can be NULL. |
1539 | + * \param pos how many bytes to skip at the beginning of the c-string |
1540 | + * \param n how many bytes to import into the SBuf. If it is SBuf::npos |
1541 | + * or unspecified, imports to end-of-cstring |
1542 | + */ |
1543 | + SBuf& append(const char * S, size_type pos = 0, size_type n = npos); |
1544 | + |
1545 | + /** Append operation for std::string |
1546 | + * |
1547 | + * Append the supplied std::string to the SBuf; extend storage as needed. |
1548 | + * |
1549 | + * \param string the std::string to be copied. |
1550 | + * \param pos how many bytes to skip at the beginning of the c-string |
1551 | + * \param n how many bytes to import into the SBuf. If it is SBuf::npos |
1552 | + * or unspecified, imports to end-of-cstring |
1553 | + */ |
1554 | + SBuf& append(const std::string &str, size_type pos = 0, size_type n = npos); |
1555 | + |
1556 | + /** Assignment operation with printf(3)-style definition |
1557 | + * \note arguments may be evaluated more than once, be careful |
1558 | + * of side-effects |
1559 | + */ |
1560 | + SBuf& Printf(const char *fmt, ...); |
1561 | + |
1562 | + /** Append operation with printf-style arguments |
1563 | + * \note arguments may be evaluated more than once, be careful |
1564 | + * of side-effects |
1565 | + */ |
1566 | + SBuf& appendf(const char *fmt, ...); |
1567 | + /** Append operation, with vsprintf(3)-style arguments. |
1568 | + * \note arguments may be evaluated more than once, be careful |
1569 | + * of side-effects |
1570 | + */ |
1571 | + SBuf& vappendf(const char *fmt, va_list vargs); |
1572 | + |
1573 | + /** print a SBuf. |
1574 | + */ |
1575 | + std::ostream& print(std::ostream &os) const; |
1576 | + |
1577 | + /** print the sbuf, debug information and stats |
1578 | + * |
1579 | + * Debug function, dumps to a stream informations on the current SBuf, |
1580 | + * including low-level details and statistics. |
1581 | + */ |
1582 | + std::ostream& dump(std::ostream &os) const; |
1583 | + |
1584 | + /** random-access read to any char within the SBuf |
1585 | + * |
1586 | + * does not check access bounds. If you need that, use at() |
1587 | + */ |
1588 | + _SQUID_INLINE_ const char operator [](size_type pos) const; |
1589 | + |
1590 | + /** random-access read to any char within the SBuf. |
1591 | + * |
1592 | + * \throw OutOfBoundsException when access is out of bounds |
1593 | + * \note bounds is 0 <= pos < length() |
1594 | + */ |
1595 | + _SQUID_INLINE_ const char at(size_type pos) const; |
1596 | + |
1597 | + /** direct-access set a byte at a specified operation. |
1598 | + * |
1599 | + * \param pos the position to be overwritten |
1600 | + * \param toset the value to be written |
1601 | + * \throw OutOfBoundsException when pos is of bounds |
1602 | + * \note bounds is 0 <= pos < length() |
1603 | + * \note performs a copy-on-write if needed. |
1604 | + */ |
1605 | + void setAt(size_type pos, char toset); |
1606 | + |
1607 | + /** compare to other SBuf, str(case)cmp-style |
1608 | + * |
1609 | + * \param isCaseSensitive one of caseSensitive or caseInsensitive |
1610 | + * \param n compare up to this many bytes. if npos (default), compare whole SBufs |
1611 | + * \retval >0 argument of the call is greater than called SBuf |
1612 | + * \retval <0 argument of the call is smaller than called SBuf |
1613 | + * \retval 0 argument of the call has the same contents of called SBuf |
1614 | + */ |
1615 | + int compare(const SBuf &S, SBufCaseSensitive isCaseSensitive, size_type n = npos) const; |
1616 | + |
1617 | + /// shorthand version for compare |
1618 | + inline int cmp(const SBuf &S, size_type n = npos) const { |
1619 | + return compare(S,caseSensitive,n); |
1620 | + } |
1621 | + |
1622 | + /// shorthand version for case-insensitive comparison |
1623 | + inline int casecmp(const SBuf &S, size_type n = npos) const { |
1624 | + return compare(S,caseInsensitive,n); |
1625 | + } |
1626 | + |
1627 | + /** check whether the entire supplied argument is a prefix of the SBuf. |
1628 | + * \param S the prefix to match against |
1629 | + * \param isCaseSensitive one of caseSensitive or caseInsensitive |
1630 | + * \retval true argument is a prefix of the SBuf |
1631 | + */ |
1632 | + bool startsWith(const SBuf &S, SBufCaseSensitive isCaseSensitive = caseSensitive) const; |
1633 | + |
1634 | + /** equality check |
1635 | + */ |
1636 | + bool operator ==(const SBuf & S) const; |
1637 | + bool operator !=(const SBuf & S) const; |
1638 | + _SQUID_INLINE_ bool operator <(const SBuf &S) const; |
1639 | + _SQUID_INLINE_ bool operator >(const SBuf &S) const; |
1640 | + _SQUID_INLINE_ bool operator <=(const SBuf &S) const; |
1641 | + _SQUID_INLINE_ bool operator >=(const SBuf &S) const; |
1642 | + |
1643 | + /** Consume bytes at the head of the SBuf |
1644 | + * |
1645 | + * Consume N chars at SBuf head, or to SBuf's end, |
1646 | + * whichever is shorter. If more bytes are consumed than available, |
1647 | + * the SBuf is emptied |
1648 | + * \param n how many bytes to remove; could be zero. |
1649 | + * SBuf::npos (or no argument) means 'to the end of SBuf' |
1650 | + * \return a new SBuf containing the consumed bytes. |
1651 | + */ |
1652 | + SBuf consume(size_type n = npos); |
1653 | + |
1654 | + /** gets global statistic informations |
1655 | + * |
1656 | + */ |
1657 | + static const SBufStats& GetStats(); |
1658 | + |
1659 | + /** Copy SBuf contents into user-supplied C buffer. |
1660 | + * |
1661 | + * Export a copy of the SBuf's contents into the user-supplied |
1662 | + * buffer, up to the user-supplied-length. No zero-termination is performed |
1663 | + * \return num the number of actually-copied chars. |
1664 | + */ |
1665 | + size_type copy(char *dest, size_type n) const; |
1666 | + |
1667 | + /** exports a pointer to the SBuf internal storage. |
1668 | + * \warning ACCESSING RAW STORAGE IS DANGEROUS! |
1669 | + * |
1670 | + * Returns a pointer to SBuf's content. No terminating null character |
1671 | + * is appended (use c_str() for that). |
1672 | + * The returned value points to an internal location whose contents |
1673 | + * are guaranteed to remain unchanged only until the next call |
1674 | + * to a non-constant member function of the SBuf object. Such a |
1675 | + * call may be implicit (e.g., when SBuf is destroyed |
1676 | + * upon leaving the current context). |
1677 | + * This is a very UNSAFE way of accessing the data. |
1678 | + * This call never returns NULL. |
1679 | + * \see c_str |
1680 | + * \note the memory management system guarantees that the exported region |
1681 | + * of memory will remain valid if the caller keeps holding |
1682 | + * a valid reference to the SBuf object and does not write or append to |
1683 | + * it. For example: |
1684 | + * \code |
1685 | + * SBuf foo("some string"); |
1686 | + * const char *bar = foo.rawContent(); |
1687 | + * doSomething(bar); //safe |
1688 | + * foo.append(" other string"); |
1689 | + * doSomething(bar); //unsafe |
1690 | + * \endcode |
1691 | + */ |
1692 | + const char* rawContent() const; |
1693 | + |
1694 | + /** Exports a writable pointer to the SBuf internal storage. |
1695 | + * \warning Use with EXTREME caution, this is a dangerous operation. |
1696 | + * |
1697 | + * Returns a pointer to the first unused byte in the SBuf's storage, |
1698 | + * to be used for writing. If minsize is specified, it is guaranteed |
1699 | + * that at least minsize bytes will be available for writing. Otherwise |
1700 | + * it is guaranteed that at least as much storage as is currently |
1701 | + * available will be available for the call. A COW will be performed |
1702 | + * if necessary to ensure that a following write will not trample |
1703 | + * a shared MemBlob. The returned pointer must not be stored, and will |
1704 | + * become invalid at the first call to a non-const method call |
1705 | + * on the SBuf. |
1706 | + * This call guarantees to never return NULL |
1707 | + * This call always forces a cow() |
1708 | + * \throw SBufTooBigException if the user tries to allocate too big a SBuf |
1709 | + */ |
1710 | + char *rawSpace(size_type minSize = npos); |
1711 | + |
1712 | + /** Force a SBuf's size |
1713 | + * \warning use with EXTREME caution, this is a dangerous operation |
1714 | + * |
1715 | + * Adapt the SBuf internal state after external interference |
1716 | + * such as writing into it via rawSpace. |
1717 | + * \throw TextException if SBuf doesn't have exclusive ownership of store |
1718 | + * \throw SBufTooBigException if new size is bigger than available store space |
1719 | + */ |
1720 | + void forceSize(size_type newSize); |
1721 | + |
1722 | + /** exports a null-terminated reference to the SBuf internal storage. |
1723 | + * \warning ACCESSING RAW STORAGE IS DANGEROUS! DO NOT EVER USE |
1724 | + * THE RETURNED POINTER FOR WRITING |
1725 | + * |
1726 | + * The returned value points to an internal location whose contents |
1727 | + * are guaranteed to remain unchanged only until the next call |
1728 | + * to a non-constant member function of the SBuf object. Such a |
1729 | + * call may be implicit (e.g., when SBuf is destroyed |
1730 | + * upon leaving the current context). |
1731 | + * This is a very UNSAFE way of accessing the data. |
1732 | + * This call never returns NULL. |
1733 | + * \see rawContent |
1734 | + * \note the memory management system guarantees that the exported region |
1735 | + * of memory will remain valid if the caller keeps holding |
1736 | + * a valid reference to the SBuf object and does not write or append to |
1737 | + * it |
1738 | + */ |
1739 | + const char* c_str(); |
1740 | + |
1741 | + /** Returns the number of bytes stored in SBuf. |
1742 | + */ |
1743 | + _SQUID_INLINE_ size_type length() const; |
1744 | + |
1745 | + /** Get the length of the SBuf, as a signed integer |
1746 | + * |
1747 | + * Compatibility function for printf(3) which requires a signed int |
1748 | + * \throw SBufTooBigException if the SBuf is too big for a signed integer |
1749 | + */ |
1750 | + _SQUID_INLINE_ int plength() const; |
1751 | + |
1752 | + /** Check whether the SBuf is empty |
1753 | + * |
1754 | + * \return true if length() == 0 |
1755 | + */ |
1756 | + _SQUID_INLINE_ bool isEmpty() const; |
1757 | + |
1758 | + /** Request to extend the SBuf's free store space. |
1759 | + * |
1760 | + * After the reserveSpace request, the SBuf is guaranteed to have at |
1761 | + * least minSpace bytes of append-able backing store (on top of the |
1762 | + * currently-used portion). |
1763 | + * \throw SBufTooBigException if the user tries to allocate too big a SBuf |
1764 | + */ |
1765 | + void reserveSpace(size_type minSpace); |
1766 | + |
1767 | + /** Request to resize the SBuf's store |
1768 | + * |
1769 | + * After this method is called, the SBuf is guaranteed to have at least |
1770 | + * minCapcity bytes of total space, including the currently-used portion |
1771 | + * \throw SBufTooBigException if the user tries to allocate too big a SBuf |
1772 | + */ |
1773 | + void reserveCapacity(size_type minCapacity); |
1774 | + |
1775 | + /** slicing method |
1776 | + * |
1777 | + * Removes SBuf prefix and suffix, leaving a sequence of <i>n</i> |
1778 | + * bytes starting from position <i>pos</i> first byte is at pos 0. |
1779 | + * \param pos start sub-stringing from this byte. If it is |
1780 | + * greater than the SBuf length, the SBuf is emptied and |
1781 | + * an empty SBuf is returned |
1782 | + * \param n maximum number of bytes of the resulting SBuf. |
1783 | + * SBuf::npos means "to end of SBuf". |
1784 | + * if 0 returns an empty SBuf. |
1785 | + */ |
1786 | + SBuf& chop(size_type pos, size_type n = npos); |
1787 | + |
1788 | + /** Remove characters in the toremove set at the beginning, end or both |
1789 | + * |
1790 | + * \param toremove characters to be removed. Stops chomping at the first |
1791 | + * found char not in the set |
1792 | + * \param atBeginning if true (default), strips at the beginning of the SBuf |
1793 | + * \param atEnd if true (default), strips at the end of the SBuf |
1794 | + */ |
1795 | + SBuf& trim(const SBuf &toRemove, bool atBeginning = true, bool atEnd = true); |
1796 | + |
1797 | + /** Extract a part of the current SBuf. |
1798 | + * |
1799 | + * Return a fresh a fresh copy of a portion the current SBuf, which is left untouched. |
1800 | + * \see trim |
1801 | + */ |
1802 | + SBuf substr(size_type pos, size_type n = npos) const; |
1803 | + |
1804 | + /** Find first occurrence of character in SBuf |
1805 | + * |
1806 | + * Returns the index in the SBuf of the first occurrence of char c. |
1807 | + * \param startPos if specified, ignore any occurrences before that position |
1808 | + * if startPos is npos, always return npos |
1809 | + * \return SBuf::npos if the char was not found |
1810 | + */ |
1811 | + size_type find(char c, size_type startPos = 0) const; |
1812 | + |
1813 | + /** Find first occurrence of SBuf in SBuf. |
1814 | + * |
1815 | + * Returns the index in the SBuf of the first occurrence of the |
1816 | + * sequence contained in the str argument. |
1817 | + * \param startPos if specified, ignore any occurrences before that position |
1818 | + * if startPos is npos, always return npos |
1819 | + * \return SBuf::npos if the SBuf was not found |
1820 | + */ |
1821 | + size_type find(const SBuf & str, size_type startPos = 0) const; |
1822 | + |
1823 | + /** Find last occurrence of character in SBuf |
1824 | + * |
1825 | + * Returns the index in the SBuf of the last occurrence of char c. |
1826 | + * \param endPos if specified, ignore any occurrences after that position |
1827 | + * \return SBuf::npos if the char was not found |
1828 | + */ |
1829 | + size_type rfind(char c, size_type endPos = npos) const; |
1830 | + |
1831 | + /** Find last occurrence of SBuf in SBuf |
1832 | + * |
1833 | + * Returns the index in the SBuf of the last occurrence of the |
1834 | + * sequence contained in the str argument. |
1835 | + * \return SBuf::npos if the sequence was not found |
1836 | + * \param endPos if specified, ignore any occurrences after that position |
1837 | + */ |
1838 | + size_type rfind(const SBuf &str, size_type endPos = npos) const; |
1839 | + |
1840 | + /** Find first occurrence of character of set in SBuf |
1841 | + * |
1842 | + * Finds the first occurrence of ANY of the characters in the supplied set in |
1843 | + * the SBuf. |
1844 | + * \return SBuf::npos if no character in the set could be found |
1845 | + * \param startPos if specified, ignore any occurrences before that position |
1846 | + */ |
1847 | + size_type find_first_of(const SBuf &set, size_type startPos = 0) const; |
1848 | + |
1849 | + /** sscanf-alike |
1850 | + * |
1851 | + * sscanf re-implementation. Non-const, and not \0-clean. |
1852 | + * \return same as sscanf |
1853 | + * \see man sscanf(3) |
1854 | + */ |
1855 | + int scanf(const char *format, ...); |
1856 | + |
1857 | + /** Lower-case SBuf |
1858 | + * |
1859 | + * Returns a lower-cased COPY of the SBuf |
1860 | + * \see man tolower(3) |
1861 | + */ |
1862 | + SBuf toLower() const; |
1863 | + |
1864 | + /** Upper-case SBuf |
1865 | + * |
1866 | + * Returns an upper-cased COPY of the SBuf |
1867 | + * \see man toupper(3) |
1868 | + */ |
1869 | + SBuf toUpper() const; |
1870 | + |
1871 | + /** String export function |
1872 | + * converts the SBuf to a legacy String, by copy. Transitional. |
1873 | + */ |
1874 | + String toString() const; |
1875 | + |
1876 | + /// TODO: possibly implement erase() similar to std::string's erase |
1877 | + /// TODO: possibly implement a replace() call |
1878 | +private: |
1879 | + |
1880 | + MemBlob::Pointer store_; ///< memory block, possibly shared with other SBufs |
1881 | + size_type off_; ///< our content start offset from the beginning of shared store_ |
1882 | + size_type len_; ///< number of our content bytes in shared store_ |
1883 | + static SBufStats stats; ///< class-wide statistics |
1884 | + |
1885 | + /// SBuf object identifier; does not change when contents do, |
1886 | + /// including during assignment |
1887 | + const InstanceId<SBuf> id; |
1888 | + |
1889 | + _SQUID_INLINE_ static MemBlob::Pointer GetStorePrototype(); |
1890 | + |
1891 | + _SQUID_INLINE_ char * buf() const; |
1892 | + _SQUID_INLINE_ char * bufEnd() const; |
1893 | + _SQUID_INLINE_ const size_type estimateCapacity(size_type desired) const; |
1894 | + void reAlloc(size_type newsize); |
1895 | + |
1896 | + bool cow(size_type minsize = npos); |
1897 | + |
1898 | + void checkAccessBounds(size_type pos) const; |
1899 | + _SQUID_INLINE_ int commonCompareChecksPre(const SBuf &S) const; |
1900 | + _SQUID_INLINE_ int commonCompareChecksPost(const SBuf &S) const; |
1901 | + |
1902 | +}; |
1903 | + |
1904 | +/** |
1905 | + * Prints a SBuf to the supplied stream, allowing for chaining |
1906 | + */ |
1907 | +std::ostream& operator <<(std::ostream &os, const SBuf &S); |
1908 | + |
1909 | +#if _USE_INLINE_ |
1910 | +#include "SBuf.cci" |
1911 | +#endif |
1912 | + |
1913 | +#endif /* SQUID_SBUF_H */ |
1914 | |
1915 | === added file 'src/SBufExceptions.cc' |
1916 | --- src/SBufExceptions.cc 1970-01-01 00:00:00 +0000 |
1917 | +++ src/SBufExceptions.cc 2013-07-04 15:56:30 +0000 |
1918 | @@ -0,0 +1,72 @@ |
1919 | +/* |
1920 | + * SBufExceptions.cc (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
1921 | + * |
1922 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
1923 | + * ---------------------------------------------------------- |
1924 | + * |
1925 | + * Squid is the result of efforts by numerous individuals from |
1926 | + * the Internet community; see the CONTRIBUTORS file for full |
1927 | + * details. Many organizations have provided support for Squid's |
1928 | + * development; see the SPONSORS file for full details. Squid is |
1929 | + * Copyrighted (C) 2001 by the Regents of the University of |
1930 | + * California; see the COPYRIGHT file for full details. Squid |
1931 | + * incorporates software developed and/or copyrighted by other |
1932 | + * sources; see the CREDITS file for full details. |
1933 | + * |
1934 | + * This program is free software; you can redistribute it and/or modify |
1935 | + * it under the terms of the GNU General Public License as published by |
1936 | + * the Free Software Foundation; either version 2 of the License, or |
1937 | + * (at your option) any later version. |
1938 | + * |
1939 | + * This program is distributed in the hope that it will be useful, |
1940 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1941 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1942 | + * GNU General Public License for more details. |
1943 | + * |
1944 | + * You should have received a copy of the GNU General Public License |
1945 | + * along with this program; if not, write to the Free Software |
1946 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
1947 | + */ |
1948 | + |
1949 | +#include "squid.h" |
1950 | +#include "OutOfBoundsException.h" |
1951 | +#include "SBuf.h" |
1952 | +#include "SBufExceptions.h" |
1953 | + |
1954 | +// Note: the SBuf is intentionally passed by copy rather than reference, |
1955 | +// to let refcounting act. |
1956 | +OutOfBoundsException::OutOfBoundsException(const SBuf &throwingBuf, |
1957 | + SBuf::size_type &pos, |
1958 | + const char *aFileName, int aLineNo) |
1959 | + :TextException(NULL, aFileName, aLineNo) |
1960 | +{ |
1961 | + _buf = throwingBuf; |
1962 | + _pos = pos; |
1963 | + SBuf explanatoryText("OutOfBoundsException"); |
1964 | + if (aLineNo != -1) |
1965 | + explanatoryText.appendf(" at line %d", aLineNo); |
1966 | + if (aFileName != 0) |
1967 | + explanatoryText.appendf(" in file %s", aFileName); |
1968 | + explanatoryText.appendf(" while accessing position %d in a SBuf long %d", |
1969 | + pos, throwingBuf.length()); |
1970 | + // we can safely alias c_str as both are local to the object |
1971 | + // and will not further manipulated. |
1972 | + message = xstrndup(explanatoryText.c_str(),explanatoryText.length()); |
1973 | +} |
1974 | + |
1975 | +OutOfBoundsException::~OutOfBoundsException() throw() |
1976 | +{ } |
1977 | + |
1978 | +NullSBufException::NullSBufException(const char *aFilename, int aLineNo) |
1979 | + : TextException("Trying to access a null SBuf", aFilename, aLineNo) |
1980 | +{ } |
1981 | + |
1982 | +InvalidParamException::InvalidParamException(const char *aFilename, int aLineNo) |
1983 | + : TextException("Invalid parameter", aFilename, aLineNo) |
1984 | +{ } |
1985 | + |
1986 | +SBufTooBigException::SBufTooBigException(const char *aFilename, int aLineNo) |
1987 | + : TextException("Trying to create an oversize SBuf", aFilename, aLineNo) |
1988 | +{ } |
1989 | + |
1990 | +/* */ |
1991 | |
1992 | === added file 'src/SBufExceptions.h' |
1993 | --- src/SBufExceptions.h 1970-01-01 00:00:00 +0000 |
1994 | +++ src/SBufExceptions.h 2013-07-04 15:56:30 +0000 |
1995 | @@ -0,0 +1,65 @@ |
1996 | +/* |
1997 | + * SBufExceptions.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
1998 | + * |
1999 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2000 | + * ---------------------------------------------------------- |
2001 | + * |
2002 | + * Squid is the result of efforts by numerous individuals from |
2003 | + * the Internet community; see the CONTRIBUTORS file for full |
2004 | + * details. Many organizations have provided support for Squid's |
2005 | + * development; see the SPONSORS file for full details. Squid is |
2006 | + * Copyrighted (C) 2001 by the Regents of the University of |
2007 | + * California; see the COPYRIGHT file for full details. Squid |
2008 | + * incorporates software developed and/or copyrighted by other |
2009 | + * sources; see the CREDITS file for full details. |
2010 | + * |
2011 | + * This program is free software; you can redistribute it and/or modify |
2012 | + * it under the terms of the GNU General Public License as published by |
2013 | + * the Free Software Foundation; either version 2 of the License, or |
2014 | + * (at your option) any later version. |
2015 | + * |
2016 | + * This program is distributed in the hope that it will be useful, |
2017 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2018 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2019 | + * GNU General Public License for more details. |
2020 | + * |
2021 | + * You should have received a copy of the GNU General Public License |
2022 | + * along with this program; if not, write to the Free Software |
2023 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2024 | + */ |
2025 | + |
2026 | +#ifndef SQUID_SBUFEXCEPTIONS_H |
2027 | +#define SQUID_SBUFEXCEPTIONS_H |
2028 | + |
2029 | +#include "base/TextException.h" |
2030 | + |
2031 | +/** |
2032 | + * Exception raised when the user is trying to operate on a Null SBuf |
2033 | + * \todo move to an Exceptions.h? |
2034 | + */ |
2035 | +class NullSBufException : public TextException |
2036 | +{ |
2037 | +public: |
2038 | + explicit NullSBufException(const char *aFilename = 0, int aLineNo = -1); |
2039 | +}; |
2040 | + |
2041 | +/** |
2042 | + * Exception raised when call parameters are not valid |
2043 | + * \todo move to an Exceptions.h? |
2044 | + */ |
2045 | +class InvalidParamException : public TextException |
2046 | +{ |
2047 | +public: |
2048 | + explicit InvalidParamException(const char *aFilename = 0, int aLineNo = -1); |
2049 | +}; |
2050 | + |
2051 | +/** |
2052 | + * Exception raised when an attempt to resize a SBuf would cause it to reserve too big |
2053 | + */ |
2054 | +class SBufTooBigException : public TextException |
2055 | +{ |
2056 | +public: |
2057 | + explicit SBufTooBigException(const char *aFilename = 0, int aLineNo = -1); |
2058 | +}; |
2059 | + |
2060 | +#endif /* SQUID_SBUFEXCEPTIONS_H */ |
2061 | |
2062 | === added file 'src/SBufExtras.cc' |
2063 | --- src/SBufExtras.cc 1970-01-01 00:00:00 +0000 |
2064 | +++ src/SBufExtras.cc 2013-07-04 15:56:30 +0000 |
2065 | @@ -0,0 +1,104 @@ |
2066 | +/* |
2067 | + * SBufExtras.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
2068 | + * |
2069 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2070 | + * ---------------------------------------------------------- |
2071 | + * |
2072 | + * Squid is the result of efforts by numerous individuals from |
2073 | + * the Internet community; see the CONTRIBUTORS file for full |
2074 | + * details. Many organizations have provided support for Squid's |
2075 | + * development; see the SPONSORS file for full details. Squid is |
2076 | + * Copyrighted (C) 2001 by the Regents of the University of |
2077 | + * California; see the COPYRIGHT file for full details. Squid |
2078 | + * incorporates software developed and/or copyrighted by other |
2079 | + * sources; see the CREDITS file for full details. |
2080 | + * |
2081 | + * This program is free software; you can redistribute it and/or modify |
2082 | + * it under the terms of the GNU General Public License as published by |
2083 | + * the Free Software Foundation; either version 2 of the License, or |
2084 | + * (at your option) any later version. |
2085 | + * |
2086 | + * This program is distributed in the hope that it will be useful, |
2087 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2088 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2089 | + * GNU General Public License for more details. |
2090 | + * |
2091 | + * You should have received a copy of the GNU General Public License |
2092 | + * along with this program; if not, write to the Free Software |
2093 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2094 | + */ |
2095 | + |
2096 | +/* |
2097 | + * This file contains various helper functions which are meant to be |
2098 | + * a bridge towards SBuf integration, but which do not belong to SBuf proper, |
2099 | + * such as functions shuttling to and from other data types. |
2100 | + */ |
2101 | + |
2102 | +#include "squid.h" |
2103 | +#include "ipc/Messages.h" |
2104 | +#include "ipc/TypedMsgHdr.h" |
2105 | +#include "mgr/Registration.h" |
2106 | +#include "SBufExtras.h" |
2107 | +#include "StoreEntryStream.h" |
2108 | + |
2109 | +SBufStatsAction::SBufStatsAction(const Mgr::CommandPointer &cmd_): |
2110 | + Action(cmd_) |
2111 | +{ } //default constructor is OK for data member |
2112 | + |
2113 | +SBufStatsAction::Pointer |
2114 | +SBufStatsAction::Create(const Mgr::CommandPointer &cmd) |
2115 | +{ |
2116 | + debugs(24, 8, "" ); |
2117 | + return new SBufStatsAction(cmd); |
2118 | +} |
2119 | +void |
2120 | +SBufStatsAction::add(const Mgr::Action& action) |
2121 | +{ |
2122 | + debugs(24, 8, ""); |
2123 | + data.sbdata += dynamic_cast<const SBufStatsAction&>(action).data.sbdata; |
2124 | + data.mbdata += dynamic_cast<const SBufStatsAction&>(action).data.mbdata; |
2125 | +} |
2126 | + |
2127 | +void |
2128 | +SBufStatsAction::collect() |
2129 | +{ |
2130 | + debugs(24, 8, "" ); |
2131 | + data.sbdata = SBuf::GetStats(); |
2132 | + data.mbdata = MemBlob::GetStats(); |
2133 | +} |
2134 | + |
2135 | +void |
2136 | +SBufStatsAction::dump(StoreEntry* entry) |
2137 | +{ |
2138 | + debugs(24, 8, "" ); |
2139 | + Must(entry != NULL); |
2140 | + StoreEntryStream ses(entry); |
2141 | + data.sbdata.dump(ses); |
2142 | + data.mbdata.dump(ses); |
2143 | +} |
2144 | + |
2145 | +void |
2146 | +SBufStatsAction::pack(Ipc::TypedMsgHdr& msg) const |
2147 | +{ |
2148 | + debugs(24, 8, "" ); |
2149 | + msg.setType(Ipc::mtCacheMgrResponse); |
2150 | + msg.putPod(data); |
2151 | +} |
2152 | + |
2153 | +void |
2154 | +SBufStatsAction::unpack(const Ipc::TypedMsgHdr& msg) |
2155 | +{ |
2156 | + debugs(24, 8, "" ); |
2157 | + msg.checkType(Ipc::mtCacheMgrResponse); |
2158 | + msg.getPod(data); |
2159 | +} |
2160 | + |
2161 | +class SBufStatsRegistrationHelperObject |
2162 | +{ |
2163 | +public: |
2164 | + SBufStatsRegistrationHelperObject() { |
2165 | + Mgr::RegisterAction("sbuf", "String-Buffer statistics", |
2166 | + &SBufStatsAction::Create, 0 , 1); |
2167 | + } |
2168 | +}; |
2169 | +static SBufStatsRegistrationHelperObject sbufstatsinstantiator; |
2170 | |
2171 | === added file 'src/SBufExtras.h' |
2172 | --- src/SBufExtras.h 1970-01-01 00:00:00 +0000 |
2173 | +++ src/SBufExtras.h 2013-07-04 15:56:30 +0000 |
2174 | @@ -0,0 +1,66 @@ |
2175 | +/* |
2176 | + * SBufExtras.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org> |
2177 | + * |
2178 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2179 | + * ---------------------------------------------------------- |
2180 | + * |
2181 | + * Squid is the result of efforts by numerous individuals from |
2182 | + * the Internet community; see the CONTRIBUTORS file for full |
2183 | + * details. Many organizations have provided support for Squid's |
2184 | + * development; see the SPONSORS file for full details. Squid is |
2185 | + * Copyrighted (C) 2001 by the Regents of the University of |
2186 | + * California; see the COPYRIGHT file for full details. Squid |
2187 | + * incorporates software developed and/or copyrighted by other |
2188 | + * sources; see the CREDITS file for full details. |
2189 | + * |
2190 | + * This program is free software; you can redistribute it and/or modify |
2191 | + * it under the terms of the GNU General Public License as published by |
2192 | + * the Free Software Foundation; either version 2 of the License, or |
2193 | + * (at your option) any later version. |
2194 | + * |
2195 | + * This program is distributed in the hope that it will be useful, |
2196 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2197 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2198 | + * GNU General Public License for more details. |
2199 | + * |
2200 | + * You should have received a copy of the GNU General Public License |
2201 | + * along with this program; if not, write to the Free Software |
2202 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2203 | + */ |
2204 | + |
2205 | +/* |
2206 | + * This file contains various helper functions which are meant to be |
2207 | + * a bridge towards SBuf integration, but which do not belong to SBuf proper, |
2208 | + * such as functions shuttling to and from other data types. |
2209 | + */ |
2210 | + |
2211 | +#ifndef SQUID_SBUFEXTRAS_H |
2212 | +#define SQUID_SBUFEXTRAS_H |
2213 | + |
2214 | +#include "ipc/TypedMsgHdr.h" |
2215 | +#include "MemBuf.h" |
2216 | +#include "mgr/Action.h" |
2217 | +#include "SBuf.h" |
2218 | +#include "Store.h" |
2219 | + |
2220 | +class SBufStatsAction: public Mgr::Action |
2221 | +{ |
2222 | +protected: |
2223 | + SBufStatsAction(const Mgr::CommandPointer &cmd); |
2224 | + virtual void collect(); |
2225 | + virtual void dump(StoreEntry* entry); |
2226 | + |
2227 | +public: |
2228 | + static Pointer Create(const Mgr::CommandPointer &cmd); |
2229 | + virtual void add(const Mgr::Action& action); |
2230 | + virtual void pack(Ipc::TypedMsgHdr& msg) const; |
2231 | + virtual void unpack(const Ipc::TypedMsgHdr& msg); |
2232 | + |
2233 | +private: |
2234 | + struct SbufStatsActionData { |
2235 | + SBufStats sbdata; |
2236 | + MemBlobStats mbdata; |
2237 | + } data; |
2238 | +}; |
2239 | + |
2240 | +#endif /* SQUID_SBUFEXTRAS_H */ |
2241 | |
2242 | === added file 'src/SBufList.cc' |
2243 | --- src/SBufList.cc 1970-01-01 00:00:00 +0000 |
2244 | +++ src/SBufList.cc 2013-07-04 15:56:30 +0000 |
2245 | @@ -0,0 +1,56 @@ |
2246 | +/* |
2247 | + * SBufList.cc (C) 2009 Francesco Chemolli <kinkie@squid-cache.org> |
2248 | + * |
2249 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2250 | + * ---------------------------------------------------------- |
2251 | + * |
2252 | + * Squid is the result of efforts by numerous individuals from |
2253 | + * the Internet community; see the CONTRIBUTORS file for full |
2254 | + * details. Many organizations have provided support for Squid's |
2255 | + * development; see the SPONSORS file for full details. Squid is |
2256 | + * Copyrighted (C) 2001 by the Regents of the University of |
2257 | + * California; see the COPYRIGHT file for full details. Squid |
2258 | + * incorporates software developed and/or copyrighted by other |
2259 | + * sources; see the CREDITS file for full details. |
2260 | + * |
2261 | + * This program is free software; you can redistribute it and/or modify |
2262 | + * it under the terms of the GNU General Public License as published by |
2263 | + * the Free Software Foundation; either version 2 of the License, or |
2264 | + * (at your option) any later version. |
2265 | + * |
2266 | + * This program is distributed in the hope that it will be useful, |
2267 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2268 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2269 | + * GNU General Public License for more details. |
2270 | + * |
2271 | + * You should have received a copy of the GNU General Public License |
2272 | + * along with this program; if not, write to the Free Software |
2273 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2274 | + */ |
2275 | + |
2276 | +#include "squid.h" |
2277 | +#include "SBufList.h" |
2278 | + |
2279 | +SBufList& SBufList::add(SBuf S) |
2280 | +{ |
2281 | + push_back(S); |
2282 | + return *this; |
2283 | +} |
2284 | + |
2285 | +bool SBufList::isMember(const SBuf &S, SBufCaseSensitive case_sensitive) |
2286 | +{ |
2287 | + iterator i; |
2288 | + for (i = begin(); i != end(); ++i) |
2289 | + if (i->compare(S,case_sensitive) == 0) |
2290 | + return true; |
2291 | + return false; |
2292 | +} |
2293 | + |
2294 | +bool SBufList::isPrefix(const SBuf &s, SBufCaseSensitive case_sensitive) |
2295 | +{ |
2296 | + iterator i; |
2297 | + for (i = begin(); i != end(); ++i) |
2298 | + if (i->startsWith(s,case_sensitive)) |
2299 | + return true; |
2300 | + return false; |
2301 | +} |
2302 | |
2303 | === added file 'src/SBufList.h' |
2304 | --- src/SBufList.h 1970-01-01 00:00:00 +0000 |
2305 | +++ src/SBufList.h 2013-07-04 15:56:30 +0000 |
2306 | @@ -0,0 +1,62 @@ |
2307 | +/* |
2308 | + * SBufList.h (C) 2009 Francesco Chemolli <kinkie@squid-cache.org> |
2309 | + * |
2310 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2311 | + * ---------------------------------------------------------- |
2312 | + * |
2313 | + * Squid is the result of efforts by numerous individuals from |
2314 | + * the Internet community; see the CONTRIBUTORS file for full |
2315 | + * details. Many organizations have provided support for Squid's |
2316 | + * development; see the SPONSORS file for full details. Squid is |
2317 | + * Copyrighted (C) 2001 by the Regents of the University of |
2318 | + * California; see the COPYRIGHT file for full details. Squid |
2319 | + * incorporates software developed and/or copyrighted by other |
2320 | + * sources; see the CREDITS file for full details. |
2321 | + * |
2322 | + * This program is free software; you can redistribute it and/or modify |
2323 | + * it under the terms of the GNU General Public License as published by |
2324 | + * the Free Software Foundation; either version 2 of the License, or |
2325 | + * (at your option) any later version. |
2326 | + * |
2327 | + * This program is distributed in the hope that it will be useful, |
2328 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2329 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2330 | + * GNU General Public License for more details. |
2331 | + * |
2332 | + * You should have received a copy of the GNU General Public License |
2333 | + * along with this program; if not, write to the Free Software |
2334 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2335 | + */ |
2336 | + |
2337 | +#ifndef SQUID_SBUFLIST_H |
2338 | +#define SQUID_SBUFLIST_H |
2339 | + |
2340 | +#include "SBuf.h" |
2341 | +#include <list> |
2342 | + |
2343 | +/** List of SBuf |
2344 | + * |
2345 | + */ |
2346 | +class SBufList : public std::list<SBuf> |
2347 | +{ |
2348 | +public: |
2349 | + /** Add a SBuf to the list |
2350 | + * |
2351 | + * \note can be chained |
2352 | + */ |
2353 | + SBufList& add(SBuf); |
2354 | + |
2355 | + /** check for membership |
2356 | + * |
2357 | + * true if the supplied SBuf is a member of the list |
2358 | + * \param case_sensitive one of caseSensitive or caseInsensitive |
2359 | + */ |
2360 | + bool isMember(const SBuf &, SBufCaseSensitive case_sensitive = caseSensitive); |
2361 | + |
2362 | + /** check whether SBuf is prefix of any member in the list |
2363 | + * \param case_sensitive one of caseSensitive or caseInsensitive |
2364 | + */ |
2365 | + bool isPrefix(const SBuf &, SBufCaseSensitive case_sensitive = caseSensitive); |
2366 | +}; |
2367 | + |
2368 | +#endif /* SQUID_SBUFLIST_H */ |
2369 | |
2370 | === added file 'src/SBufStream.h' |
2371 | --- src/SBufStream.h 1970-01-01 00:00:00 +0000 |
2372 | +++ src/SBufStream.h 2013-07-04 15:56:30 +0000 |
2373 | @@ -0,0 +1,141 @@ |
2374 | +/* |
2375 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2376 | + * ---------------------------------------------------------- |
2377 | + * |
2378 | + * Squid is the result of efforts by numerous individuals from |
2379 | + * the Internet community; see the CONTRIBUTORS file for full |
2380 | + * details. Many organizations have provided support for Squid's |
2381 | + * development; see the SPONSORS file for full details. Squid is |
2382 | + * Copyrighted (C) 2001 by the Regents of the University of |
2383 | + * California; see the COPYRIGHT file for full details. Squid |
2384 | + * incorporates software developed and/or copyrighted by other |
2385 | + * sources; see the CREDITS file for full details. |
2386 | + * |
2387 | + * This program is free software; you can redistribute it and/or modify |
2388 | + * it under the terms of the GNU General Public License as published by |
2389 | + * the Free Software Foundation; either version 2 of the License, or |
2390 | + * (at your option) any later version. |
2391 | + * |
2392 | + * This program is distributed in the hope that it will be useful, |
2393 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2394 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2395 | + * GNU General Public License for more details. |
2396 | + * |
2397 | + * You should have received a copy of the GNU General Public License |
2398 | + * along with this program; if not, write to the Free Software |
2399 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2400 | + * |
2401 | + */ |
2402 | + |
2403 | +#ifndef SQUID_SBUFSTREAM_H |
2404 | +#define SQUID_SBUFSTREAM_H |
2405 | + |
2406 | +#include "SBuf.h" |
2407 | + |
2408 | +#if HAVE_OSTREAM |
2409 | +#include <ostream> |
2410 | +#endif |
2411 | + |
2412 | +/** |
2413 | + * streambuf class for a SBuf-backed stream interface. |
2414 | + * |
2415 | + */ |
2416 | +class SBufStreamBuf : public std::streambuf |
2417 | +{ |
2418 | +public: |
2419 | + /// initialize streambuf; use supplied SBuf as backing store |
2420 | + SBufStreamBuf(SBuf aBuf) : theBuf(aBuf) {} |
2421 | + |
2422 | + /// get a copy of the stream's contents |
2423 | + SBuf getBuf() { |
2424 | + return theBuf; |
2425 | + } |
2426 | + |
2427 | + /// clear the stream's store |
2428 | + void clearBuf() { |
2429 | + theBuf.clear(); |
2430 | + } |
2431 | + |
2432 | +protected: |
2433 | + virtual int_type overflow(int_type aChar = traits_type::eof()) { |
2434 | + std::streamsize pending(pptr() - pbase()); |
2435 | + |
2436 | + if (pending && sync()) |
2437 | + return traits_type::eof(); |
2438 | + |
2439 | + if (aChar != traits_type::eof()) { |
2440 | + char chars[1] = {static_cast<char>(aChar)}; |
2441 | + |
2442 | + if (aChar != traits_type::eof()) |
2443 | + theBuf.append(chars, 0, 1); |
2444 | + } |
2445 | + |
2446 | + pbump(-pending); // Reset pptr(). |
2447 | + return aChar; |
2448 | + } |
2449 | + |
2450 | + /* push the streambuf to the backing SBuf */ |
2451 | + virtual int sync() { |
2452 | + std::streamsize pending(pptr() - pbase()); |
2453 | + |
2454 | + if (pending) |
2455 | + theBuf.append(pbase(), 0, pending); |
2456 | + |
2457 | + return 0; |
2458 | + } |
2459 | + |
2460 | + /* write multiple characters to the store entry |
2461 | + * - this is an optimisation method. |
2462 | + */ |
2463 | + virtual std::streamsize xsputn(const char * chars, std::streamsize number) { |
2464 | + if (number) |
2465 | + theBuf.append(chars, 0, number); |
2466 | + |
2467 | + return number; |
2468 | + } |
2469 | + |
2470 | +private: |
2471 | + SBuf theBuf; |
2472 | + SBufStreamBuf(); // no default constructor |
2473 | +}; |
2474 | + |
2475 | +/** Stream interface to write to a SBuf. |
2476 | + * |
2477 | + * Data is appended using standard operator << semantics, and extracted |
2478 | + * using the buf() method, in analogy with std::strstream . |
2479 | + */ |
2480 | +class SBufStream : public std::ostream |
2481 | +{ |
2482 | +public: |
2483 | + /** Create a SBufStream preinitialized with the argument's SBuf. |
2484 | + * |
2485 | + * The supplied SBuf is not aliased: in order to retrieve the altered contents |
2486 | + * they must be fetched using the buf() class method. |
2487 | + */ |
2488 | + SBufStream(SBuf aBuf): std::ostream(0), theBuffer(aBuf) { |
2489 | + rdbuf(&theBuffer); // set the buffer to now-initialized theBuffer |
2490 | + clear(); //clear badbit set by calling init(0) |
2491 | + } |
2492 | + |
2493 | + /// Create an empty SBufStream |
2494 | + SBufStream(): std::ostream(0), theBuffer(SBuf()) { |
2495 | + rdbuf(&theBuffer); // set the buffer to now-initialized theBuffer |
2496 | + clear(); //clear badbit set by calling init(0) |
2497 | + } |
2498 | + |
2499 | + /// Retrieve a copy of the current stream status |
2500 | + SBuf buf() { |
2501 | + return theBuffer.getBuf(); |
2502 | + } |
2503 | + |
2504 | + /// Clear the stream's backing store |
2505 | + SBufStream& clearBuf() { |
2506 | + theBuffer.clearBuf(); |
2507 | + return *this; |
2508 | + } |
2509 | + |
2510 | +private: |
2511 | + SBufStreamBuf theBuffer; |
2512 | +}; |
2513 | + |
2514 | +#endif /* SQUID_SBUFSTREAM_H */ |
2515 | |
2516 | === added file 'src/SBufTokenizer.cc' |
2517 | --- src/SBufTokenizer.cc 1970-01-01 00:00:00 +0000 |
2518 | +++ src/SBufTokenizer.cc 2013-07-04 15:56:30 +0000 |
2519 | @@ -0,0 +1,68 @@ |
2520 | +/* |
2521 | + * SBufTokenizer.cc (C) 2008 Francesco Chemollli <kinkie@squid-cache.org> |
2522 | + * |
2523 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2524 | + * ---------------------------------------------------------- |
2525 | + * |
2526 | + * Squid is the result of efforts by numerous individuals from |
2527 | + * the Internet community; see the CONTRIBUTORS file for full |
2528 | + * details. Many organizations have provided support for Squid's |
2529 | + * development; see the SPONSORS file for full details. Squid is |
2530 | + * Copyrighted (C) 2001 by the Regents of the University of |
2531 | + * California; see the COPYRIGHT file for full details. Squid |
2532 | + * incorporates software developed and/or copyrighted by other |
2533 | + * sources; see the CREDITS file for full details. |
2534 | + * |
2535 | + * This program is free software; you can redistribute it and/or modify |
2536 | + * it under the terms of the GNU General Public License as published by |
2537 | + * the Free Software Foundation; either version 2 of the License, or |
2538 | + * (at your option) any later version. |
2539 | + * |
2540 | + * This program is distributed in the hope that it will be useful, |
2541 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2542 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2543 | + * GNU General Public License for more details. |
2544 | + * |
2545 | + * You should have received a copy of the GNU General Public License |
2546 | + * along with this program; if not, write to the Free Software |
2547 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2548 | + */ |
2549 | + |
2550 | +#include "squid.h" |
2551 | +#include "Debug.h" |
2552 | +#include "SBufTokenizer.h" |
2553 | + |
2554 | +void SBufTokenizer::reset(const SBuf &toparse, const SBuf &delim) |
2555 | +{ |
2556 | + debugs(24, 4, "SBufTokenizer::reset()"); |
2557 | + _toParse = toparse; |
2558 | + _delim = delim; |
2559 | + _lastToken.clear(); |
2560 | + _lastDelim = 0; |
2561 | + next(); |
2562 | +} |
2563 | + |
2564 | +SBufTokenizer& SBufTokenizer::next() |
2565 | +{ |
2566 | + debugs(24, 7, "SBufTokenizer::next()"); |
2567 | + SBuf::size_type tok; |
2568 | + tok = _toParse.find_first_of(_delim); |
2569 | + if (tok == SBuf::npos) { |
2570 | + debugs(24, 8, "SBufTokenizer::token(): separator not found"); |
2571 | + _lastToken = _toParse; |
2572 | + _toParse.clear(); |
2573 | + _lastDelim = '\0'; |
2574 | + } else { |
2575 | + _lastDelim = _toParse[tok]; |
2576 | + _lastToken = _toParse.consume(tok); |
2577 | + _toParse.consume(1); //the separator |
2578 | + } |
2579 | + return *this; |
2580 | +} |
2581 | + |
2582 | +bool SBufTokenizer::atEnd() const |
2583 | +{ |
2584 | + debugs(24, 8, "result: " << (_toParse.length() == 0)); |
2585 | + return (_toParse.length() == 0 && _lastToken.length() == 0); |
2586 | +} |
2587 | + |
2588 | |
2589 | === added file 'src/SBufTokenizer.h' |
2590 | --- src/SBufTokenizer.h 1970-01-01 00:00:00 +0000 |
2591 | +++ src/SBufTokenizer.h 2013-07-04 15:56:30 +0000 |
2592 | @@ -0,0 +1,149 @@ |
2593 | +/* |
2594 | + * SBuTokenizer.h (C) 2008 Francesco Chemollli <kinkie@squid-cache.org> |
2595 | + * |
2596 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2597 | + * ---------------------------------------------------------- |
2598 | + * |
2599 | + * Squid is the result of efforts by numerous individuals from |
2600 | + * the Internet community; see the CONTRIBUTORS file for full |
2601 | + * details. Many organizations have provided support for Squid's |
2602 | + * development; see the SPONSORS file for full details. Squid is |
2603 | + * Copyrighted (C) 2001 by the Regents of the University of |
2604 | + * California; see the COPYRIGHT file for full details. Squid |
2605 | + * incorporates software developed and/or copyrighted by other |
2606 | + * sources; see the CREDITS file for full details. |
2607 | + * |
2608 | + * This program is free software; you can redistribute it and/or modify |
2609 | + * it under the terms of the GNU General Public License as published by |
2610 | + * the Free Software Foundation; either version 2 of the License, or |
2611 | + * (at your option) any later version. |
2612 | + * |
2613 | + * This program is distributed in the hope that it will be useful, |
2614 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2615 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2616 | + * GNU General Public License for more details. |
2617 | + * |
2618 | + * You should have received a copy of the GNU General Public License |
2619 | + * along with this program; if not, write to the Free Software |
2620 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2621 | + */ |
2622 | + |
2623 | +#ifndef SQUID_SBUFTOKENIZER_H |
2624 | +#define SQUID_SBUFTOKENIZER_H |
2625 | + |
2626 | +#include "SBuf.h" |
2627 | + |
2628 | +/** |
2629 | + * A tokenizer for SBuf |
2630 | + * example: |
2631 | + * \code |
2632 | + * SBuf toparse, sep; |
2633 | + * toparse = ...; sep = ...; |
2634 | + * for (SBufTokenizer st(toparse,sep);!st.atEnd();st.next()) { |
2635 | + * SBuf s = st.token(); |
2636 | + * //... |
2637 | + * } |
2638 | + * \endcode |
2639 | + */ |
2640 | +class SBufTokenizer |
2641 | +{ |
2642 | +public: |
2643 | + /** Constructor |
2644 | + * |
2645 | + * create a new SBufTokenizer to check over the contents of toparse, |
2646 | + * using any of the characters of delim as a token delimiter |
2647 | + * \param toparse the SBuf to be tokenized |
2648 | + * \param delim the token separator. It's a SBuf which is interpreted |
2649 | + * as a bag of chars, whose each is a possible token delimiter. |
2650 | + */ |
2651 | + SBufTokenizer(const SBuf &toparse, const SBuf &delim) |
2652 | + { |
2653 | + reset(toparse,delim); |
2654 | + } |
2655 | + |
2656 | + /** reset the Tokenizer |
2657 | + * |
2658 | + * reset the SBufTokenizer with a new SBuf to be parsed and a new |
2659 | + * delimiter set. |
2660 | + * \param toparse the SBuf to be tokenized |
2661 | + * \param delim the token separator. It's a SBuf which is interpreted |
2662 | + */ |
2663 | + void reset(const SBuf &toparse, const SBuf &delim); |
2664 | + |
2665 | + /** set a new delimiter set |
2666 | + * |
2667 | + * \param newdelim the token separator. |
2668 | + */ |
2669 | + void setDelimiter(const SBuf &newdelim) |
2670 | + { |
2671 | + _delim = newdelim; |
2672 | + } |
2673 | + |
2674 | + /** retrieve the current delimiter set |
2675 | + */ |
2676 | + SBuf getDelimiter() const |
2677 | + { |
2678 | + return _delim; |
2679 | + } |
2680 | + |
2681 | + /** Extract the next Token |
2682 | + * |
2683 | + * strtok()-equivalent. |
2684 | + * Will extract a token from the beginning of the SBuf, containing |
2685 | + * all chars up to the first occurrence of any of the chars in |
2686 | + * <i>delim</i> or end-of-SBuf if no delimiter can be found. |
2687 | + * The tokenized SBuf is modified, by removing its head |
2688 | + * the to-be-returned token AND the delimiter. |
2689 | + */ |
2690 | + SBufTokenizer& next(); |
2691 | + |
2692 | + /** get last delimiter found |
2693 | + * |
2694 | + ** returns the delimiter which terminated the last-matched token |
2695 | + * If no token() has not been extracted or we are at the end of the |
2696 | + * SBuf to be tokenized, the result is undefined |
2697 | + */ |
2698 | + char separator() const |
2699 | + { |
2700 | + return _lastDelim; |
2701 | + } |
2702 | + |
2703 | + /** Move to the next token, specify new delimiter |
2704 | + * |
2705 | + * Move to the next token, and a new delimiter to parse it |
2706 | + */ |
2707 | + SBufTokenizer &next(const SBuf &newdelim) |
2708 | + { |
2709 | + setDelimiter(newdelim); |
2710 | + return next(); |
2711 | + } |
2712 | + |
2713 | + /** Extract a token |
2714 | + * |
2715 | + * Extract a token from the SBuf. May be called repeatedly, in that case |
2716 | + * will return each time a fresh copy of the same token. |
2717 | + */ |
2718 | + SBuf token() const |
2719 | + { |
2720 | + return _lastToken; |
2721 | + } |
2722 | + |
2723 | + /** check whether we are done |
2724 | + * |
2725 | + * \retval true if we are at the SBuf to be parsed. |
2726 | + */ |
2727 | + bool atEnd() const; |
2728 | + |
2729 | +private: |
2730 | + SBuf _toParse; /// the still-unparsed part of the buffer to parse |
2731 | + SBuf _lastToken;/// the last returned token |
2732 | + char _lastDelim;/// the delimiter last matched |
2733 | + SBuf _delim; /// a SBuf containing the delimiter characters |
2734 | + |
2735 | + SBuf::size_type pbrk() const |
2736 | + { |
2737 | + return _toParse.find_first_of(_delim); |
2738 | + } |
2739 | +}; |
2740 | + |
2741 | +#endif |
2742 | |
2743 | === added file 'src/SBufUtil.cc' |
2744 | --- src/SBufUtil.cc 1970-01-01 00:00:00 +0000 |
2745 | +++ src/SBufUtil.cc 2013-07-04 15:56:30 +0000 |
2746 | @@ -0,0 +1,64 @@ |
2747 | +/* |
2748 | + * SBufUtil.cc (C) 2009 Francesco Chemolli <kinkie@squid-cache.org> |
2749 | + * |
2750 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2751 | + * ---------------------------------------------------------- |
2752 | + * |
2753 | + * Squid is the result of efforts by numerous individuals from |
2754 | + * the Internet community; see the CONTRIBUTORS file for full |
2755 | + * details. Many organizations have provided support for Squid's |
2756 | + * development; see the SPONSORS file for full details. Squid is |
2757 | + * Copyrighted (C) 2001 by the Regents of the University of |
2758 | + * California; see the COPYRIGHT file for full details. Squid |
2759 | + * incorporates software developed and/or copyrighted by other |
2760 | + * sources; see the CREDITS file for full details. |
2761 | + * |
2762 | + * This program is free software; you can redistribute it and/or modify |
2763 | + * it under the terms of the GNU General Public License as published by |
2764 | + * the Free Software Foundation; either version 2 of the License, or |
2765 | + * (at your option) any later version. |
2766 | + * |
2767 | + * This program is distributed in the hope that it will be useful, |
2768 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2769 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2770 | + * GNU General Public License for more details. |
2771 | + * |
2772 | + * You should have received a copy of the GNU General Public License |
2773 | + * along with this program; if not, write to the Free Software |
2774 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2775 | + */ |
2776 | + |
2777 | +#include "squid.h" |
2778 | +#include "SBufUtil.h" |
2779 | + |
2780 | +SBuf |
2781 | +SBufListJoin(SBufList &list, const SBuf &separator) |
2782 | +{ |
2783 | + SBufList::iterator i; |
2784 | + SBuf::size_type sz = 0; |
2785 | + //first thing: calculate the length to reserveSpace |
2786 | + for (i = list.begin(); i!= list.end(); ++i) |
2787 | + sz += (*i).length()+separator.length(); |
2788 | + SBuf rv; |
2789 | + rv.reserveSpace(sz); |
2790 | + i = list.begin(); |
2791 | + if (i != list.end()) |
2792 | + rv.append(*i); |
2793 | + ++i; |
2794 | + if (i != list.end()) { |
2795 | + for (; i!= list.end(); i++) { |
2796 | + rv.append(separator); |
2797 | + rv.append(*i); |
2798 | + } |
2799 | + } |
2800 | + return rv; |
2801 | +} |
2802 | + |
2803 | +SBuf |
2804 | +BaseName(const SBuf &s, char separator) |
2805 | +{ |
2806 | + SBuf::size_type pos = s.rfind(separator); |
2807 | + if (pos == SBuf::npos) |
2808 | + return s; |
2809 | + return s.substr(pos+1); |
2810 | +} |
2811 | |
2812 | === added file 'src/SBufUtil.h' |
2813 | --- src/SBufUtil.h 1970-01-01 00:00:00 +0000 |
2814 | +++ src/SBufUtil.h 2013-07-04 15:56:30 +0000 |
2815 | @@ -0,0 +1,51 @@ |
2816 | +/* |
2817 | + * SBufUtil.h (C) 2009 Francesco Chemolli <kinkie@squid-cache.org> |
2818 | + * |
2819 | + * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2820 | + * ---------------------------------------------------------- |
2821 | + * |
2822 | + * Squid is the result of efforts by numerous individuals from |
2823 | + * the Internet community; see the CONTRIBUTORS file for full |
2824 | + * details. Many organizations have provided support for Squid's |
2825 | + * development; see the SPONSORS file for full details. Squid is |
2826 | + * Copyrighted (C) 2001 by the Regents of the University of |
2827 | + * California; see the COPYRIGHT file for full details. Squid |
2828 | + * incorporates software developed and/or copyrighted by other |
2829 | + * sources; see the CREDITS file for full details. |
2830 | + * |
2831 | + * This program is free software; you can redistribute it and/or modify |
2832 | + * it under the terms of the GNU General Public License as published by |
2833 | + * the Free Software Foundation; either version 2 of the License, or |
2834 | + * (at your option) any later version. |
2835 | + * |
2836 | + * This program is distributed in the hope that it will be useful, |
2837 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2838 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2839 | + * GNU General Public License for more details. |
2840 | + * |
2841 | + * You should have received a copy of the GNU General Public License |
2842 | + * along with this program; if not, write to the Free Software |
2843 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2844 | + */ |
2845 | + |
2846 | +#ifndef SQUID_SBUFUTIL_H |
2847 | +#define SQUID_SBUFUTIL_H |
2848 | + |
2849 | +#include "SBuf.h" |
2850 | +#include "SBufList.h" |
2851 | +#include "SBufTokenizer.h" |
2852 | + |
2853 | +/** join a SBufList into a SBuf using the supplied separator. |
2854 | + */ |
2855 | +SBuf SBufListJoin(SBufList &list, const SBuf &separator); |
2856 | + |
2857 | +/** Obtain the basename of a file. |
2858 | + * |
2859 | + * Returns the part of a SBuf after the last occurrence of the specified delimiter. |
2860 | + * If the delimiter is not found, return the whole SBuf |
2861 | + * \param s the SBuf to be analyzed |
2862 | + * \param separator the separating character (defaults to '/') |
2863 | + */ |
2864 | +SBuf BaseName(const SBuf &s, char separator = '/'); |
2865 | + |
2866 | +#endif /* SQUID_SBUFUTIL_H */ |
2867 | |
2868 | === modified file 'src/SquidString.h' |
2869 | --- src/SquidString.h 2012-09-22 10:56:48 +0000 |
2870 | +++ src/SquidString.h 2013-07-04 15:56:30 +0000 |
2871 | @@ -43,40 +43,6 @@ |
2872 | #define SQUIDSTRINGPRINT(s) (s).psize(),(s).rawBuf() |
2873 | #endif /* SQUIDSTRINGPH */ |
2874 | |
2875 | -#define DEBUGSTRINGS 0 |
2876 | -#if DEBUGSTRINGS |
2877 | -#include "splay.h" |
2878 | - |
2879 | -class String; |
2880 | - |
2881 | -class StringRegistry |
2882 | -{ |
2883 | - |
2884 | -public: |
2885 | - static StringRegistry &Instance(); |
2886 | - |
2887 | - void add(String const *); |
2888 | - |
2889 | - StringRegistry(); |
2890 | - |
2891 | - void remove(String const *); |
2892 | - |
2893 | -private: |
2894 | - static OBJH Stat; |
2895 | - |
2896 | - static StringRegistry Instance_; |
2897 | - |
2898 | - static SplayNode<String const *>::SPLAYWALKEE Stater; |
2899 | - |
2900 | - Splay<String const *> entries; |
2901 | - |
2902 | - bool registered; |
2903 | - |
2904 | -}; |
2905 | - |
2906 | -class StoreEntry; |
2907 | -#endif |
2908 | - |
2909 | class String |
2910 | { |
2911 | |
2912 | @@ -150,10 +116,6 @@ |
2913 | |
2914 | _SQUID_INLINE_ void cut(size_type newLength); |
2915 | |
2916 | -#if DEBUGSTRINGS |
2917 | - void stat(StoreEntry *) const; |
2918 | -#endif |
2919 | - |
2920 | private: |
2921 | void allocAndFill(const char *str, int len); |
2922 | void allocBuffer(size_type sz); |
2923 | |
2924 | === modified file 'src/StrList.h' |
2925 | --- src/StrList.h 2012-09-21 14:57:30 +0000 |
2926 | +++ src/StrList.h 2013-07-04 15:56:30 +0000 |
2927 | @@ -1,7 +1,4 @@ |
2928 | /* |
2929 | - * DEBUG: section 66 HTTP Header Tools |
2930 | - * AUTHOR: Alex Rousskov |
2931 | - * |
2932 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
2933 | * ---------------------------------------------------------- |
2934 | * |
2935 | @@ -28,16 +25,77 @@ |
2936 | * along with this program; if not, write to the Free Software |
2937 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
2938 | * |
2939 | + * Copyright (c) 2010 Francesco Chemolli <kinkie@squid-cache.org> |
2940 | */ |
2941 | |
2942 | -#ifndef SQUID_STRLIST_H_ |
2943 | -#define SQUID_STRLIST_H_ |
2944 | +#ifndef STRLIST_H_ |
2945 | +#define STRLIST_H_ |
2946 | |
2947 | -class String; |
2948 | +#include "SBufList.h" |
2949 | +#include "SBufUtil.h" |
2950 | +#include "SquidString.h" |
2951 | +#include "protos.h" |
2952 | |
2953 | void strListAdd(String * str, const char *item, char del); |
2954 | int strListIsMember(const String * str, const char *item, char del); |
2955 | int strListIsSubstr(const String * list, const char *s, char del); |
2956 | int strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos); |
2957 | |
2958 | -#endif /* SQUID_STRLIST_H_ */ |
2959 | +#if 0 |
2960 | +/* incomplete code, do not use! |
2961 | + * It is meant to eventually turn the strList* functions into proper object |
2962 | + * manipulators. |
2963 | + * TODO: finish and use it. |
2964 | + */ |
2965 | +class StrList |
2966 | +{ |
2967 | +public: |
2968 | + StrList() { } |
2969 | + explicit StrList(const SBufList &s) { |
2970 | + const SBuf sep(", "); |
2971 | + SBuf b=SBufListJoin(s,sep); |
2972 | + data_=b.toString(); |
2973 | + } |
2974 | + explicit StrList(const char *s) { |
2975 | + data_=s; |
2976 | + } |
2977 | + explicit StrList (const SBuf &s) { |
2978 | + data_=s.toString(); |
2979 | + } |
2980 | + ~StrList() { data_.clean(); }; |
2981 | + void StrListAdd(const char *item, char del) { |
2982 | + strListAdd(&data_,item,del); |
2983 | + } |
2984 | + int StrListIsMember(const char *item, char del=',') { |
2985 | + return strListIsMember(&data_,item,del); |
2986 | + } |
2987 | + int StrListIsSubstr(const char *s, char del) { |
2988 | + return strListIsSubstr(&data_, s, del); |
2989 | + } |
2990 | + int StrListGetItem(char del, const char **item, int *ilen, const char **pos) { |
2991 | + return strListGetItem(&data_, del, item, ilen, pos); |
2992 | + } |
2993 | + String StrListGetString() { |
2994 | + return data_; |
2995 | + } |
2996 | + void clear() { |
2997 | + data_.clean(); |
2998 | + } |
2999 | + void append(char const *buf, int len) { |
3000 | + data_.append(buf,len); |
3001 | + } |
3002 | + void append(char const *buf) { |
3003 | + data_.append(buf); |
3004 | + } |
3005 | + String::size_type size() const { |
3006 | + return data_.size(); |
3007 | + } |
3008 | + |
3009 | +private: |
3010 | + String data_; |
3011 | + SBufList ndata; |
3012 | +}; |
3013 | + |
3014 | +#endif |
3015 | + |
3016 | +#endif /* STRLIST_H_ */ |
3017 | |
3018 | === modified file 'src/icmp/Makefile.am' |
3019 | --- src/icmp/Makefile.am 2010-11-01 05:44:28 +0000 |
3020 | +++ src/icmp/Makefile.am 2013-07-04 15:56:30 +0000 |
3021 | @@ -22,6 +22,25 @@ |
3022 | |
3023 | noinst_LTLIBRARIES = libicmp-core.la libicmp.la |
3024 | |
3025 | +SBUF_SOURCE= \ |
3026 | + $(top_srcdir)/src/SBuf.h \ |
3027 | + $(top_srcdir)/src/SBuf.cc \ |
3028 | + $(top_srcdir)/src/MemBlob.h \ |
3029 | + $(top_srcdir)/src/MemBlob.cc \ |
3030 | + $(top_srcdir)/src/OutOfBoundsException.h \ |
3031 | + $(top_srcdir)/src/SBufExceptions.h \ |
3032 | + $(top_srcdir)/src/SBufExceptions.cc \ |
3033 | + $(top_srcdir)/src/SBufTokenizer.h \ |
3034 | + $(top_srcdir)/src/SBufTokenizer.cc \ |
3035 | + $(top_srcdir)/src/SBufList.h \ |
3036 | + $(top_srcdir)/src/SBufList.cc \ |
3037 | + $(top_srcdir)/src/SBufUtil.h \ |
3038 | + $(top_srcdir)/src/SBufUtil.cc \ |
3039 | + $(top_srcdir)/src/String.cc \ |
3040 | + $(top_srcdir)/src/SquidString.h \ |
3041 | + $(top_srcdir)/src/base/TextException.h \ |
3042 | + $(top_srcdir)/src/base/TextException.cc |
3043 | + |
3044 | # ICMP API definition ... |
3045 | libicmp_core_la_SOURCES = \ |
3046 | Icmp.h \ |
3047 | |
3048 | === added file 'src/tests/SBufFindTest.cc' |
3049 | --- src/tests/SBufFindTest.cc 1970-01-01 00:00:00 +0000 |
3050 | +++ src/tests/SBufFindTest.cc 2013-07-04 15:56:30 +0000 |
3051 | @@ -0,0 +1,418 @@ |
3052 | +#include "squid.h" |
3053 | +#include "SBufFindTest.h" |
3054 | +#include <cppunit/extensions/HelperMacros.h> |
3055 | +#include <cppunit/Message.h> |
3056 | +#include <limits> |
3057 | + |
3058 | + |
3059 | +/* TODO: The whole SBufFindTest class is currently implemented as a single |
3060 | + CppUnit test case (because we do not want to register and report every one |
3061 | + of the thousands of generated test cases). Is there a better way to |
3062 | + integrate with CppUnit? |
3063 | + */ |
3064 | + |
3065 | + |
3066 | +SBufFindTest::SBufFindTest(): |
3067 | + caseLimit(std::numeric_limits<int>::max()), |
3068 | + errorLimit(std::numeric_limits<int>::max()), |
3069 | + randomSeed(1), |
3070 | + hushSimilar(true), |
3071 | + maxHayLength(40), |
3072 | + thePos(0), |
3073 | + thePlacement(placeEof), |
3074 | + theStringPos(0), |
3075 | + theBareNeedlePos(0), |
3076 | + caseCount(0), |
3077 | + errorCount(0), |
3078 | + reportCount(0) |
3079 | +{ |
3080 | +} |
3081 | + |
3082 | +void |
3083 | +SBufFindTest::run() |
3084 | +{ |
3085 | + srandom(randomSeed); |
3086 | + |
3087 | + for (SBuf::size_type hayLen = 0; hayLen <= maxHayLength; nextLen(hayLen, maxHayLength)) { |
3088 | + const SBuf cleanHay = RandomSBuf(hayLen); |
3089 | + |
3090 | + const SBuf::size_type maxNeedleLen = hayLen + 10; |
3091 | + for (SBuf::size_type needleLen = 0; needleLen <= maxNeedleLen; nextLen(needleLen, maxNeedleLen)) { |
3092 | + theSBufNeedle = RandomSBuf(needleLen); |
3093 | + |
3094 | + for (int i = 0; i < placeEof; i++) { |
3095 | + thePlacement = Placement(i); |
3096 | + placeNeedle(cleanHay); |
3097 | + |
3098 | + const SBuf::size_type maxArg = |
3099 | + max(theSBufHay.length(), theSBufNeedle.length()) + 10; |
3100 | + for (thePos = 0; thePos <= maxArg; nextLen(thePos, maxArg)) |
3101 | + testAllMethods(); |
3102 | + |
3103 | + // also test the special npos value |
3104 | + thePos = SBuf::npos; |
3105 | + testAllMethods(); |
3106 | + } |
3107 | + } |
3108 | + } |
3109 | + |
3110 | + if (errorCount > 0) { |
3111 | + std::cerr << "Generated SBuf test cases: " << caseCount << std::endl; |
3112 | + std::cerr << "\tfailed cases: " << errorCount << std::endl; |
3113 | + std::cerr << "\treported cases: " << reportCount << std::endl; |
3114 | + std::cerr << "Asserting because some cases failed..." << std::endl; |
3115 | + CPPUNIT_ASSERT(!SBufFindTest::errorCount); |
3116 | + } |
3117 | +} |
3118 | + |
3119 | +/// tests SBuf::find(string needle) |
3120 | +void |
3121 | +SBufFindTest::testFindDefs() { |
3122 | + theFindString = theBareNeedlePos = theStringHay.find(theStringNeedle); |
3123 | + theFindSBuf = theSBufHay.find(theSBufNeedle); |
3124 | + checkResults("find"); |
3125 | +} |
3126 | + |
3127 | +/// tests SBuf::rfind(string needle) |
3128 | +void |
3129 | +SBufFindTest::testRFindDefs() { |
3130 | + theFindString = theBareNeedlePos = theStringHay.rfind(theStringNeedle); |
3131 | + theFindSBuf = theSBufHay.rfind(theSBufNeedle); |
3132 | + checkResults("rfind"); |
3133 | +} |
3134 | + |
3135 | +/// tests SBuf::find(string needle, pos) |
3136 | +void |
3137 | +SBufFindTest::testFind() { |
3138 | + theFindString = theStringHay.find(theStringNeedle, thePos); |
3139 | + theBareNeedlePos = theStringHay.find(theStringNeedle); |
3140 | + theFindSBuf = theSBufHay.find(theSBufNeedle, thePos); |
3141 | + checkResults("find"); |
3142 | +} |
3143 | + |
3144 | +/// tests SBuf::rfind(string needle, pos) |
3145 | +void |
3146 | +SBufFindTest::testRFind() { |
3147 | + theFindString = theStringHay.rfind(theStringNeedle, thePos); |
3148 | + theBareNeedlePos = theStringHay.rfind(theStringNeedle); |
3149 | + theFindSBuf = theSBufHay.rfind(theSBufNeedle, thePos); |
3150 | + checkResults("rfind"); |
3151 | +} |
3152 | + |
3153 | +/// tests SBuf::find(char needle) |
3154 | +void |
3155 | +SBufFindTest::testFindCharDefs() { |
3156 | + const char c = theStringNeedle[0]; |
3157 | + theFindString = theBareNeedlePos = theStringHay.find(c); |
3158 | + theFindSBuf = theSBufHay.find(c); |
3159 | + checkResults("find"); |
3160 | +} |
3161 | + |
3162 | +/// tests SBuf::find(char needle, pos) |
3163 | +void |
3164 | +SBufFindTest::testFindChar() { |
3165 | + const char c = theStringNeedle[0]; |
3166 | + theFindString = theStringHay.find(c, thePos); |
3167 | + theBareNeedlePos = theStringHay.find(c); |
3168 | + theFindSBuf = theSBufHay.find(c, thePos); |
3169 | + checkResults("find"); |
3170 | +} |
3171 | + |
3172 | +/// tests SBuf::rfind(char needle) |
3173 | +void |
3174 | +SBufFindTest::testRFindCharDefs() { |
3175 | + const char c = theStringNeedle[0]; |
3176 | + theFindString = theBareNeedlePos = theStringHay.rfind(c); |
3177 | + theFindSBuf = theSBufHay.rfind(c); |
3178 | + checkResults("rfind"); |
3179 | +} |
3180 | + |
3181 | +/// tests SBuf::rfind(char needle, pos) |
3182 | +void |
3183 | +SBufFindTest::testRFindChar() { |
3184 | + const char c = theStringNeedle[0]; |
3185 | + theFindString = theStringHay.rfind(c, thePos); |
3186 | + theBareNeedlePos = theStringHay.rfind(c); |
3187 | + theFindSBuf = theSBufHay.rfind(c, thePos); |
3188 | + checkResults("rfind"); |
3189 | +} |
3190 | + |
3191 | +/// whether the last SBuf and std::string find() results are the same |
3192 | +bool |
3193 | +SBufFindTest::resultsMatch() const { |
3194 | + // this method is needed because SBuf and std::string use different |
3195 | + // size_types (and npos values); comparing the result values directly |
3196 | + // would lead to bugs |
3197 | + |
3198 | + if (theFindString == std::string::npos && theFindSBuf == SBuf::npos) |
3199 | + return true; // both npos |
3200 | + |
3201 | + if (theFindSBuf < 0) // should not happen, treat as error |
3202 | + return false; |
3203 | + |
3204 | + // now safe to cast a non-negative SBuf result |
3205 | + return theFindString == static_cast<std::string::size_type>(theFindSBuf); |
3206 | +} |
3207 | + |
3208 | +/// called at the end of test case to update state, detect and report failures |
3209 | +void |
3210 | +SBufFindTest::checkResults(const char *method) { |
3211 | + ++caseCount; |
3212 | + if (!resultsMatch()) |
3213 | + handleFailure(method); |
3214 | +} |
3215 | + |
3216 | +/// helper function to convert "printable" Type to std::string |
3217 | +template<typename Type> |
3218 | +inline std::string |
3219 | +AnyToString(const Type &value) |
3220 | +{ |
3221 | + std::stringstream sbuf; |
3222 | + sbuf << value; |
3223 | + return sbuf.str(); |
3224 | +} |
3225 | + |
3226 | +/// helper function to convert SBuf position to a human-friendly string |
3227 | +inline std::string |
3228 | +PosToString(const SBuf::size_type pos) |
3229 | +{ |
3230 | + return pos == SBuf::npos ? std::string("npos") : AnyToString(pos); |
3231 | +} |
3232 | + |
3233 | +/// helper function to convert std::string position to a human-friendly string |
3234 | +inline std::string |
3235 | +PosToString(const std::string::size_type pos) |
3236 | +{ |
3237 | + return pos == std::string::npos ? std::string("npos") : AnyToString(pos); |
3238 | +} |
3239 | + |
3240 | +/// tests each supported SBuf::*find() method using generated hay, needle, pos |
3241 | +void |
3242 | +SBufFindTest::testAllMethods() { |
3243 | + theStringHay = std::string(theSBufHay.rawContent(), theSBufHay.length()); |
3244 | + theStringNeedle = std::string(theSBufNeedle.rawContent(), theSBufNeedle.length()); |
3245 | + theBareNeedlePos = std::string::npos; |
3246 | + const std::string reportPos = PosToString(thePos); |
3247 | + |
3248 | + // always test string search |
3249 | + { |
3250 | + theReportQuote = '"'; |
3251 | + theReportNeedle = theStringNeedle; |
3252 | + |
3253 | + theReportPos = ""; |
3254 | + testFindDefs(); |
3255 | + testRFindDefs(); |
3256 | + |
3257 | + theReportPos = reportPos; |
3258 | + testFind(); |
3259 | + testRFind(); |
3260 | + } |
3261 | + |
3262 | + // if possible, test char search |
3263 | + if (!theStringNeedle.empty()) { |
3264 | + theReportQuote = '\''; |
3265 | + theReportNeedle = theStringNeedle[0]; |
3266 | + |
3267 | + theReportPos = ""; |
3268 | + testFindCharDefs(); |
3269 | + testRFindCharDefs(); |
3270 | + |
3271 | + theReportPos = reportPos; |
3272 | + testFindChar(); |
3273 | + testRFindChar(); |
3274 | + } |
3275 | +} |
3276 | + |
3277 | +/// helper function to format a length-based key (part of case category string) |
3278 | +inline std::string |
3279 | +lengthKey(const std::string &str) |
3280 | +{ |
3281 | + if (str.length() == 0) |
3282 | + return "0"; |
3283 | + if (str.length() == 1) |
3284 | + return "1"; |
3285 | + return "N"; |
3286 | +} |
3287 | + |
3288 | +/// formats position key (part of the case category string) |
3289 | +std::string |
3290 | +SBufFindTest::posKey() const |
3291 | +{ |
3292 | + // the search position does not matter if needle is not in hay |
3293 | + if (theBareNeedlePos == std::string::npos) |
3294 | + return std::string(); |
3295 | + |
3296 | + if (thePos == SBuf::npos) |
3297 | + return ",npos"; |
3298 | + |
3299 | + if (thePos < 0) |
3300 | + return ",posN"; // negative |
3301 | + |
3302 | + // we know Pos is not negative or special; avoid signed/unsigned warnings |
3303 | + const std::string::size_type pos = |
3304 | + static_cast<std::string::size_type>(thePos); |
3305 | + |
3306 | + if (pos < theBareNeedlePos) |
3307 | + return ",posL"; // to the Left of the needle |
3308 | + if (pos == theBareNeedlePos) |
3309 | + return ",posB"; // Beginning of the needle |
3310 | + if (pos < theBareNeedlePos + theStringNeedle.length()) |
3311 | + return ",posM"; // in the Middle of the needle |
3312 | + if (pos == theBareNeedlePos + theStringNeedle.length()) |
3313 | + return ",posE"; // at the End of the needle |
3314 | + if (pos < theStringHay.length()) |
3315 | + return ",posR"; // to the Right of the needle |
3316 | + return ",posP"; // past the hay |
3317 | +} |
3318 | + |
3319 | +/// formats placement key (part of the case category string) |
3320 | +std::string |
3321 | +SBufFindTest::placementKey() const |
3322 | +{ |
3323 | + // Ignore thePlacement because theBareNeedlePos covers it better: we may |
3324 | + // try to place the needle somewhere, but hay limits the actual placement. |
3325 | + |
3326 | + // the placent does not matter if needle is not in hay |
3327 | + if (theBareNeedlePos == std::string::npos) |
3328 | + return std::string(); |
3329 | + |
3330 | + if (theBareNeedlePos == 0) |
3331 | + return "@B"; // at the beggining of the hay string |
3332 | + if (theBareNeedlePos == theStringHay.length()-theStringNeedle.length()) |
3333 | + return "@E"; // at the end of the hay string |
3334 | + return "@M"; // in the "middle" of the hay string |
3335 | +} |
3336 | + |
3337 | +/// called when a test case fails; counts and possibly reports the failure |
3338 | +void |
3339 | +SBufFindTest::handleFailure(const char *method) { |
3340 | + // line break after "........." printed for previous tests |
3341 | + if (!errorCount) |
3342 | + std::cerr << std::endl; |
3343 | + |
3344 | + ++errorCount; |
3345 | + |
3346 | + if (errorCount > errorLimit) { |
3347 | + std::cerr << "Will stop generating SBuf test cases because the " << |
3348 | + "number of failed ones is over the limit: " << errorCount << |
3349 | + " (after " << caseCount << " test cases)" << std::endl; |
3350 | + CPPUNIT_ASSERT(errorCount <= errorLimit); |
3351 | + /* NOTREACHED */ |
3352 | + } |
3353 | + |
3354 | + // format test case category; category allows us to hush failure reports |
3355 | + // for already seen categories with failed cases (to reduce output noise) |
3356 | + std::string category = "hay" + lengthKey(theStringHay) + |
3357 | + "." + method + '('; |
3358 | + if (theReportQuote == '"') |
3359 | + category += "needle" + lengthKey(theStringNeedle); |
3360 | + else |
3361 | + category += "char"; |
3362 | + category += placementKey(); |
3363 | + category += posKey(); |
3364 | + category += ')'; |
3365 | + |
3366 | + if (hushSimilar) { |
3367 | + if (failedCats.find(category) != failedCats.end()) |
3368 | + return; // do not report another similar test case failure |
3369 | + failedCats.insert(category); |
3370 | + } |
3371 | + |
3372 | + std::string reportPos = theReportPos; |
3373 | + if (!reportPos.empty()) |
3374 | + reportPos = ", " + reportPos; |
3375 | + |
3376 | + std::cerr << "case" << caseCount << ": " << |
3377 | + "SBuf(\"" << theStringHay << "\")." << method << |
3378 | + "(" << theReportQuote << theReportNeedle << theReportQuote << |
3379 | + reportPos << ") returns " << PosToString(theFindSBuf) << |
3380 | + " instead of " << PosToString(theFindString) << |
3381 | + std::endl << |
3382 | + " std::string(\"" << theStringHay << "\")." << method << |
3383 | + "(" << theReportQuote << theReportNeedle << theReportQuote << |
3384 | + reportPos << ") returns " << PosToString(theFindString) << |
3385 | + std::endl << |
3386 | + " category: " << category << std::endl; |
3387 | + |
3388 | + ++reportCount; |
3389 | +} |
3390 | + |
3391 | +/// generates a random string of the specified length |
3392 | +SBuf |
3393 | +SBufFindTest::RandomSBuf(const int length) { |
3394 | + static const char characters[] = |
3395 | + "0123456789" |
3396 | + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
3397 | + "abcdefghijklomnpqrstuvwxyz"; |
3398 | + // sizeof() counts the terminating zero at the end of characters |
3399 | + // TODO: add \0 character (needs reporting adjustments to print it as \0) |
3400 | + static const size_t charCount = sizeof(characters)-1; |
3401 | + |
3402 | + char buf[length]; |
3403 | + for (int i = 0; i < length; ++i) { |
3404 | + const unsigned int pos = random() % charCount; |
3405 | + assert(pos < sizeof(characters)); |
3406 | + assert(characters[pos] > 32); |
3407 | + buf[i] = characters[random() % charCount]; |
3408 | + } |
3409 | + |
3410 | + return SBuf(buf, 0, length); |
3411 | +} |
3412 | + |
3413 | +/// increments len to quickly cover [0, max] range, slowing down in risky areas |
3414 | +/// jumps to max+1 if caseLimit is reached |
3415 | +void |
3416 | +SBufFindTest::nextLen(int &len, const int max) { |
3417 | + assert(len <= max); |
3418 | + |
3419 | + if (caseCount >= caseLimit) |
3420 | + len = max+1; // avoid future test cases |
3421 | + else if (len <= 10) |
3422 | + ++len; // move slowly at the beginning of the [0,max] range |
3423 | + else if (len >= max - 10) |
3424 | + ++len; // move slowly at the end of the [0,max] range |
3425 | + else { |
3426 | + // move fast in the middle of the [0,max] range |
3427 | + len += len/10 + 1; |
3428 | + |
3429 | + // but do not overshoot the interesting area at the end of the range |
3430 | + if (len > max - 10) |
3431 | + len = max - 10; |
3432 | + } |
3433 | +} |
3434 | + |
3435 | +/// Places the needle into the hay using cleanHay as a starting point. |
3436 | +void |
3437 | +SBufFindTest::placeNeedle(const SBuf &cleanHay) { |
3438 | + // For simplicity, we do not overwrite clean hay characters but use them as |
3439 | + // needle suffix and/or prefix. Should not matter since hay length varies? |
3440 | + |
3441 | + // TODO: support two needles per hay (explicitly) |
3442 | + // TODO: better handle cases where clean hay already contains needle |
3443 | + switch (thePlacement) |
3444 | + { |
3445 | + case placeBeginning: |
3446 | + theSBufHay.assign(theSBufNeedle).append(cleanHay); |
3447 | + break; |
3448 | + |
3449 | + case placeMiddle: |
3450 | + { |
3451 | + const SBuf firstHalf = cleanHay.substr(0, cleanHay.length()/2); |
3452 | + const SBuf secondHalf = cleanHay.substr(cleanHay.length()/2); |
3453 | + theSBufHay.assign(firstHalf).append(theSBufNeedle).append(secondHalf); |
3454 | + break; |
3455 | + } |
3456 | + |
3457 | + case placeEnd: |
3458 | + theSBufHay.assign(cleanHay).append(theSBufNeedle); |
3459 | + break; |
3460 | + |
3461 | + case placeNowhere: |
3462 | + theSBufHay.assign(cleanHay); |
3463 | + break; |
3464 | + |
3465 | + case placeEof: |
3466 | + assert(false); // should not happen |
3467 | + break; |
3468 | + } |
3469 | +} |
3470 | |
3471 | === added file 'src/tests/SBufFindTest.h' |
3472 | --- src/tests/SBufFindTest.h 1970-01-01 00:00:00 +0000 |
3473 | +++ src/tests/SBufFindTest.h 2013-07-04 15:56:30 +0000 |
3474 | @@ -0,0 +1,85 @@ |
3475 | +#ifndef SQUID_SRC_TEST_SBUFFINDTEST_H |
3476 | +#define SQUID_SRC_TEST_SBUFFINDTEST_H |
3477 | + |
3478 | +#include "SBuf.h" |
3479 | + |
3480 | +#if HAVE_STRING |
3481 | +#include <string> |
3482 | +#endif |
3483 | +#include <set> |
3484 | + |
3485 | +/// Generates and executes a [configurable] large number of SBuf::*find() |
3486 | +/// test cases using random strings. Reports detected failures. |
3487 | +class SBufFindTest |
3488 | +{ |
3489 | +public: |
3490 | + SBufFindTest(); |
3491 | + |
3492 | + void run(); ///< generates and executes cases using configuration params |
3493 | + |
3494 | + /* test configuration parameters; can be optionally set before run() */ |
3495 | + int caseLimit; ///< approximate caseCount limit |
3496 | + int errorLimit; ///< errorCount limit |
3497 | + unsigned int randomSeed; ///< pseudo-random sequence choice |
3498 | + /// whether to report only one failed test case per "category" |
3499 | + bool hushSimilar; |
3500 | + /// approximate maximum generated hay string length |
3501 | + SBuf::size_type maxHayLength; |
3502 | + |
3503 | + /// Supported algorithms for placing needle in the hay. |
3504 | + typedef enum { placeBeginning, placeMiddle, placeEnd, placeNowhere, |
3505 | + placeEof } Placement; // placeLast marker must terminate |
3506 | +protected: |
3507 | + |
3508 | + static SBuf RandomSBuf(const int length); |
3509 | + void nextLen(int &len, const int max); |
3510 | + void placeNeedle(const SBuf &cleanHay); |
3511 | + |
3512 | + void testAllMethods(); |
3513 | + void testFindDefs(); |
3514 | + void testFind(); |
3515 | + void testRFindDefs(); |
3516 | + void testRFind(); |
3517 | + void testFindCharDefs(); |
3518 | + void testFindChar(); |
3519 | + void testRFindCharDefs(); |
3520 | + void testRFindChar(); |
3521 | + |
3522 | + std::string posKey() const; |
3523 | + std::string placementKey() const; |
3524 | + |
3525 | + bool resultsMatch() const; |
3526 | + void checkResults(const char *method); |
3527 | + void handleFailure(const char *method); |
3528 | + |
3529 | +private: |
3530 | + /* test case parameters */ |
3531 | + SBuf theSBufHay; ///< the string to be searched |
3532 | + SBuf theSBufNeedle; ///< the string to be found |
3533 | + SBuf::size_type thePos; ///< search position limit |
3534 | + Placement thePlacement; ///< where in the hay the needle is placed |
3535 | + std::string::size_type theStringPos; ///< thePos converted to std::string::size_type |
3536 | + std::string theStringHay; ///< theHay converted to std::string |
3537 | + std::string theStringNeedle; ///< theNeedle converted to std::string |
3538 | + |
3539 | + /// needle pos w/o thePos restrictions; used for case categorization |
3540 | + std::string::size_type theBareNeedlePos; |
3541 | + |
3542 | + /* test case results */ |
3543 | + std::string::size_type theFindString; |
3544 | + SBuf::size_type theFindSBuf; |
3545 | + std::string theReportFunc; |
3546 | + std::string theReportNeedle; |
3547 | + std::string theReportPos; |
3548 | + char theReportQuote; |
3549 | + |
3550 | + /* test progress indicators */ |
3551 | + int caseCount; ///< cases executed so far |
3552 | + int errorCount; ///< total number of failed test cases so far |
3553 | + int reportCount; ///< total number of test cases reported so far |
3554 | + std::set<std::string> failedCats; ///< reported failed categories |
3555 | +}; |
3556 | + |
3557 | +typedef SBufFindTest::Placement Placement; |
3558 | + |
3559 | +#endif |
3560 | |
3561 | === added file 'src/tests/testSBuf.cc' |
3562 | --- src/tests/testSBuf.cc 1970-01-01 00:00:00 +0000 |
3563 | +++ src/tests/testSBuf.cc 2013-07-04 15:56:30 +0000 |
3564 | @@ -0,0 +1,603 @@ |
3565 | +#include "squid.h" |
3566 | +#include "Mem.h" |
3567 | +#include "SBuf.h" |
3568 | +#include "SBufList.h" |
3569 | +#include "SBufStream.h" |
3570 | +#include "SBufTokenizer.h" |
3571 | +#include "SBufUtil.h" |
3572 | +#include "SquidString.h" |
3573 | +#include "testSBuf.h" |
3574 | +#include "SBufFindTest.h" |
3575 | + |
3576 | +#include <iostream> |
3577 | +#include <stdexcept> |
3578 | + |
3579 | +CPPUNIT_TEST_SUITE_REGISTRATION( testSBuf ); |
3580 | + |
3581 | +/* let this test link sanely */ |
3582 | +#include "event.h" |
3583 | +#include "MemObject.h" |
3584 | +void |
3585 | +eventAdd(const char *name, EVH * func, void *arg, double when, int, bool cbdata) |
3586 | +{} |
3587 | +int64_t |
3588 | +MemObject::endOffset() const |
3589 | +{ return 0; } |
3590 | +/* end of stubs */ |
3591 | + |
3592 | +// test string |
3593 | +static char fox[]="The quick brown fox jumped over the lazy dog"; |
3594 | +static char fox1[]="The quick brown fox "; |
3595 | +static char fox2[]="jumped over the lazy dog"; |
3596 | + |
3597 | +// TEST: globals variables (default/empty and with contents) are |
3598 | +// created outside and before any unit tests and memory subsystem |
3599 | +// initialization. Check for correct constructor operation. |
3600 | +SBuf empty_sbuf; |
3601 | +SBuf literal("The quick brown fox jumped over the lazy dog"); |
3602 | + |
3603 | +void |
3604 | +testSBuf::testSBufConstructDestruct() |
3605 | +{ |
3606 | + /* NOTE: Do not initialize memory here because we need |
3607 | + * to test correct operation before and after Mem::Init |
3608 | + */ |
3609 | + |
3610 | + // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test |
3611 | + // is working on local-scope variables constructed fresh for the test, and destructed when |
3612 | + // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc) |
3613 | + |
3614 | + // TEST: default constructor (implicit destructor non-crash test) |
3615 | + // test accessors on empty SBuf. |
3616 | + { |
3617 | + SBuf s1; |
3618 | + CPPUNIT_ASSERT_EQUAL(s1.length(),0); |
3619 | + CPPUNIT_ASSERT_EQUAL(s1,SBuf("")); |
3620 | + CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf); |
3621 | + CPPUNIT_ASSERT(0==strcmp("",s1.c_str())); |
3622 | + } |
3623 | + |
3624 | + // TEST: copy-construct NULL string (implicit destructor non-crash test) |
3625 | + { |
3626 | + SBuf s1(NULL); |
3627 | + CPPUNIT_ASSERT_EQUAL(s1.length(),0); |
3628 | + CPPUNIT_ASSERT_EQUAL(s1,SBuf("")); |
3629 | + CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf); |
3630 | + CPPUNIT_ASSERT(0==strcmp("",s1.c_str())); |
3631 | + } |
3632 | + |
3633 | + // TEST: copy-construct empty string (implicit destructor non-crash test) |
3634 | + { |
3635 | + SBuf s1(""); |
3636 | + CPPUNIT_ASSERT_EQUAL(s1.length(),0); |
3637 | + CPPUNIT_ASSERT_EQUAL(s1,SBuf("")); |
3638 | + CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf); |
3639 | + CPPUNIT_ASSERT(0==strcmp("",s1.c_str())); |
3640 | + } |
3641 | + |
3642 | + // TEST: copy-construct from a SBuf |
3643 | + { |
3644 | + SBuf s1(empty_sbuf); |
3645 | + CPPUNIT_ASSERT_EQUAL(s1.length(),0); |
3646 | + CPPUNIT_ASSERT_EQUAL(s1,SBuf("")); |
3647 | + CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf); |
3648 | + CPPUNIT_ASSERT(0==strcmp("",s1.c_str())); |
3649 | + |
3650 | + SBuf s5(literal); |
3651 | + CPPUNIT_ASSERT_EQUAL(s5,literal); |
3652 | + SBuf s6(fox); |
3653 | + CPPUNIT_ASSERT_EQUAL(s6,literal); |
3654 | + // XXX: other state checks. expected result of calling any state accessor on s4 ? |
3655 | + } |
3656 | + |
3657 | + // TEST: check that COW doesn't happen upon copy-construction |
3658 | + { |
3659 | + SBuf s1(empty_sbuf), s2(s1); |
3660 | + CPPUNIT_ASSERT_EQUAL(s1.rawContent(), s2.rawContent()); |
3661 | + SBuf s3(literal), s4(literal); |
3662 | + CPPUNIT_ASSERT_EQUAL(s3.rawContent(), s4.rawContent()); |
3663 | + } |
3664 | + |
3665 | + // TEST: sub-string copy |
3666 | + { |
3667 | + SBuf s1=SBuf(fox,4), s2(fox); |
3668 | + SBuf s3=s2.substr(4,s2.length()); //n is out-of-bounds |
3669 | + CPPUNIT_ASSERT_EQUAL(s1,s3); |
3670 | + SBuf s4=SBuf(fox,0,4); |
3671 | + s3=s2.substr(0,4); |
3672 | + CPPUNIT_ASSERT_EQUAL(s4,s3); |
3673 | + } |
3674 | + |
3675 | + // TEST: go via SquidString adapters. |
3676 | + { |
3677 | + String str(fox); |
3678 | + SBuf s1(str); |
3679 | + CPPUNIT_ASSERT_EQUAL(s1,literal); |
3680 | + } |
3681 | +} |
3682 | + |
3683 | +void |
3684 | +testSBuf::testSBufConstructDestructAfterMemInit() |
3685 | +{ |
3686 | + Mem::Init(); |
3687 | + testSBufConstructDestruct(); |
3688 | + |
3689 | +// XXX: or perhapse ... |
3690 | +// repeat all of the tests inside testSBufConstructDestructBeforeMemInit() |
3691 | +// with additional checks on Mem usage stats after each operation ?? |
3692 | +} |
3693 | + |
3694 | +void |
3695 | +testSBuf::testEqualityTest() |
3696 | +{ |
3697 | + SBuf s1(fox),s2(fox); |
3698 | + CPPUNIT_ASSERT_EQUAL(s1,s1); //self-equality |
3699 | + CPPUNIT_ASSERT_EQUAL(s1,s2); //same contents |
3700 | + s2.assign("The quick brown fox jumped over the lazy doe"); |
3701 | + CPPUNIT_ASSERT(!(s1 == s2)); //same length, different contents |
3702 | + s2.assign("foo"); |
3703 | + CPPUNIT_ASSERT(!(s1 == s2)); //different length and contents |
3704 | + CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality |
3705 | + s2.clear(); |
3706 | + CPPUNIT_ASSERT(!(s1 == s2)); //null and not-null |
3707 | + CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality |
3708 | + s1.clear(); |
3709 | + CPPUNIT_ASSERT_EQUAL(s1,s2); //null and null |
3710 | +} |
3711 | + |
3712 | +void |
3713 | +testSBuf::testAppendSBuf() |
3714 | +{ |
3715 | + SBuf s1(fox1),s2(fox2); |
3716 | + s1.append(s2); |
3717 | + CPPUNIT_ASSERT_EQUAL(s1,literal); |
3718 | +} |
3719 | + |
3720 | +void |
3721 | +testSBuf::testPrintf() |
3722 | +{ |
3723 | + SBuf s1,s2; |
3724 | + s1.Printf("%s:%d:%03.3f","fox",10,12345.67); |
3725 | + s2.assign("fox:10:12345.670"); |
3726 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3727 | +} |
3728 | + |
3729 | +void |
3730 | +testSBuf::testAppendCString() |
3731 | +{ |
3732 | + SBuf s1(fox1); |
3733 | + s1.append(fox2); |
3734 | + CPPUNIT_ASSERT_EQUAL(s1,literal); |
3735 | +} |
3736 | + |
3737 | +void |
3738 | +testSBuf::testAppendStdString() |
3739 | +{ |
3740 | + SBuf s1(fox1); |
3741 | + std::string str(fox2); |
3742 | + s1.append(str); |
3743 | + CPPUNIT_ASSERT_EQUAL(s1,literal); |
3744 | +} |
3745 | + |
3746 | +void |
3747 | +testSBuf::testAppendf() |
3748 | +{ |
3749 | + SBuf s1,s2; |
3750 | + s1.appendf("%s:%d:%03.2f",fox,1234,1234.56); |
3751 | + s2.assign("The quick brown fox jumped over the lazy dog:1234:1234.56"); |
3752 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3753 | +} |
3754 | + |
3755 | +void |
3756 | +testSBuf::testDumpStats() |
3757 | +{ |
3758 | + SBuf::GetStats().dump(std::cout); |
3759 | + MemBlob::GetStats().dump(std::cout); |
3760 | + std::cout << "sizeof(SBuf): " << sizeof(SBuf) << std::endl; |
3761 | + std::cout << "sizeof(MemBlob): " << sizeof(MemBlob) << std::endl; |
3762 | +} |
3763 | + |
3764 | +void |
3765 | +testSBuf::testSubscriptOp() |
3766 | +{ |
3767 | + SBuf chg(literal); |
3768 | + CPPUNIT_ASSERT_EQUAL(chg[5],'u'); |
3769 | + chg.setAt(5,'e'); |
3770 | + CPPUNIT_ASSERT_EQUAL(literal[5],'u'); |
3771 | + CPPUNIT_ASSERT_EQUAL(chg[5],'e'); |
3772 | +// std::cout << chg << std::endl << empty_sbuf << std::endl ; |
3773 | +} |
3774 | + |
3775 | +// note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and |
3776 | +// so the test can't be properly completed. |
3777 | +void |
3778 | +testSBuf::testSubscriptOpFail() |
3779 | +{ |
3780 | + char c; |
3781 | + c=literal.at(1234); //out of bounds |
3782 | + //notreached |
3783 | + std::cout << c << std::endl; |
3784 | +} |
3785 | + |
3786 | +static int sign(int v) |
3787 | +{ |
3788 | + if (v < 0) |
3789 | + return -1; |
3790 | + if (v>0) |
3791 | + return 1; |
3792 | + return 0; |
3793 | +} |
3794 | + |
3795 | +void |
3796 | +testSBuf::testComparisons() |
3797 | +{ |
3798 | + //same length |
3799 | + SBuf s1("foo"),s2("foe"); |
3800 | + CPPUNIT_ASSERT(s1.cmp(s2)>0); |
3801 | + CPPUNIT_ASSERT(s1.casecmp(s2)>0); |
3802 | + CPPUNIT_ASSERT(s2.cmp(s1)<0); |
3803 | + CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2)); |
3804 | + CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2,2)); |
3805 | + CPPUNIT_ASSERT(s1 > s2); |
3806 | + CPPUNIT_ASSERT(s2 < s1); |
3807 | + CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str()))); |
3808 | + //different lengths |
3809 | + s1.assign("foo"); |
3810 | + s2.assign("foof"); |
3811 | + CPPUNIT_ASSERT(s1.cmp(s2)<0); |
3812 | + CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str()))); |
3813 | + CPPUNIT_ASSERT(s1 < s2); |
3814 | + // specifying the max-length and overhanging size |
3815 | + CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").casecmp(SBuf("foo"), 5)); |
3816 | + // case-insensive comaprison |
3817 | + s1 = "foo"; |
3818 | + s2 = "fOo"; |
3819 | + CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2)); |
3820 | + CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2,2)); |
3821 | + // \0-clenliness test |
3822 | + s1.assign("f\0oo",0,4); |
3823 | + s2.assign("f\0Oo",0,4); |
3824 | + CPPUNIT_ASSERT_EQUAL(1,s1.cmp(s2)); |
3825 | + CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2)); |
3826 | + CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2,3)); |
3827 | +} |
3828 | + |
3829 | +void |
3830 | +testSBuf::testConsume() |
3831 | +{ |
3832 | + SBuf s1(literal),s2,s3; |
3833 | + s2=s1.consume(4); |
3834 | + s3.assign("The "); |
3835 | + CPPUNIT_ASSERT_EQUAL(s2,s3); |
3836 | + s3.assign("quick brown fox jumped over the lazy dog"); |
3837 | + CPPUNIT_ASSERT_EQUAL(s1,s3); |
3838 | + s1.consume(40); |
3839 | + CPPUNIT_ASSERT_EQUAL(s1,SBuf()); |
3840 | +} |
3841 | + |
3842 | +void |
3843 | +testSBuf::testRawContent() |
3844 | +{ |
3845 | + SBuf s1(literal); |
3846 | + SBuf s2(s1); |
3847 | + s2.append("foo"); |
3848 | + const char *foo; |
3849 | + foo = s1.rawContent(); |
3850 | + CPPUNIT_ASSERT(strncmp(fox,foo,s1.length())==0); |
3851 | + foo = s1.c_str(); |
3852 | + CPPUNIT_ASSERT(!strcmp(fox,foo)); |
3853 | +} |
3854 | + |
3855 | +void |
3856 | +testSBuf::testRawSpace() |
3857 | +{ |
3858 | + SBuf s1(literal); |
3859 | + SBuf s2(fox1); |
3860 | + char *rb=s2.rawSpace(strlen(fox2)+1); |
3861 | + strcat(rb,fox2); |
3862 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3863 | +} |
3864 | + |
3865 | +void |
3866 | +testSBuf::testChop() |
3867 | +{ |
3868 | + SBuf s1(literal),s2; |
3869 | + s1.chop(4,5); |
3870 | + s2.assign("quick"); |
3871 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3872 | + s1=literal; |
3873 | + s2.clear(); |
3874 | + s1.chop(5,0); |
3875 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3876 | +} |
3877 | + |
3878 | +void |
3879 | +testSBuf::testChomp() |
3880 | +{ |
3881 | + SBuf s1("complete string"); |
3882 | + SBuf s2(s1); |
3883 | + s2.trim(SBuf(" ,")); |
3884 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3885 | + s2.assign(" complete string ,"); |
3886 | + s2.trim(SBuf(" ,")); |
3887 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3888 | + s1.assign(", complete string ,"); |
3889 | + s2=s1; |
3890 | + s2.trim(SBuf(" ")); |
3891 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3892 | +} |
3893 | + |
3894 | +void |
3895 | +testSBuf::testSubstr() |
3896 | +{ |
3897 | + SBuf s1(literal),s2,s3; |
3898 | + s2=s1.substr(4,5); |
3899 | + s3.assign("quick"); |
3900 | + CPPUNIT_ASSERT_EQUAL(s2,s3); |
3901 | + s1.chop(4,5); |
3902 | + CPPUNIT_ASSERT_EQUAL(s1,s2); |
3903 | +} |
3904 | + |
3905 | +void |
3906 | +testSBuf::testFindChar() |
3907 | +{ |
3908 | + const char *alphabet="abcdefghijklmnopqrstuvwxyz"; |
3909 | + SBuf s1(alphabet); |
3910 | + SBuf::size_type idx; |
3911 | + idx=s1.find('d'); |
3912 | + CPPUNIT_ASSERT(idx == 3); |
3913 | + CPPUNIT_ASSERT(s1[idx]=='d'); |
3914 | + idx=s1.find(' '); //fails |
3915 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3916 | + idx=s1.find('e',5); |
3917 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3918 | + idx=s1.rfind('x',s1.length()-4); |
3919 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3920 | +} |
3921 | + |
3922 | +void |
3923 | +testSBuf::testFindSBuf() |
3924 | +{ |
3925 | + SBuf haystack(literal),afox("fox"),foobar("foobar"),foe("foe"), dog("dog"); |
3926 | + SBuf toolong(literal), g; |
3927 | + //very long string matching at the end |
3928 | + toolong.append(literal).append(literal).append(literal).append(literal); |
3929 | + SBuf::size_type idx; |
3930 | + idx=haystack.find(afox); |
3931 | + CPPUNIT_ASSERT_EQUAL(16,idx); |
3932 | + idx=haystack.find(foobar); //fails |
3933 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3934 | + idx=haystack.find(foe); //fails |
3935 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3936 | + idx=haystack.find(foe); |
3937 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3938 | + idx=haystack.find(dog); |
3939 | + CPPUNIT_ASSERT_EQUAL(haystack.length()-dog.length(),idx); |
3940 | + dog.append("foo"); |
3941 | + idx=haystack.find(dog); |
3942 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3943 | + idx=haystack.find(toolong); |
3944 | + CPPUNIT_ASSERT(SBuf::npos==idx); //consistent with std::string |
3945 | + g="g"; //match at the last char |
3946 | + idx=haystack.find(g); |
3947 | + CPPUNIT_ASSERT_EQUAL(43,idx); |
3948 | + CPPUNIT_ASSERT_EQUAL('g',haystack[idx]); |
3949 | +} |
3950 | + |
3951 | +void |
3952 | +testSBuf::testRFindChar() |
3953 | +{ |
3954 | + SBuf s1(literal); |
3955 | + SBuf::size_type idx; |
3956 | + idx=s1.rfind(' '); |
3957 | + CPPUNIT_ASSERT_EQUAL(40,idx); |
3958 | + CPPUNIT_ASSERT_EQUAL(' ',s1[idx]); |
3959 | +} |
3960 | + |
3961 | +void |
3962 | +testSBuf::testRFindSBuf() |
3963 | +{ |
3964 | + SBuf haystack(literal),afox("fox"); |
3965 | + SBuf goobar("goobar"); |
3966 | + SBuf::size_type idx; |
3967 | + |
3968 | + // corner case: search for a zero-length SBuf |
3969 | + idx=haystack.rfind(SBuf("")); |
3970 | + CPPUNIT_ASSERT_EQUAL(haystack.length(),idx); |
3971 | + |
3972 | + // corner case: search for a needle longer than the haystack |
3973 | + idx=afox.rfind(SBuf(" ")); |
3974 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3975 | + |
3976 | + idx=haystack.rfind(SBuf("fox")); |
3977 | + CPPUNIT_ASSERT_EQUAL(16,idx); |
3978 | + |
3979 | + // needle not found, no match for first char |
3980 | + idx=goobar.rfind(SBuf("foo")); |
3981 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3982 | + |
3983 | + // needle not found, match for first char but no match for SBuf |
3984 | + idx=haystack.rfind(SBuf("foe")); |
3985 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
3986 | + |
3987 | + SBuf g("g"); //match at the last char |
3988 | + idx=haystack.rfind(g); |
3989 | + CPPUNIT_ASSERT_EQUAL(43,idx); |
3990 | + CPPUNIT_ASSERT_EQUAL('g',haystack[idx]); |
3991 | + |
3992 | + idx=haystack.rfind(SBuf("The")); |
3993 | + CPPUNIT_ASSERT_EQUAL(0,idx); |
3994 | + |
3995 | + haystack.append("The"); |
3996 | + idx=haystack.rfind(SBuf("The")); |
3997 | + CPPUNIT_ASSERT_EQUAL(44,idx); |
3998 | + |
3999 | + //partial match |
4000 | + haystack="The quick brown fox"; |
4001 | + SBuf needle("foxy lady"); |
4002 | + idx=haystack.rfind(needle); |
4003 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
4004 | +} |
4005 | + |
4006 | +void |
4007 | +testSBuf::testSBufLength() |
4008 | +{ |
4009 | + SBuf s(fox); |
4010 | + CPPUNIT_ASSERT((size_t)s.length()==strlen(fox)); |
4011 | +} |
4012 | + |
4013 | +void |
4014 | +testSBuf::testScanf() |
4015 | +{ |
4016 | + SBuf s1; |
4017 | + char s[128]; |
4018 | + int i; |
4019 | + float f; |
4020 | + int rv; |
4021 | + s1.assign("string , 123 , 123.50"); |
4022 | + rv=s1.scanf("%s , %d , %f",s,&i,&f); |
4023 | + CPPUNIT_ASSERT(3 == rv); |
4024 | + CPPUNIT_ASSERT(0 == strcmp(s,"string")); |
4025 | + CPPUNIT_ASSERT(i == 123); |
4026 | + CPPUNIT_ASSERT(f == 123.5); |
4027 | +} |
4028 | + |
4029 | +void testSBuf::testCopy() |
4030 | +{ |
4031 | + char buf[40]; //shorter than literal() |
4032 | + SBuf s(fox1),s2; |
4033 | + CPPUNIT_ASSERT(s.copy(buf,40)==s.length()); |
4034 | + CPPUNIT_ASSERT(strncmp(s.rawContent(),buf,s.length())==0); |
4035 | + s=literal; |
4036 | + CPPUNIT_ASSERT(s.copy(buf,40)==40); |
4037 | + s2.assign(buf,0,40); |
4038 | + s.chop(0,40); |
4039 | + CPPUNIT_ASSERT(s==s2); |
4040 | +} |
4041 | + |
4042 | +// XXX: please split each class into a separate unit-test .cc / even if they share a binary. |
4043 | +// rule-of-thumb guideline for layering is 'one class Foo -> one Foo.cc, one Foo.cc -> one testFoo.cc' |
4044 | + |
4045 | +static int sbuf_tokens_number=9; |
4046 | +static SBuf tokens[]={ |
4047 | + SBuf("The",0,3), SBuf("quick",0,5), SBuf("brown",0,5), SBuf("fox",0,3), |
4048 | + SBuf("jumped",0,6), SBuf("over",0,4), SBuf("the",0,3), SBuf("lazy",0,4), |
4049 | + SBuf("dog",0,3) |
4050 | +}; |
4051 | + |
4052 | +void testSBuf::testSBufTokenizer() |
4053 | +{ |
4054 | + int j=0; |
4055 | + SBuf s; |
4056 | + for (SBufTokenizer st(literal,SBuf(" ",0,1)); !st.atEnd(); st.next()) { |
4057 | + s=st.token(); |
4058 | + CPPUNIT_ASSERT(s==tokens[j]); |
4059 | + j++; |
4060 | + } |
4061 | + CPPUNIT_ASSERT(j==9); |
4062 | +} |
4063 | + |
4064 | +void testSBuf::testStringOps() |
4065 | +{ |
4066 | + SBuf sng(literal), |
4067 | + ref("the quick brown fox jumped over the lazy dog"); |
4068 | + sng=sng.toLower(); |
4069 | + CPPUNIT_ASSERT_EQUAL(ref,sng); |
4070 | + sng=literal; |
4071 | + CPPUNIT_ASSERT_EQUAL(0,sng.compare(ref,caseInsensitive)); |
4072 | +} |
4073 | + |
4074 | +void testSBuf::testGrow() |
4075 | +{ |
4076 | + SBuf t; |
4077 | + t.assign("foo"); |
4078 | + const char *ref=t.rawContent(); |
4079 | + t.reserveCapacity(10240); |
4080 | + const char *match=t.rawContent(); |
4081 | + CPPUNIT_ASSERT(match!=ref); |
4082 | + ref=match; |
4083 | + t.append(literal).append(literal).append(literal).append(literal).append(literal); |
4084 | + t.append(t).append(t).append(t).append(t).append(t); |
4085 | + CPPUNIT_ASSERT(match==ref); |
4086 | +} |
4087 | + |
4088 | +void testSBuf::testStartsWith() |
4089 | +{ |
4090 | + static SBuf casebuf("THE QUICK"); |
4091 | + CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1))); |
4092 | + CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1))); //too short |
4093 | + CPPUNIT_ASSERT(!literal.startsWith(SBuf(fox2))); //different contents |
4094 | + |
4095 | + // case-insensitive checks |
4096 | + CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive)); |
4097 | + casebuf=SBuf(fox1).toUpper(); |
4098 | + CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive)); |
4099 | + CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1),caseInsensitive)); |
4100 | + casebuf = "tha quick"; |
4101 | + CPPUNIT_ASSERT_EQUAL(false,literal.startsWith(casebuf,caseInsensitive)); |
4102 | +} |
4103 | + |
4104 | +void testSBuf::testSBufList() |
4105 | +{ |
4106 | + SBufList foo; |
4107 | + for (int j=0; j<sbuf_tokens_number; ++j) |
4108 | + foo.add(tokens[j]); |
4109 | + CPPUNIT_ASSERT(foo.isMember(SBuf("fox"))); |
4110 | + CPPUNIT_ASSERT(foo.isMember(SBuf("Fox"),caseInsensitive)); |
4111 | + CPPUNIT_ASSERT(!foo.isMember(SBuf("garble"))); |
4112 | + CPPUNIT_ASSERT(foo.isPrefix(SBuf("qui"))); |
4113 | + CPPUNIT_ASSERT(foo.isPrefix(SBuf("qUi"),caseInsensitive)); |
4114 | + CPPUNIT_ASSERT(!foo.isPrefix(SBuf("qUa"),caseInsensitive)); |
4115 | +} |
4116 | + |
4117 | +void testSBuf::testBaseName() |
4118 | +{ |
4119 | + SBuf totest("/foo/bar/gazonk"); |
4120 | + CPPUNIT_ASSERT_EQUAL(BaseName(totest),SBuf("gazonk")); |
4121 | + CPPUNIT_ASSERT_EQUAL(BaseName(totest,'.'),totest); |
4122 | +} |
4123 | + |
4124 | +void testSBuf::testSBufStream() |
4125 | +{ |
4126 | + SBuf b("const.string, int 10 and a float 10.5"); |
4127 | + SBufStream ss; |
4128 | + ss << "const.string, int " << 10 << " and a float " << 10.5; |
4129 | + SBuf o=ss.buf(); |
4130 | + CPPUNIT_ASSERT_EQUAL(b,o); |
4131 | + ss.clearBuf(); |
4132 | + o=ss.buf(); |
4133 | + CPPUNIT_ASSERT_EQUAL(SBuf(),o); |
4134 | + SBuf f1(fox1); |
4135 | + SBufStream ss2(f1); |
4136 | + ss2 << fox2; |
4137 | + CPPUNIT_ASSERT_EQUAL(ss2.buf(),literal); |
4138 | + CPPUNIT_ASSERT_EQUAL(f1,SBuf(fox1)); |
4139 | +} |
4140 | + |
4141 | +void testSBuf::testFindFirstOf() |
4142 | +{ |
4143 | + SBuf haystack(literal); |
4144 | + SBuf::size_type idx; |
4145 | + |
4146 | + // not found |
4147 | + idx=haystack.find_first_of(SBuf("ADHRWYP")); |
4148 | + CPPUNIT_ASSERT(idx==SBuf::npos); |
4149 | + |
4150 | + // found at beginning |
4151 | + idx=haystack.find_first_of(SBuf("THANDF")); |
4152 | + CPPUNIT_ASSERT_EQUAL(0,idx); |
4153 | + |
4154 | + //found at end of haystack |
4155 | + idx=haystack.find_first_of(SBuf("QWERYVg")); |
4156 | + CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx); |
4157 | + |
4158 | + //found in the middle of haystack |
4159 | + idx=haystack.find_first_of(SBuf("QWERqYV")); |
4160 | + CPPUNIT_ASSERT_EQUAL(4,idx); |
4161 | +} |
4162 | + |
4163 | +void testSBuf::testAutoFind() |
4164 | +{ |
4165 | + SBufFindTest test; |
4166 | + test.run(); |
4167 | +} |
4168 | |
4169 | === added file 'src/tests/testSBuf.h' |
4170 | --- src/tests/testSBuf.h 1970-01-01 00:00:00 +0000 |
4171 | +++ src/tests/testSBuf.h 2013-07-04 15:56:30 +0000 |
4172 | @@ -0,0 +1,92 @@ |
4173 | +#ifndef SQUID_SRC_TEST_TESTSBUF_H |
4174 | +#define SQUID_SRC_TEST_TESTSBUF_H |
4175 | + |
4176 | +#include <cppunit/extensions/HelperMacros.h> |
4177 | + |
4178 | +#include "OutOfBoundsException.h" |
4179 | + |
4180 | +/* |
4181 | + * test the SBuf functionalities |
4182 | + */ |
4183 | + |
4184 | +class testSBuf : public CPPUNIT_NS::TestFixture |
4185 | +{ |
4186 | + CPPUNIT_TEST_SUITE( testSBuf ); |
4187 | + CPPUNIT_TEST( testSBufConstructDestruct ); |
4188 | + CPPUNIT_TEST( testSBufConstructDestructAfterMemInit ); |
4189 | + CPPUNIT_TEST( testSBufLength ); |
4190 | + CPPUNIT_TEST( testEqualityTest ); |
4191 | + CPPUNIT_TEST( testStartsWith ); |
4192 | + CPPUNIT_TEST( testAppendSBuf ); |
4193 | + CPPUNIT_TEST( testAppendCString ); |
4194 | + CPPUNIT_TEST( testAppendStdString ); |
4195 | + CPPUNIT_TEST( testAppendf ); |
4196 | + CPPUNIT_TEST( testSubscriptOp ); |
4197 | + CPPUNIT_TEST_EXCEPTION( testSubscriptOpFail , OutOfBoundsException ); |
4198 | + CPPUNIT_TEST( testComparisons ); |
4199 | + CPPUNIT_TEST( testConsume ); |
4200 | + CPPUNIT_TEST( testRawContent ); |
4201 | + //CPPUNIT_TEST( testRawSpace ); |
4202 | + CPPUNIT_TEST( testChop ); |
4203 | + CPPUNIT_TEST( testChomp ); |
4204 | + CPPUNIT_TEST( testSubstr ); |
4205 | + CPPUNIT_TEST( testFindChar ); |
4206 | + CPPUNIT_TEST( testFindSBuf ); |
4207 | + CPPUNIT_TEST( testRFindChar ); |
4208 | + CPPUNIT_TEST( testRFindSBuf ); |
4209 | + CPPUNIT_TEST( testFindFirstOf ); |
4210 | + CPPUNIT_TEST( testPrintf ); |
4211 | + CPPUNIT_TEST( testScanf ); |
4212 | + CPPUNIT_TEST( testCopy ); |
4213 | + CPPUNIT_TEST( testSBufTokenizer ); |
4214 | + CPPUNIT_TEST( testStringOps ); |
4215 | + CPPUNIT_TEST( testGrow ); |
4216 | + CPPUNIT_TEST( testSBufList ); |
4217 | + CPPUNIT_TEST( testBaseName ); |
4218 | + CPPUNIT_TEST( testSBufStream ); |
4219 | + CPPUNIT_TEST( testAutoFind ); |
4220 | + |
4221 | +// CPPUNIT_TEST( testDumpStats ); //fake test, to print alloc stats |
4222 | + |
4223 | + CPPUNIT_TEST_SUITE_END(); |
4224 | +protected: |
4225 | + void commonInit(); |
4226 | + void testSBufConstructDestruct(); |
4227 | + void testSBufConstructDestructAfterMemInit(); |
4228 | + void testEqualityTest(); |
4229 | + void testAppendSBuf(); |
4230 | + void testAppendCString(); |
4231 | + void testAppendStdString(); |
4232 | + void testAppendf(); |
4233 | + void testPrintf(); |
4234 | + void testScanf(); |
4235 | + void testSubscriptOp(); |
4236 | + void testSubscriptOpFail(); |
4237 | + void testDumpStats(); |
4238 | + void testComparisons(); |
4239 | + void testConsume(); |
4240 | + void testRawContent(); |
4241 | + void testRawSpace(); |
4242 | + void testChop(); |
4243 | + void testChomp(); |
4244 | + void testSubstr(); |
4245 | + void testTailCopy(); |
4246 | + void testSBufLength(); |
4247 | + void testFindChar(); |
4248 | + void testFindSBuf(); |
4249 | + void testRFindChar(); |
4250 | + void testRFindSBuf(); |
4251 | + void testSearchFail(); |
4252 | + void testCopy(); |
4253 | + void testSBufTokenizer(); |
4254 | + void testStringOps(); |
4255 | + void testGrow(); |
4256 | + void testStartsWith(); |
4257 | + void testSBufList(); |
4258 | + void testBaseName(); |
4259 | + void testSBufStream(); |
4260 | + void testFindFirstOf(); |
4261 | + void testAutoFind(); |
4262 | +}; |
4263 | + |
4264 | +#endif |