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