Merge lp:~kinkie/squid/stringng into lp:squid/v4

Proposed by Francesco Chemolli
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
Reviewer Review Type Date Requested Status
Alex Rousskov Pending
Review via email: mp+70503@code.launchpad.net

Description of the change

String-Buffer class, sporting
- refcounted backing store
- efficient substring operations
- mempools and cachemgr integration
- tokenizer
- ostream interface

To post a comment you must log in.
lp:~kinkie/squid/stringng updated
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 OutOfBoundsException

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::StorePrototype 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 OutOfBoundsException

9609. By Francesco Chemolli

Simplified OutOfBoundsException'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 commonCompareChecksPost()
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 commonCompareChecksPost()
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/util.h'
--- include/util.h 2012-10-09 09:23:00 +0000
+++ include/util.h 2013-07-04 15:56:30 +0000
@@ -102,7 +102,7 @@
102extern const char *gb_to_str(const gb_t *);102extern const char *gb_to_str(const gb_t *);
103extern void gb_flush(gb_t *); /* internal, do not use this */103extern void gb_flush(gb_t *); /* internal, do not use this */
104104
105/*105/**
106 * Returns the amount of known allocated memory106 * Returns the amount of known allocated memory
107 */107 */
108int statMemoryAccounted(void);108int statMemoryAccounted(void);
109109
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2013-06-20 09:56:11 +0000
+++ src/Makefile.am 2013-07-04 15:56:30 +0000
@@ -24,7 +24,18 @@
24SBUF_SOURCE= \24SBUF_SOURCE= \
25 base/InstanceId.h \25 base/InstanceId.h \
26 MemBlob.h \26 MemBlob.h \
27 MemBlob.cc27 MemBlob.cc \
28 OutOfBoundsException.h \
29 SBuf.h \
30 SBuf.cc \
31 SBufExceptions.h \
32 SBufExceptions.cc \
33 SBufTokenizer.h \
34 SBufTokenizer.cc \
35 SBufList.h \
36 SBufList.cc \
37 SBufUtil.h \
38 SBufUtil.cc
2839
29LOADABLE_MODULES_SOURCES = \40LOADABLE_MODULES_SOURCES = \
30 LoadableModule.h \41 LoadableModule.h \
@@ -142,7 +153,7 @@
142UNLINKDSOURCE = unlinkd.h unlinkd.cc153UNLINKDSOURCE = unlinkd.h unlinkd.cc
143UNLINKD = unlinkd154UNLINKD = unlinkd
144else155else
145UNLINKDSOURCE = unlinkd.h156UNLINKDSOURCE =
146UNLINKD = 157UNLINKD =
147endif158endif
148159
@@ -290,7 +301,6 @@
290 client_db.cc \301 client_db.cc \
291 client_side.h \302 client_side.h \
292 client_side.cc \303 client_side.cc \
293 client_side.h \
294 client_side_reply.cc \304 client_side_reply.cc \
295 client_side_reply.h \305 client_side_reply.h \
296 client_side_request.cc \306 client_side_request.cc \
@@ -298,7 +308,6 @@
298 ClientInfo.h \308 ClientInfo.h \
299 BodyPipe.cc \309 BodyPipe.cc \
300 BodyPipe.h \310 BodyPipe.h \
301 ClientInfo.h \
302 ClientRequestContext.h \311 ClientRequestContext.h \
303 clientStream.cc \312 clientStream.cc \
304 clientStream.h \313 clientStream.h \
@@ -390,6 +399,7 @@
390 HttpHeaderFieldInfo.h \399 HttpHeaderFieldInfo.h \
391 HttpHeaderTools.h \400 HttpHeaderTools.h \
392 HttpHeaderTools.cc \401 HttpHeaderTools.cc \
402 StrList.h \
393 HttpBody.h \403 HttpBody.h \
394 HttpBody.cc \404 HttpBody.cc \
395 HttpControlMsg.h \405 HttpControlMsg.h \
@@ -428,7 +438,6 @@
428 mem.cc \438 mem.cc \
429 mem_node.cc \439 mem_node.cc \
430 mem_node.h \440 mem_node.h \
431 Mem.h \
432 MemBuf.cc \441 MemBuf.cc \
433 MemObject.cc \442 MemObject.cc \
434 MemObject.h \443 MemObject.h \
@@ -470,6 +479,8 @@
470 send-announce.h \479 send-announce.h \
471 send-announce.cc \480 send-announce.cc \
472 $(SBUF_SOURCE) \481 $(SBUF_SOURCE) \
482 SBufExtras.h \
483 SBufExtras.cc \
473 $(SNMP_SOURCE) \484 $(SNMP_SOURCE) \
474 SquidMath.h \485 SquidMath.h \
475 SquidMath.cc \486 SquidMath.cc \
@@ -482,7 +493,6 @@
482 StatHist.h \493 StatHist.h \
483 StatHist.cc \494 StatHist.cc \
484 String.cc \495 String.cc \
485 StrList.h \
486 StrList.cc \496 StrList.cc \
487 stmem.cc \497 stmem.cc \
488 stmem.h \498 stmem.h \
@@ -592,7 +602,8 @@
592 StoreEntryStream.h \602 StoreEntryStream.h \
593 String.cci \603 String.cci \
594 SquidString.h \604 SquidString.h \
595 SquidTime.h605 SquidTime.h \
606 SBuf.cci
596607
597BUILT_SOURCES = \608BUILT_SOURCES = \
598 cf_gen_defines.cci \609 cf_gen_defines.cci \
@@ -1076,7 +1087,7 @@
1076TESTSOURCES= \1087TESTSOURCES= \
1077 tests/STUB.h \1088 tests/STUB.h \
1078 test_tools.cc \1089 test_tools.cc \
1079 globals.cc1090 globals.cc
10801091
1081check_PROGRAMS+=\1092check_PROGRAMS+=\
1082 tests/testBoilerplate \1093 tests/testBoilerplate \
@@ -1091,6 +1102,7 @@
1091 tests/testStore \1102 tests/testStore \
1092 tests/testString \1103 tests/testString \
1093 tests/testURL \1104 tests/testURL \
1105 tests/testSBuf \
1094 tests/testConfigParser \1106 tests/testConfigParser \
1095 tests/testStatHist \1107 tests/testStatHist \
1096 tests/testVector \1108 tests/testVector \
@@ -1241,6 +1253,7 @@
1241 HttpHeaderFieldInfo.h \1253 HttpHeaderFieldInfo.h \
1242 HttpHeaderTools.h \1254 HttpHeaderTools.h \
1243 HttpHeaderTools.cc \1255 HttpHeaderTools.cc \
1256 StrList.h \
1244 HttpHdrContRange.cc \1257 HttpHdrContRange.cc \
1245 HttpHdrRange.cc \1258 HttpHdrRange.cc \
1246 HttpHeaderFieldStat.h \1259 HttpHeaderFieldStat.h \
@@ -1264,7 +1277,6 @@
1264 StatCounters.cc \1277 StatCounters.cc \
1265 StatCounters.h \1278 StatCounters.h \
1266 StatHist.h \1279 StatHist.h \
1267 StrList.h \
1268 StrList.cc \1280 StrList.cc \
1269 tests/stub_StatHist.cc \1281 tests/stub_StatHist.cc \
1270 stmem.cc \1282 stmem.cc \
@@ -1472,6 +1484,7 @@
1472 HttpHeaderFieldInfo.h \1484 HttpHeaderFieldInfo.h \
1473 HttpHeaderTools.h \1485 HttpHeaderTools.h \
1474 HttpHeaderTools.cc \1486 HttpHeaderTools.cc \
1487 StrList.h \
1475 HttpHeaderFieldStat.h \1488 HttpHeaderFieldStat.h \
1476 HttpHdrCc.h \1489 HttpHdrCc.h \
1477 HttpHdrCc.cc \1490 HttpHdrCc.cc \
@@ -1534,7 +1547,6 @@
1534 StatCounters.h \1547 StatCounters.h \
1535 StatCounters.cc \1548 StatCounters.cc \
1536 StatHist.h \1549 StatHist.h \
1537 StrList.h \
1538 StrList.cc \1550 StrList.cc \
1539 tests/stub_StatHist.cc \1551 tests/stub_StatHist.cc \
1540 stmem.cc \1552 stmem.cc \
@@ -2207,7 +2219,6 @@
2207 StatCounters.cc \2219 StatCounters.cc \
2208 StatHist.h \2220 StatHist.h \
2209 StatHist.cc \2221 StatHist.cc \
2210 Mem.h \
2211 stmem.cc \2222 stmem.cc \
2212 repl_modules.h \2223 repl_modules.h \
2213 store.cc \2224 store.cc \
@@ -3825,6 +3836,42 @@
3825 $(REPL_OBJS) \3836 $(REPL_OBJS) \
3826 $(SQUID_CPPUNIT_LA)3837 $(SQUID_CPPUNIT_LA)
38273838
3839tests_testSBuf_SOURCES= \
3840 tests/testSBuf.h \
3841 tests/testSBuf.cc \
3842 tests/testMain.cc \
3843 tests/SBufFindTest.h \
3844 tests/SBufFindTest.cc \
3845 $(SBUF_SOURCE) \
3846 SBufStream.h \
3847 time.cc \
3848 mem.cc \
3849 tests/stub_debug.cc \
3850 tests/stub_fatal.cc \
3851 tests/stub_HelperChildConfig.cc \
3852 tests/stub_cache_cf.cc \
3853 tests/stub_cache_manager.cc \
3854 tests/stub_store.cc \
3855 tests/stub_store_stats.cc \
3856 tests/stub_tools.cc \
3857 SquidString.h \
3858 String.cc \
3859 wordlist.cc \
3860 MemBuf.cc
3861nodist_tests_testSBuf_SOURCES=$(TESTSOURCES)
3862tests_testSBuf_LDFLAGS = $(LIBADD_DL)
3863tests_testSBuf_LDADD=\
3864 $(SQUID_CPPUNIT_LIBS) \
3865 $(SQUID_CPPUNIT_LA) \
3866 $(COMPAT_LIB) \
3867 libsquid.la \
3868 ip/libip.la \
3869 mgr/libmgr.la \
3870 base/libbase.la \
3871 $(top_builddir)/lib/libmiscutil.la \
3872 $(COMMON_LIBS)
3873tests_testSBuf_DEPENDENCIES= $(SQUID_CPPUNIT_LA)
3874
3828tests_testConfigParser_SOURCES = \3875tests_testConfigParser_SOURCES = \
3829 ClientInfo.h \3876 ClientInfo.h \
3830 Mem.h \3877 Mem.h \
38313878
=== modified file 'src/MemBlob.cc'
--- src/MemBlob.cc 2012-11-15 22:12:03 +0000
+++ src/MemBlob.cc 2013-07-04 15:56:30 +0000
@@ -46,6 +46,17 @@
46MemBlobStats::MemBlobStats(): alloc(0), live(0), append(0), liveBytes(0)46MemBlobStats::MemBlobStats(): alloc(0), live(0), append(0), liveBytes(0)
47{}47{}
4848
49MemBlobStats&
50MemBlobStats::operator += (const MemBlobStats& s)
51{
52 alloc+=s.alloc;
53 live+=s.live;
54 append+=s.append;
55 liveBytes+=s.liveBytes;
56
57 return *this;
58}
59
49std::ostream&60std::ostream&
50MemBlobStats::dump(std::ostream &os) const61MemBlobStats::dump(std::ostream &os) const
51{62{
5263
=== modified file 'src/MemBlob.h'
--- src/MemBlob.h 2012-10-29 04:59:58 +0000
+++ src/MemBlob.h 2013-07-04 15:56:30 +0000
@@ -46,6 +46,8 @@
46 /// dumps class-wide statistics46 /// dumps class-wide statistics
47 std::ostream& dump(std::ostream& os) const;47 std::ostream& dump(std::ostream& os) const;
4848
49 MemBlobStats& operator += (const MemBlobStats&);
50
49public:51public:
50 uint64_t alloc; ///< number of MemBlob instances created so far52 uint64_t alloc; ///< number of MemBlob instances created so far
51 uint64_t live; ///< number of MemBlob instances currently alive53 uint64_t live; ///< number of MemBlob instances currently alive
5254
=== added file 'src/OutOfBoundsException.h'
--- src/OutOfBoundsException.h 1970-01-01 00:00:00 +0000
+++ src/OutOfBoundsException.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,22 @@
1#ifndef _SQUID_SRC_OUTOFBOUNDSEXCEPTION_H
2#define _SQUID_SRC_OUTOFBOUNDSEXCEPTION_H
3
4#include "base/TextException.h"
5#include "SBuf.h"
6
7/**
8 * Exception raised when the user is going out of bounds when accessing
9 * a char within the SBuf
10 */
11class OutOfBoundsException : public TextException
12{
13public:
14 OutOfBoundsException(const SBuf &buf, SBuf::size_type &pos, const char *aFileName = 0, int aLineNo = -1);
15 virtual ~OutOfBoundsException() throw();
16
17protected:
18 SBuf _buf;
19 SBuf::size_type _pos;
20};
21
22#endif /* _SQUID_SRC_OUTOFBOUNDSEXCEPTION_H */
023
=== added file 'src/SBuf.cc'
--- src/SBuf.cc 1970-01-01 00:00:00 +0000
+++ src/SBuf.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,887 @@
1/*
2 * SBuf.cc (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#include "squid.h"
32#include "base/RefCount.h"
33#include "Debug.h"
34#include "OutOfBoundsException.h"
35#include "SBuf.h"
36#include "SBufExceptions.h"
37#include "util.h"
38
39#if HAVE_STRING_H
40#include <string.h>
41#endif
42
43#if HAVE_SSTREAM
44#include <sstream>
45#endif
46
47#if HAVE_IOSTREAM
48#include <iostream>
49#endif
50
51#ifdef VA_COPY
52#undef VA_COPY
53#endif
54#if defined HAVE_VA_COPY
55#define VA_COPY va_copy
56#elif defined HAVE___VA_COPY
57#define VA_COPY __va_copy
58#endif
59
60InstanceIdDefinitions(SBuf, "SBuf");
61
62SBufStats SBuf::stats;
63const SBuf::size_type SBuf::npos;
64const SBuf::size_type SBuf::maxSize;
65
66
67SBufStats::SBufStats()
68 : alloc(0), allocCopy(0), allocFromString(0), allocFromCString(0),
69 assignFast(0), clear(0), append(0), toStream(0), setChar(0),
70 getChar(0), compareSlow(0), compareFast(0), copyOut(0),
71 rawAccess(0), chop(0), trim(0), find(0), scanf(0),
72 caseChange(0), cowFast(0), cowSlow(0), live(0)
73{}
74
75SBufStats&
76SBufStats::operator +=(const SBufStats& ss)
77{
78 alloc += ss.alloc;
79 allocCopy += ss.allocCopy;
80 allocFromString += ss.allocFromString;
81 allocFromCString += ss.allocFromCString;
82 assignFast += ss.assignFast;
83 clear += ss.clear;
84 append += ss.append;
85 toStream += ss.toStream;
86 setChar += ss.setChar;
87 getChar += ss.getChar;
88 compareSlow += ss.compareSlow;
89 compareFast += ss.compareFast;
90 copyOut += ss.copyOut;
91 rawAccess += ss.rawAccess;
92 chop += ss.chop;
93 trim += ss.trim;
94 find += ss.find;
95 scanf += ss.scanf;
96 caseChange += ss.caseChange;
97 cowFast += ss.cowFast;
98 cowSlow += ss.cowSlow;
99 live += ss.live;
100
101 return *this;
102}
103
104SBuf::SBuf()
105 : store_(GetStorePrototype()), off_(0), len_(0)
106{
107 debugs(24, 8, id << " created");
108 ++stats.alloc;
109 ++stats.live;
110}
111
112SBuf::SBuf(const SBuf &S)
113 : store_(S.store_), off_(S.off_), len_(S.len_)
114{
115 debugs(24, 8, id << " created from id " << S.id);
116 ++stats.alloc;
117 ++stats.allocCopy;
118 ++stats.live;
119}
120
121SBuf::SBuf(const String &S)
122 : store_(GetStorePrototype()), off_(0), len_(0)
123{
124 debugs(24, 8, id << " created from string");
125 assign(S.rawBuf(), 0, S.size());
126 ++stats.alloc;
127 ++stats.allocFromString;
128 ++stats.live;
129}
130
131SBuf::SBuf(const char *S, size_type pos, size_type n)
132 : store_(GetStorePrototype()), off_(0), len_(0)
133{
134 append(S,pos,n); //bounds checked in append()
135 ++stats.alloc;
136 ++stats.allocFromCString;
137 ++stats.live;
138}
139
140SBuf::~SBuf()
141{
142 debugs(24, 8, id << " destructed");
143 --stats.live;
144}
145
146SBuf&
147SBuf::assign(const SBuf &S)
148{
149 debugs(24, 7, "assigning " << id << " from " << S.id);
150 if (&S == this) //assignment to self. Noop.
151 return *this;
152 ++stats.assignFast;
153 store_ = S.store_;
154 off_ = S.off_;
155 len_ = S.len_;
156 return *this;
157}
158
159SBuf&
160SBuf::assign(const char *S, size_type pos, size_type n)
161{
162 debugs(24, 6, id << " from c-string, pos=" << pos << "n=" << n << ")");
163 clear();
164 return append(S, pos, n); //bounds checked in append()
165}
166
167void
168SBuf::reserveCapacity(size_type minCapacity)
169{
170 Must(0 <= minCapacity && minCapacity <= maxSize);
171 reserveSpace(minCapacity-length());
172}
173
174void
175SBuf::reserveSpace(size_type minSpace)
176{
177 Must(0 <= minSpace && minSpace <= maxSize);
178 debugs(24, 7, "reserving " << minSpace << " for " << id);
179 // we're not concerned about RefCounts here,
180 // the store knows the last-used portion. If
181 // it's available, we're effectively claiming ownership
182 // of it. If it's not, we need to go away (realloc)
183 if (store_->canAppend(off_+len_, minSpace)) {
184 debugs(24, 7, "not growing");
185 return;
186 }
187 // TODO: we may try to memmove before realloc'ing in order to avoid
188 // one allocation operation, if we're the sole owners of a MemBlob.
189 // Maybe some heuristic on off_ and length()?
190 reAlloc(estimateCapacity(minSpace+length()));
191}
192
193void
194SBuf::clear()
195{
196#if 0
197 //enabling this code path, the store will be freed and reinitialized
198 store_ = GetStorePrototype(); //uncomment to actually free storage upon clear()
199#else
200 //enabling this code path, we try to release the store without deallocating it.
201 // will be lazily reallocated if needed.
202 if (store_->LockCount() == 1)
203 store_->clear();
204#endif
205 len_ = 0;
206 off_ = 0;
207 ++stats.clear;
208}
209
210SBuf&
211SBuf::append(const SBuf &S)
212{
213 return append(S.buf(), 0, S.length());
214}
215
216SBuf&
217SBuf::append(const char * S, size_type pos, size_type n)
218{
219 Must(pos == npos || pos >= 0);
220 Must(n == npos || n >= 0);
221
222 if (S == NULL)
223 return *this;
224 if (n == npos)
225 n = strlen(S)-pos;
226
227 debugs(24, 7, "from c-string to id " << id);
228
229 reserveSpace(n); //called method also checks n <= maxSize()
230 const char *actual_start = S+pos;
231 store_->append(actual_start, n);
232 len_ += n;
233 ++stats.append;
234 return *this;
235}
236
237SBuf&
238SBuf::append(const std::string &str, SBuf::size_type pos, SBuf::size_type n)
239{
240 return append(str.data(), pos, n); //bounds checked in append()
241}
242
243SBuf&
244SBuf::assign(const std::string &str, size_type pos, size_type n)
245{
246 clear();
247 return append(str, pos, n); //bounds checked in append()
248}
249
250SBuf&
251SBuf::Printf(const char *fmt, ...)
252{
253 va_list args;
254 va_start(args, fmt);
255 clear();
256 vappendf(fmt, args);
257 va_end(args);
258 return *this;
259}
260
261SBuf&
262SBuf::appendf(const char *fmt, ...)
263{
264 va_list args;
265 va_start(args, fmt);
266 vappendf(fmt, args);
267 va_end(args);
268 return *this;
269}
270
271SBuf&
272SBuf::vappendf(const char *fmt, va_list vargs)
273{
274#ifdef VA_COPY
275 va_list ap;
276#endif
277 int sz = 0;
278
279 Must(fmt != NULL);
280
281 //we can assume that we'll need to append at least strlen(fmt) bytes,
282 //times 1.2 for instance...
283 reserveSpace(strlen(fmt)*2);
284
285 while (length() <= maxSize) {
286#ifdef VA_COPY
287 /* Fix of bug 753r. The value of vargs is undefined
288 * after vsnprintf() returns. Make a copy of vargs
289 * in case we loop around and call vsnprintf() again.
290 */
291 VA_COPY(ap, vargs);
292 sz = vsnprintf(bufEnd(), store_->spaceSize(), fmt, ap);
293 va_end(ap);
294#else /* VA_COPY */
295 sz = vsnprintf(bufEnd(), store_->spaceSize(), fmt, vargs);
296#endif /* VA_COPY*/
297 /* check for possible overflow */
298 /* snprintf on Linux returns -1 on overflows */
299 /* snprintf on FreeBSD returns at least free_space on overflows */
300
301 if (sz < 0 || sz >= (int)store_->spaceSize())
302 reserveSpace(sz*2); // TODO: tune heuristics
303 else
304 break;
305 }
306
307 len_ += sz;
308 // TODO: this does NOT belong here, but to class-init or autoconf
309 /* on Linux and FreeBSD, '\0' is not counted in return value */
310 /* on XXX it might be counted */
311 /* check that '\0' is appended and not counted */
312
313 if (operator[](len_-1) == 0) {
314 --sz;
315 --len_;
316 }
317
318 store_->size += sz;
319 ++stats.append;
320
321 return *this;
322}
323
324std::ostream&
325SBuf::print(std::ostream &os) const
326{
327 os.write(buf(), length());
328 ++stats.toStream;
329 return os;
330}
331
332std::ostream&
333SBuf::dump(std::ostream &os) const
334{
335 os << id
336 << ": ";
337 store_->dump(os);
338 os << ",offset:" << off_
339 << ",len:" << len_
340 << ") : '";
341 print(os);
342 os << std::endl;
343 return os;
344}
345
346void
347SBuf::setAt(SBuf::size_type pos, char toset)
348{
349 checkAccessBounds(pos);
350 cow();
351 store_->mem[off_+pos] = toset;
352 ++stats.setChar;
353}
354
355static int
356memcasecmp(const char *b1, const char *b2, SBuf::size_type len)
357{
358 int rv=0;
359 while (len > 0) {
360 rv = tolower(*b1)-tolower(*b2);
361 if (rv != 0)
362 return rv;
363 ++b1;
364 ++b2;
365 --len;
366 }
367 return rv;
368}
369
370int
371SBuf::compare(const SBuf &S, SBufCaseSensitive isCaseSensitive, size_type n) const
372{
373 Must(n == npos || n >= 0);
374 size_type sz = min(S.length(), length());
375 if (n != npos)
376 sz = min(n, sz);
377 ++stats.compareSlow;
378 int rv;
379 if (isCaseSensitive == caseSensitive) {
380 rv = memcmp(buf(), S.buf(), sz);
381 } else {
382 rv = memcasecmp(buf(), S.buf(), sz);
383 }
384 if (rv != 0)
385 return rv;
386 // the first sz bytes are equal. If the user asked to ignore the rest
387 // by specifying n and no SBuf was shorter than it, the result is final
388 if (n == sz)
389 return 0;
390 //first sz bytes equal. longest SBuf "wins"
391 if (length() == S.length()) //they're REALLY the same..
392 return 0;
393 if (length() > S.length())
394 return 1;
395 return -1;
396
397}
398
399bool
400SBuf::startsWith(const SBuf &S, SBufCaseSensitive isCaseSensitive) const
401{
402 if (length() < S.length()) {
403 ++stats.compareFast;
404 return false;
405 }
406 return (compare(S, isCaseSensitive, S.length()) == 0);
407}
408
409bool
410SBuf::operator ==(const SBuf & S) const
411{
412 debugs(24, 8, id << " == " << S.id);
413 if (length() != S.length()) {
414 debugs(24, 8, "no, different lengths");
415 ++stats.compareFast;
416 return false; //shortcut: must be equal length
417 }
418 if (store_ == S.store_ && off_ == S.off_) {
419 debugs(24, 8, "yes, same length and backing store");
420 ++stats.compareFast;
421 return true; //shortcut: same store, offset and length
422 }
423 ++stats.compareSlow;
424 const bool rv = (0 == strncmp(buf(), S.buf(), length()));
425 debugs(24, 8, "returning " << rv);
426 return rv;
427}
428
429bool
430SBuf::operator !=(const SBuf & S) const
431{
432 return !(*this == S);
433}
434
435SBuf
436SBuf::consume(SBuf::size_type n)
437{
438 Must (n == npos || n >= 0);
439 if (n == npos)
440 n = length();
441 else
442 n = min(n, length());
443 SBuf rv(substr(0, n));
444 chop(n);
445 return rv;
446}
447
448const
449SBufStats& SBuf::GetStats()
450{
451 return stats;
452}
453
454SBuf::size_type
455SBuf::copy(char *dest, SBuf::size_type n) const
456{
457 Must(n >= 0);
458
459 SBuf::size_type toexport = length();
460 if (toexport > n)
461 toexport = n;
462
463 memcpy(dest, buf(), toexport);
464
465 ++stats.copyOut;
466 return toexport;
467}
468
469const char*
470SBuf::rawContent() const
471{
472 ++stats.rawAccess;
473 return buf();
474}
475
476char *
477SBuf::rawSpace(size_type minSize)
478{
479 cow(minSize+length());
480 ++stats.rawAccess;
481 return bufEnd();
482}
483
484void
485SBuf::forceSize(SBuf::size_type newSize)
486{
487 Must(store_->LockCount() == 1);
488 if (newSize > min(SBuf::maxSize,store_->capacity-off_))
489 throw SBufTooBigException(__FILE__,__LINE__);
490 len_ = newSize;
491 store_->size = newSize;
492}
493
494const char*
495SBuf::c_str()
496{
497 ++stats.rawAccess;
498 /* null-terminate the current buffer, by hand-appending a \0 at its tail but
499 * without increasing its length. May COW, the side-effect is to guarantee that
500 * the MemBlob's tail is availabe for us to use */
501 *rawSpace(1) = '\0';
502 ++store_->size;
503 ++stats.setChar;
504 return buf();
505}
506
507SBuf&
508SBuf::chop(SBuf::size_type pos, SBuf::size_type n)
509{
510 Must(pos >= 0);
511 Must(n == npos || n >= 0);
512 /*
513 * TODO: possible optimization: if the SBuf is at the tail of the
514 * MemBlob we could decrease the MemBlob tail-pointer so that a subsequent
515 * append will reuse the freed space.
516 */
517 if (pos > length() || n == 0) {
518 clear();
519 return *this;
520 }
521 if (n == npos || (pos+n) > length())
522 n = length()-pos;
523 ++stats.chop;
524 off_ += pos;
525 len_ = n;
526 return *this;
527}
528
529SBuf&
530SBuf::trim(const SBuf &toRemove, bool atBeginning, bool atEnd)
531{
532 ++stats.trim;
533 if (atEnd) {
534 const char *p = bufEnd()-1;
535 while (!isEmpty() && memchr(toRemove.buf(), *p, toRemove.length()) != NULL) {
536 //current end-of-buf is in the searched set
537 --len_;
538 --p;
539 }
540 }
541 if (atBeginning) {
542 const char *p = buf();
543 while (!isEmpty() && memchr(toRemove.buf(), *p, toRemove.length()) != NULL) {
544 --len_;
545 ++off_;
546 ++p;
547 }
548 }
549 if (isEmpty())
550 clear();
551 return *this;
552}
553
554SBuf
555SBuf::substr(SBuf::size_type pos, SBuf::size_type n) const
556{
557 SBuf rv(*this);
558 rv.chop(pos, n); //stats handled by callee
559 return rv;
560}
561
562SBuf::size_type
563SBuf::find(char c, SBuf::size_type startPos) const
564{
565 ++stats.find;
566
567 // std::string presents npos if needle is outside hay
568 if (startPos >= length())
569 return npos;
570
571 if (startPos < 0)
572 return npos;
573
574 // for npos with char sd::string returns npos
575 // this differs from how std::string handles 1-length string
576 if (startPos == npos)
577 return npos;
578
579 const void *i = memchr(buf()+startPos, (int)c, (size_type)length()-startPos);
580
581 if (i == NULL)
582 return npos;
583
584 return (static_cast<const char *>(i)-buf());
585}
586
587SBuf::size_type
588SBuf::find(const SBuf &needle, size_type startPos) const
589{
590 // std::string allows needle to overhang hay but not start outside
591 if (startPos != npos && startPos > length()) {
592 ++stats.find;
593 return npos;
594 }
595
596 // for empty needle std::string returns startPos
597 if (needle.length() == 0) {
598 ++stats.find;
599 return startPos;
600 }
601
602 // for npos with char* std::string scans entire hay
603 // this differs from how std::string handles single char from npos
604 if (startPos == npos)
605 return npos;
606
607 // if needle length is 1 use the char search
608 if (needle.length() == 1)
609 return find(needle[0], startPos);
610
611 ++stats.find;
612
613 char *begin = buf()+startPos;
614 char *lastPossible = buf()+length()-needle.length()+1;
615 char needleBegin = needle[0];
616
617 debugs(24, 7, "looking for " << needle << "starting at " << startPos <<
618 " in id " << id);
619 while (begin < lastPossible) {
620 char *tmp;
621 debugs(24, 8, " begin=" << (void *) begin <<
622 ", lastPossible=" << (void*) lastPossible );
623 tmp = static_cast<char *>(memchr(begin, needleBegin, lastPossible-begin));
624 if (tmp == NULL) {
625 debugs(24, 8 , "First byte not found");
626 return npos;
627 }
628 // lastPossible guarrantees no out-of-bounds with memcmp()
629 if (0 == memcmp(needle.buf(), tmp, needle.length())) {
630 debugs(24, 8, "Found at " << (tmp-buf()));
631 return (tmp-buf());
632 }
633 begin = tmp+1;
634 }
635 debugs(24, 8, "not found");
636 return npos;
637}
638
639SBuf::size_type
640SBuf::rfind(const SBuf &needle, SBuf::size_type endPos) const
641{
642 // when the needle is 1 char, use the 1-char rfind()
643 if (needle.length() == 1)
644 return rfind(needle[0], endPos);
645
646 ++stats.find;
647
648 // on npos input std::string scans from the end of hay
649 if (endPos == npos || endPos > length())
650 endPos=length();
651
652 // on empty hay std::string returns npos
653 if (length() < needle.length())
654 return npos;
655
656 // on empty needle std::string returns the position the search starts
657 if (needle.length() == 0)
658 return endPos;
659
660/* std::string permits needle to overhang endPos
661 if (endPos <= needle.length())
662 return npos;
663*/
664
665 char *bufBegin = buf();
666 char *cur = bufBegin+endPos;
667 char needleBegin = needle[0];
668 while (cur >= bufBegin) {
669 if (*cur == needleBegin) {
670 if (0 == memcmp(needle.buf(), cur, needle.length())) {
671 // found
672 return (cur-buf());
673 }
674 }
675 --cur;
676 }
677 return npos;
678}
679
680SBuf::size_type
681SBuf::rfind(char c, SBuf::size_type endPos) const
682{
683 ++stats.find;
684
685 // on empty hay std::string returns size of hay
686 if (length() < 1)
687 return npos;
688
689 // on npos input std::string compares last octet of hay
690 if (endPos == npos || endPos >= length())
691 endPos=length();
692 else {
693 // NP: off-by-one weirdness:
694 // endPos is an offset ... 0-based
695 // length() is a count ... 1-based
696 // memrhr() requires a 1-based count of space to scan.
697 ++endPos;
698 }
699
700 const void *i = memrchr(buf(), (int)c, (size_type)endPos);
701
702 if (i == NULL)
703 return npos;
704
705 return (static_cast<const char *>(i)-buf());
706}
707
708SBuf::size_type
709SBuf::find_first_of(const SBuf &set, size_type startPos) const
710{
711 Must(startPos == npos || startPos >= 0);
712 ++stats.find;
713
714 if (set.length() == 0)
715 return 0;
716
717 debugs(24, 7, "any of '" << set << "' " << " in id " << id);
718 if (startPos == npos || startPos > length())
719 return npos;
720 startPos = min(startPos, length());
721 char *cur = buf()+startPos, *end = bufEnd();
722 while (cur < end) {
723 if (memchr(set.buf(), *cur, set.length()))
724 return (cur-buf());
725 ++cur;
726 }
727 debugs(24, 7, "not found");
728 return npos;
729}
730
731/*
732 * TODO: borrow a sscanf implementation from Linux or similar?
733 * we'd really need a vsnscanf(3)... ? As an alternative, a
734 * light-regexp-like domain-specific syntax might be an idea.
735 */
736int
737SBuf::scanf(const char *format, ...)
738{
739 va_list arg;
740 int rv;
741 ++stats.scanf;
742 va_start(arg, format);
743 rv = vsscanf(c_str(), format, arg);
744 va_end(arg);
745 return rv;
746}
747
748std::ostream &
749operator <<(std::ostream& os, const SBuf& S)
750{
751 return S.print(os);
752}
753
754std::ostream &
755SBufStats::dump(std::ostream& os) const
756{
757 MemBlobStats ststats = MemBlob::GetStats();
758 os <<
759 "SBuf stats:\nnumber of allocations: " << alloc <<
760 "\ncopy-allocations: " << allocCopy <<
761 "\ncopy-allocations from SquidString: " << allocFromString <<
762 "\ncopy-allocations from C String: " << allocFromCString <<
763 "\nlive references: " << live <<
764 "\nno-copy assignments: " << assignFast <<
765 "\nclearing operations: " << clear <<
766 "\nappend operations: " << append <<
767 "\ndump-to-ostream: " << toStream <<
768 "\nset-char: " << setChar <<
769 "\nget-char: " << getChar <<
770 "\ncomparisons with data-scan: " << compareSlow <<
771 "\ncomparisons not requiring data-scan: " << compareFast <<
772 "\ncopy-out ops: " << copyOut <<
773 "\nraw access to memory: " << rawAccess <<
774 "\nchop operations: " << chop <<
775 "\ntrim operations: " << trim <<
776 "\nfind: " << find <<
777 "\nscanf: " << scanf <<
778 "\ncase-change ops: " << caseChange <<
779 "\nCOW not actually requiring a copy: " << cowFast <<
780 "\nCOW: " << cowSlow <<
781 "\naverage store share factor: " <<
782 (ststats.live != 0 ? static_cast<float>(live)/ststats.live : 0) <<
783 std::endl;
784 return os;
785}
786
787SBuf
788SBuf::toLower() const
789{
790 debugs(24, 8, "\"" << *this << "\"");
791 SBuf rv(*this);
792 for (size_type j = 0; j < length(); ++j) {
793 const int c = (*this)[j];
794 if (isupper(c))
795 rv.setAt(j, tolower(c)); //will cow() if needed
796 }
797 debugs(24, 8, "result: \"" << *this << "\"");
798 ++stats.caseChange;
799 return rv;
800}
801
802SBuf
803SBuf::toUpper() const
804{
805 debugs(24, 8, "\"" << *this << "\"");
806 SBuf rv(*this);
807 for (size_type j = 0; j < length(); ++j) {
808 const int c = (*this)[j];
809 if (islower(c))
810 rv.setAt(j, toupper(c)); //will cow() if needed
811 }
812 debugs(24, 8, "result: \"" << *this << "\"");
813 ++stats.caseChange;
814 return rv;
815}
816
817/**
818 * checks whether the requested 'pos' is within the bounds of the SBuf
819 * \throw OutOfBoundsException if access is out of bounds
820 */
821void
822SBuf::checkAccessBounds(SBuf::size_type pos) const
823{
824 if (pos < 0)
825 throw OutOfBoundsException(*this, pos, __FILE__, __LINE__);
826 if (pos > length())
827 throw OutOfBoundsException(*this, pos, __FILE__, __LINE__);
828}
829
830String
831SBuf::toString() const
832{
833 String rv;
834 rv.limitInit(buf(), length());
835 ++stats.copyOut;
836 return rv;
837}
838
839/*
840 * re-allocate the backing store of the SBuf.
841 * If there are contents in the SBuf, they will be copied over.
842 * NO verifications are made on the size parameters, it's up to the caller to
843 * make sure that the new size is big enough to hold the copied contents.
844 * The re-allocated storage MAY be bigger than the requested size due to size-chunking
845 * algorithms in MemBlock, it is guarranteed NOT to be smaller.
846 */
847void
848SBuf::reAlloc(SBuf::size_type newsize)
849{
850 debugs(24, DBG_DATA, "new size: " << newsize);
851 if (newsize > maxSize)
852 throw SBufTooBigException(__FILE__, __LINE__);
853 MemBlob::Pointer newbuf = new MemBlob(newsize);
854 if (length() > 0)
855 newbuf->append(buf(), length());
856 store_ = newbuf;
857 off_ = 0;
858 ++stats.cowSlow;
859 debugs(24, 7, "new store capacity: " << store_->capacity);
860}
861
862/**
863 * copy-on-write: make sure that we are the only holder of the backing store.
864 * If not, reallocate. If a new size is specified, and it is greater than the
865 * current length, the backing store will be extended as needed
866 * \retval false no grow was needed
867 * \retval true had to copy
868 */
869bool
870SBuf::cow(SBuf::size_type newsize)
871{
872 debugs(24, DBG_DATA, "new size:" << newsize);
873 if (newsize == npos || newsize < length())
874 newsize = length();
875
876 if (store_->LockCount() == 1 && newsize == length()) {
877 debugs(24, DBG_DATA, "no cow needed");
878 ++stats.cowFast;
879 return false;
880 }
881 reAlloc(newsize);
882 return true;
883}
884
885#if !_USE_INLINE_
886#include "SBuf.cci"
887#endif
0888
=== added file 'src/SBuf.cci'
--- src/SBuf.cci 1970-01-01 00:00:00 +0000
+++ src/SBuf.cci 2013-07-04 15:56:30 +0000
@@ -0,0 +1,174 @@
1/*
2 * SBuf.cc (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#include "base/RefCount.h"
32#include "OutOfBoundsException.h"
33#include "SBufExceptions.h"
34
35#if HAVE_CLIMITS
36#include <climits>
37#elif HAVE_LIMITS_H
38#include <limits.h>
39#endif
40
41SBuf&
42SBuf::operator =(const SBuf & S)
43{
44 return assign(S);
45}
46
47SBuf&
48SBuf::operator =(const char *S)
49{
50 return assign(S);
51}
52
53bool
54SBuf::operator <(const SBuf &S) const
55{
56 return (cmp(S) < 0);
57}
58
59bool
60SBuf::operator >(const SBuf &S) const
61{
62 return (cmp(S) > 0);
63}
64
65bool
66SBuf::operator <=(const SBuf &S) const
67{
68 return (cmp(S) <= 0);
69}
70
71bool
72SBuf::operator >=(const SBuf &S) const
73{
74 return (cmp(S) >= 0);
75}
76
77SBuf::size_type
78SBuf::length() const
79{
80 return len_;
81}
82
83int
84SBuf::plength() const
85{
86 if (length() > INT_MAX)
87 throw SBufTooBigException(__FILE__, __LINE__);
88 return (int)length();
89}
90
91/**
92 * obtains a char* to the beginning of this SBuf in memory.
93 * \note the obtained string is NOT null-terminated.
94 */
95char *
96SBuf::buf() const
97{
98 return store_->mem+off_;
99}
100
101/** returns the pointer to the first char after this SBuf end
102 *
103 */
104char *
105SBuf::bufEnd() const
106{
107 return store_->mem+off_+len_;
108}
109
110/**
111 * Try to guesstimate how big a MemBlob to allocate.
112 * The result is guarranteed to be to be at least the desired
113 * size.
114 */
115const SBuf::size_type
116SBuf::estimateCapacity(SBuf::size_type desired) const
117{
118 return 2*desired;
119}
120
121/**
122 * To be called after having determined that the buffers are equal up to the
123 * length of the shortest one.
124 * If the buffers' length is the same, then they're equal. Otherwise, the
125 * longest one is deemed to be greater than the other.
126 * This matches the behavior of strcmp(1) and strcasecmp(1)
127 */
128int
129SBuf::commonCompareChecksPost(const SBuf &S) const
130{
131 if (length() == S.length()) //they're REALLY the same..
132 return 0;
133 if (length() > S.length())
134 return 1;
135 return -1;
136}
137
138/** obtain prototype store
139 *
140 * Just-created SBufs all share to the same MemBlob.
141 * This call instantiates and returns it.
142 */
143MemBlob::Pointer
144SBuf::GetStorePrototype()
145{
146 static MemBlob::Pointer InitialStore = NULL;
147 if (InitialStore == NULL) {
148 static char lowPrototype[] = "";
149 InitialStore = new MemBlob(lowPrototype, 0);
150 }
151 return InitialStore;
152}
153
154const char
155SBuf::operator [](SBuf::size_type pos) const
156{
157 ++stats.getChar;
158 if (pos < 0 || pos >= length())
159 return '\0';
160 return store_->mem[off_+pos];
161}
162
163const char
164SBuf::at(SBuf::size_type pos) const
165{
166 checkAccessBounds(pos);
167 return operator[](pos);
168}
169
170bool
171SBuf::isEmpty() const
172{
173 return (len_ == 0);
174}
0175
=== added file 'src/SBuf.h'
--- src/SBuf.h 1970-01-01 00:00:00 +0000
+++ src/SBuf.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,571 @@
1/*
2 * SBuf.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#ifndef SQUID_SBUF_H
32#define SQUID_SBUF_H
33
34#include "base/InstanceId.h"
35#include "Debug.h"
36#include "MemBlob.h"
37#include "SquidString.h"
38
39#if HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42#if HAVE_STDARG_H
43#include <stdarg.h>
44#endif
45#if HAVE_IOSFWD
46#include <iosfwd>
47#endif
48
49/* squid string placeholder (for printf) */
50#ifndef SQUIDSBUFPH
51#define SQUIDSBUFPH "%.*s"
52#define SQUIDSBUFPRINT(s) (s).plength(),(s).rawContent()
53#endif /* SQUIDSBUFPH */
54
55typedef enum {
56 caseSensitive,
57 caseInsensitive
58} SBufCaseSensitive;
59
60/**
61 * Container for various SBuf class-wide statistics.
62 *
63 * The stats are not completely accurate; they're mostly meant to
64 * understand whether Squid is leaking resources
65 * and whether SBuf is paying off the expected gains.
66 */
67class SBufStats
68{
69public:
70 u_int64_t alloc; ///<number of calls to SBuf constructors
71 u_int64_t allocCopy; ///<number of calls to SBuf copy-constructor
72 u_int64_t allocFromString; ///<number of copy-allocations from Strings
73 u_int64_t allocFromCString; ///<number of copy-allocations from c-strings
74 u_int64_t assignFast; ///<number of no-copy assignment operations
75 u_int64_t clear; ///<number of clear operations
76 u_int64_t append; ///<number of append operations
77 u_int64_t toStream; ///<number of write operations to ostreams
78 u_int64_t setChar; ///<number of calls to setAt
79 u_int64_t getChar; ///<number of calls to at() and operator[]
80 u_int64_t compareSlow; ///<number of comparison operations requiring data scan
81 u_int64_t compareFast; ///<number of comparison operations not requiring data scan
82 u_int64_t copyOut; ///<number of data-copies to other forms of buffers
83 u_int64_t rawAccess; ///<number of accesses to raw contents
84 u_int64_t chop; ///<number of chop operations
85 u_int64_t trim; ///<number of trim operations
86 u_int64_t find; ///<number of find operations
87 u_int64_t scanf; ///<number of scanf operations
88 u_int64_t caseChange; ///<number of toUpper and toLower operations
89 u_int64_t cowFast; ///<number of cow operations not actually requiring a copy
90 u_int64_t cowSlow; ///<number of cow operations requiring a copy
91 u_int64_t live; ///<number of currently-allocated SBuf
92
93 /**
94 * Dump statistics to an ostream.
95 */
96 std::ostream& dump(std::ostream &os) const;
97 SBufStats();
98
99 SBufStats& operator +=(const SBufStats&);
100};
101
102/**
103 * A String or Buffer.
104 * Features: refcounted backing store, cheap copy and sub-stringing
105 * operations, copy-on-write to isolate change operations to each instance.
106 * Where possible, we're trying to mimic std::string's interface.
107 */
108class SBuf
109{
110public:
111 typedef int32_t size_type;
112 static const size_type npos = -1;
113
114 /// Maximum size of a SBuf. By design it MUST be < MAX(size_type)/2. Currently 256Mb.
115 static const size_type maxSize = 0xfffffff;
116
117 /// create an empty (zero-size) SBuf
118 SBuf();
119 SBuf(const SBuf &S);
120
121 /** Constructor: import c-style string
122 *
123 * Create a new SBuf containing a COPY of the contents of the
124 * c-string
125 * \param S the c string to be copied
126 * \param pos how many bytes to skip at the beginning of the c-string
127 * \param n how many bytes to import into the SBuf. If it is SBuf::npos
128 * or unspecified, imports to end-of-cstring
129 * \note it is the caller's responsibility not to go out of bounds
130 * \note bounds is 0 <= pos < length()
131 */
132 explicit SBuf(const char *S, size_type pos = 0, size_type n = npos);
133
134 /** Constructor: import SquidString, copying contents.
135 *
136 * This method will be removed once SquidString has gone.
137 */
138 SBuf(const String &S);
139
140 ~SBuf();
141 /** Explicit assignment.
142 *
143 * Current SBuf will share backing store with the assigned one.
144 */
145 SBuf& assign(const SBuf &S);
146 /** Assignment operator.
147 *
148 * Current SBuf will share backing store with the assigned one.
149 */
150 _SQUID_INLINE_ SBuf& operator =(const SBuf & S);
151
152 /** Import a c-string into a SBuf, copying the data.
153 *
154 * It is the caller's duty to free the imported string, if needed.
155 * \param S the c string to be copied
156 * \param pos how many bytes to skip at the beginning of the c-string.
157 * \param n how many bytes to import into the SBuf. If it is SBuf::npos
158 * or unspecified, imports to end-of-cstring
159 * \note it is the caller's responsibility not to go out of bounds
160 * \note bounds is 0 <= pos < length()
161 */
162 SBuf& assign(const char *S, size_type pos = 0, size_type n = npos);
163
164 /** Assignment operator. Copy a NULL-terminated c-style string into a SBuf.
165 *
166 * Copy a c-style string into a SBuf. Shortcut for SBuf.assign(S)
167 * It is the caller's duty to free the imported string, if needed.
168 */
169 _SQUID_INLINE_ SBuf& operator =(const char *S);
170
171 /** Import a std::string into a SBuf. Contents are copied.
172 *
173 * \param pos skip this many bytes at the beginning of string.
174 * 0 is beginning-of-string
175 * \param n how many bytes to copy. Default is SBuf::npos, end-of-string.
176 */
177 SBuf& assign(const std::string &s, size_type pos = 0, size_type n = npos);
178
179 /** reset the SBuf as if it was just created.
180 *
181 * Resets the SBuf to empty, memory is freed lazily.
182 */
183 void clear();
184
185 /** Append operation
186 *
187 * Append the supplied SBuf to the current one; extend storage as needed.
188 */
189 SBuf& append(const SBuf & S);
190
191 /** Append operation for C-style strings.
192 *
193 * Append the supplied c-string to the SBuf; extend storage
194 * as needed.
195 *
196 * \param S the c string to be copied. Can be NULL.
197 * \param pos how many bytes to skip at the beginning of the c-string
198 * \param n how many bytes to import into the SBuf. If it is SBuf::npos
199 * or unspecified, imports to end-of-cstring
200 */
201 SBuf& append(const char * S, size_type pos = 0, size_type n = npos);
202
203 /** Append operation for std::string
204 *
205 * Append the supplied std::string to the SBuf; extend storage as needed.
206 *
207 * \param string the std::string to be copied.
208 * \param pos how many bytes to skip at the beginning of the c-string
209 * \param n how many bytes to import into the SBuf. If it is SBuf::npos
210 * or unspecified, imports to end-of-cstring
211 */
212 SBuf& append(const std::string &str, size_type pos = 0, size_type n = npos);
213
214 /** Assignment operation with printf(3)-style definition
215 * \note arguments may be evaluated more than once, be careful
216 * of side-effects
217 */
218 SBuf& Printf(const char *fmt, ...);
219
220 /** Append operation with printf-style arguments
221 * \note arguments may be evaluated more than once, be careful
222 * of side-effects
223 */
224 SBuf& appendf(const char *fmt, ...);
225 /** Append operation, with vsprintf(3)-style arguments.
226 * \note arguments may be evaluated more than once, be careful
227 * of side-effects
228 */
229 SBuf& vappendf(const char *fmt, va_list vargs);
230
231 /** print a SBuf.
232 */
233 std::ostream& print(std::ostream &os) const;
234
235 /** print the sbuf, debug information and stats
236 *
237 * Debug function, dumps to a stream informations on the current SBuf,
238 * including low-level details and statistics.
239 */
240 std::ostream& dump(std::ostream &os) const;
241
242 /** random-access read to any char within the SBuf
243 *
244 * does not check access bounds. If you need that, use at()
245 */
246 _SQUID_INLINE_ const char operator [](size_type pos) const;
247
248 /** random-access read to any char within the SBuf.
249 *
250 * \throw OutOfBoundsException when access is out of bounds
251 * \note bounds is 0 <= pos < length()
252 */
253 _SQUID_INLINE_ const char at(size_type pos) const;
254
255 /** direct-access set a byte at a specified operation.
256 *
257 * \param pos the position to be overwritten
258 * \param toset the value to be written
259 * \throw OutOfBoundsException when pos is of bounds
260 * \note bounds is 0 <= pos < length()
261 * \note performs a copy-on-write if needed.
262 */
263 void setAt(size_type pos, char toset);
264
265 /** compare to other SBuf, str(case)cmp-style
266 *
267 * \param isCaseSensitive one of caseSensitive or caseInsensitive
268 * \param n compare up to this many bytes. if npos (default), compare whole SBufs
269 * \retval >0 argument of the call is greater than called SBuf
270 * \retval <0 argument of the call is smaller than called SBuf
271 * \retval 0 argument of the call has the same contents of called SBuf
272 */
273 int compare(const SBuf &S, SBufCaseSensitive isCaseSensitive, size_type n = npos) const;
274
275 /// shorthand version for compare
276 inline int cmp(const SBuf &S, size_type n = npos) const {
277 return compare(S,caseSensitive,n);
278 }
279
280 /// shorthand version for case-insensitive comparison
281 inline int casecmp(const SBuf &S, size_type n = npos) const {
282 return compare(S,caseInsensitive,n);
283 }
284
285 /** check whether the entire supplied argument is a prefix of the SBuf.
286 * \param S the prefix to match against
287 * \param isCaseSensitive one of caseSensitive or caseInsensitive
288 * \retval true argument is a prefix of the SBuf
289 */
290 bool startsWith(const SBuf &S, SBufCaseSensitive isCaseSensitive = caseSensitive) const;
291
292 /** equality check
293 */
294 bool operator ==(const SBuf & S) const;
295 bool operator !=(const SBuf & S) const;
296 _SQUID_INLINE_ bool operator <(const SBuf &S) const;
297 _SQUID_INLINE_ bool operator >(const SBuf &S) const;
298 _SQUID_INLINE_ bool operator <=(const SBuf &S) const;
299 _SQUID_INLINE_ bool operator >=(const SBuf &S) const;
300
301 /** Consume bytes at the head of the SBuf
302 *
303 * Consume N chars at SBuf head, or to SBuf's end,
304 * whichever is shorter. If more bytes are consumed than available,
305 * the SBuf is emptied
306 * \param n how many bytes to remove; could be zero.
307 * SBuf::npos (or no argument) means 'to the end of SBuf'
308 * \return a new SBuf containing the consumed bytes.
309 */
310 SBuf consume(size_type n = npos);
311
312 /** gets global statistic informations
313 *
314 */
315 static const SBufStats& GetStats();
316
317 /** Copy SBuf contents into user-supplied C buffer.
318 *
319 * Export a copy of the SBuf's contents into the user-supplied
320 * buffer, up to the user-supplied-length. No zero-termination is performed
321 * \return num the number of actually-copied chars.
322 */
323 size_type copy(char *dest, size_type n) const;
324
325 /** exports a pointer to the SBuf internal storage.
326 * \warning ACCESSING RAW STORAGE IS DANGEROUS!
327 *
328 * Returns a pointer to SBuf's content. No terminating null character
329 * is appended (use c_str() for that).
330 * The returned value points to an internal location whose contents
331 * are guaranteed to remain unchanged only until the next call
332 * to a non-constant member function of the SBuf object. Such a
333 * call may be implicit (e.g., when SBuf is destroyed
334 * upon leaving the current context).
335 * This is a very UNSAFE way of accessing the data.
336 * This call never returns NULL.
337 * \see c_str
338 * \note the memory management system guarantees that the exported region
339 * of memory will remain valid if the caller keeps holding
340 * a valid reference to the SBuf object and does not write or append to
341 * it. For example:
342 * \code
343 * SBuf foo("some string");
344 * const char *bar = foo.rawContent();
345 * doSomething(bar); //safe
346 * foo.append(" other string");
347 * doSomething(bar); //unsafe
348 * \endcode
349 */
350 const char* rawContent() const;
351
352 /** Exports a writable pointer to the SBuf internal storage.
353 * \warning Use with EXTREME caution, this is a dangerous operation.
354 *
355 * Returns a pointer to the first unused byte in the SBuf's storage,
356 * to be used for writing. If minsize is specified, it is guaranteed
357 * that at least minsize bytes will be available for writing. Otherwise
358 * it is guaranteed that at least as much storage as is currently
359 * available will be available for the call. A COW will be performed
360 * if necessary to ensure that a following write will not trample
361 * a shared MemBlob. The returned pointer must not be stored, and will
362 * become invalid at the first call to a non-const method call
363 * on the SBuf.
364 * This call guarantees to never return NULL
365 * This call always forces a cow()
366 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
367 */
368 char *rawSpace(size_type minSize = npos);
369
370 /** Force a SBuf's size
371 * \warning use with EXTREME caution, this is a dangerous operation
372 *
373 * Adapt the SBuf internal state after external interference
374 * such as writing into it via rawSpace.
375 * \throw TextException if SBuf doesn't have exclusive ownership of store
376 * \throw SBufTooBigException if new size is bigger than available store space
377 */
378 void forceSize(size_type newSize);
379
380 /** exports a null-terminated reference to the SBuf internal storage.
381 * \warning ACCESSING RAW STORAGE IS DANGEROUS! DO NOT EVER USE
382 * THE RETURNED POINTER FOR WRITING
383 *
384 * The returned value points to an internal location whose contents
385 * are guaranteed to remain unchanged only until the next call
386 * to a non-constant member function of the SBuf object. Such a
387 * call may be implicit (e.g., when SBuf is destroyed
388 * upon leaving the current context).
389 * This is a very UNSAFE way of accessing the data.
390 * This call never returns NULL.
391 * \see rawContent
392 * \note the memory management system guarantees that the exported region
393 * of memory will remain valid if the caller keeps holding
394 * a valid reference to the SBuf object and does not write or append to
395 * it
396 */
397 const char* c_str();
398
399 /** Returns the number of bytes stored in SBuf.
400 */
401 _SQUID_INLINE_ size_type length() const;
402
403 /** Get the length of the SBuf, as a signed integer
404 *
405 * Compatibility function for printf(3) which requires a signed int
406 * \throw SBufTooBigException if the SBuf is too big for a signed integer
407 */
408 _SQUID_INLINE_ int plength() const;
409
410 /** Check whether the SBuf is empty
411 *
412 * \return true if length() == 0
413 */
414 _SQUID_INLINE_ bool isEmpty() const;
415
416 /** Request to extend the SBuf's free store space.
417 *
418 * After the reserveSpace request, the SBuf is guaranteed to have at
419 * least minSpace bytes of append-able backing store (on top of the
420 * currently-used portion).
421 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
422 */
423 void reserveSpace(size_type minSpace);
424
425 /** Request to resize the SBuf's store
426 *
427 * After this method is called, the SBuf is guaranteed to have at least
428 * minCapcity bytes of total space, including the currently-used portion
429 * \throw SBufTooBigException if the user tries to allocate too big a SBuf
430 */
431 void reserveCapacity(size_type minCapacity);
432
433 /** slicing method
434 *
435 * Removes SBuf prefix and suffix, leaving a sequence of <i>n</i>
436 * bytes starting from position <i>pos</i> first byte is at pos 0.
437 * \param pos start sub-stringing from this byte. If it is
438 * greater than the SBuf length, the SBuf is emptied and
439 * an empty SBuf is returned
440 * \param n maximum number of bytes of the resulting SBuf.
441 * SBuf::npos means "to end of SBuf".
442 * if 0 returns an empty SBuf.
443 */
444 SBuf& chop(size_type pos, size_type n = npos);
445
446 /** Remove characters in the toremove set at the beginning, end or both
447 *
448 * \param toremove characters to be removed. Stops chomping at the first
449 * found char not in the set
450 * \param atBeginning if true (default), strips at the beginning of the SBuf
451 * \param atEnd if true (default), strips at the end of the SBuf
452 */
453 SBuf& trim(const SBuf &toRemove, bool atBeginning = true, bool atEnd = true);
454
455 /** Extract a part of the current SBuf.
456 *
457 * Return a fresh a fresh copy of a portion the current SBuf, which is left untouched.
458 * \see trim
459 */
460 SBuf substr(size_type pos, size_type n = npos) const;
461
462 /** Find first occurrence of character in SBuf
463 *
464 * Returns the index in the SBuf of the first occurrence of char c.
465 * \param startPos if specified, ignore any occurrences before that position
466 * if startPos is npos, always return npos
467 * \return SBuf::npos if the char was not found
468 */
469 size_type find(char c, size_type startPos = 0) const;
470
471 /** Find first occurrence of SBuf in SBuf.
472 *
473 * Returns the index in the SBuf of the first occurrence of the
474 * sequence contained in the str argument.
475 * \param startPos if specified, ignore any occurrences before that position
476 * if startPos is npos, always return npos
477 * \return SBuf::npos if the SBuf was not found
478 */
479 size_type find(const SBuf & str, size_type startPos = 0) const;
480
481 /** Find last occurrence of character in SBuf
482 *
483 * Returns the index in the SBuf of the last occurrence of char c.
484 * \param endPos if specified, ignore any occurrences after that position
485 * \return SBuf::npos if the char was not found
486 */
487 size_type rfind(char c, size_type endPos = npos) const;
488
489 /** Find last occurrence of SBuf in SBuf
490 *
491 * Returns the index in the SBuf of the last occurrence of the
492 * sequence contained in the str argument.
493 * \return SBuf::npos if the sequence was not found
494 * \param endPos if specified, ignore any occurrences after that position
495 */
496 size_type rfind(const SBuf &str, size_type endPos = npos) const;
497
498 /** Find first occurrence of character of set in SBuf
499 *
500 * Finds the first occurrence of ANY of the characters in the supplied set in
501 * the SBuf.
502 * \return SBuf::npos if no character in the set could be found
503 * \param startPos if specified, ignore any occurrences before that position
504 */
505 size_type find_first_of(const SBuf &set, size_type startPos = 0) const;
506
507 /** sscanf-alike
508 *
509 * sscanf re-implementation. Non-const, and not \0-clean.
510 * \return same as sscanf
511 * \see man sscanf(3)
512 */
513 int scanf(const char *format, ...);
514
515 /** Lower-case SBuf
516 *
517 * Returns a lower-cased COPY of the SBuf
518 * \see man tolower(3)
519 */
520 SBuf toLower() const;
521
522 /** Upper-case SBuf
523 *
524 * Returns an upper-cased COPY of the SBuf
525 * \see man toupper(3)
526 */
527 SBuf toUpper() const;
528
529 /** String export function
530 * converts the SBuf to a legacy String, by copy. Transitional.
531 */
532 String toString() const;
533
534 /// TODO: possibly implement erase() similar to std::string's erase
535 /// TODO: possibly implement a replace() call
536private:
537
538 MemBlob::Pointer store_; ///< memory block, possibly shared with other SBufs
539 size_type off_; ///< our content start offset from the beginning of shared store_
540 size_type len_; ///< number of our content bytes in shared store_
541 static SBufStats stats; ///< class-wide statistics
542
543 /// SBuf object identifier; does not change when contents do,
544 /// including during assignment
545 const InstanceId<SBuf> id;
546
547 _SQUID_INLINE_ static MemBlob::Pointer GetStorePrototype();
548
549 _SQUID_INLINE_ char * buf() const;
550 _SQUID_INLINE_ char * bufEnd() const;
551 _SQUID_INLINE_ const size_type estimateCapacity(size_type desired) const;
552 void reAlloc(size_type newsize);
553
554 bool cow(size_type minsize = npos);
555
556 void checkAccessBounds(size_type pos) const;
557 _SQUID_INLINE_ int commonCompareChecksPre(const SBuf &S) const;
558 _SQUID_INLINE_ int commonCompareChecksPost(const SBuf &S) const;
559
560};
561
562/**
563 * Prints a SBuf to the supplied stream, allowing for chaining
564 */
565std::ostream& operator <<(std::ostream &os, const SBuf &S);
566
567#if _USE_INLINE_
568#include "SBuf.cci"
569#endif
570
571#endif /* SQUID_SBUF_H */
0572
=== added file 'src/SBufExceptions.cc'
--- src/SBufExceptions.cc 1970-01-01 00:00:00 +0000
+++ src/SBufExceptions.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,72 @@
1/*
2 * SBufExceptions.cc (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#include "squid.h"
32#include "OutOfBoundsException.h"
33#include "SBuf.h"
34#include "SBufExceptions.h"
35
36// Note: the SBuf is intentionally passed by copy rather than reference,
37// to let refcounting act.
38OutOfBoundsException::OutOfBoundsException(const SBuf &throwingBuf,
39 SBuf::size_type &pos,
40 const char *aFileName, int aLineNo)
41 :TextException(NULL, aFileName, aLineNo)
42{
43 _buf = throwingBuf;
44 _pos = pos;
45 SBuf explanatoryText("OutOfBoundsException");
46 if (aLineNo != -1)
47 explanatoryText.appendf(" at line %d", aLineNo);
48 if (aFileName != 0)
49 explanatoryText.appendf(" in file %s", aFileName);
50 explanatoryText.appendf(" while accessing position %d in a SBuf long %d",
51 pos, throwingBuf.length());
52 // we can safely alias c_str as both are local to the object
53 // and will not further manipulated.
54 message = xstrndup(explanatoryText.c_str(),explanatoryText.length());
55}
56
57OutOfBoundsException::~OutOfBoundsException() throw()
58{ }
59
60NullSBufException::NullSBufException(const char *aFilename, int aLineNo)
61 : TextException("Trying to access a null SBuf", aFilename, aLineNo)
62{ }
63
64InvalidParamException::InvalidParamException(const char *aFilename, int aLineNo)
65 : TextException("Invalid parameter", aFilename, aLineNo)
66{ }
67
68SBufTooBigException::SBufTooBigException(const char *aFilename, int aLineNo)
69 : TextException("Trying to create an oversize SBuf", aFilename, aLineNo)
70{ }
71
72/* */
073
=== added file 'src/SBufExceptions.h'
--- src/SBufExceptions.h 1970-01-01 00:00:00 +0000
+++ src/SBufExceptions.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,65 @@
1/*
2 * SBufExceptions.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#ifndef SQUID_SBUFEXCEPTIONS_H
32#define SQUID_SBUFEXCEPTIONS_H
33
34#include "base/TextException.h"
35
36/**
37 * Exception raised when the user is trying to operate on a Null SBuf
38 * \todo move to an Exceptions.h?
39 */
40class NullSBufException : public TextException
41{
42public:
43 explicit NullSBufException(const char *aFilename = 0, int aLineNo = -1);
44};
45
46/**
47 * Exception raised when call parameters are not valid
48 * \todo move to an Exceptions.h?
49 */
50class InvalidParamException : public TextException
51{
52public:
53 explicit InvalidParamException(const char *aFilename = 0, int aLineNo = -1);
54};
55
56/**
57 * Exception raised when an attempt to resize a SBuf would cause it to reserve too big
58 */
59class SBufTooBigException : public TextException
60{
61public:
62 explicit SBufTooBigException(const char *aFilename = 0, int aLineNo = -1);
63};
64
65#endif /* SQUID_SBUFEXCEPTIONS_H */
066
=== added file 'src/SBufExtras.cc'
--- src/SBufExtras.cc 1970-01-01 00:00:00 +0000
+++ src/SBufExtras.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,104 @@
1/*
2 * SBufExtras.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31/*
32 * This file contains various helper functions which are meant to be
33 * a bridge towards SBuf integration, but which do not belong to SBuf proper,
34 * such as functions shuttling to and from other data types.
35 */
36
37#include "squid.h"
38#include "ipc/Messages.h"
39#include "ipc/TypedMsgHdr.h"
40#include "mgr/Registration.h"
41#include "SBufExtras.h"
42#include "StoreEntryStream.h"
43
44SBufStatsAction::SBufStatsAction(const Mgr::CommandPointer &cmd_):
45 Action(cmd_)
46{ } //default constructor is OK for data member
47
48SBufStatsAction::Pointer
49SBufStatsAction::Create(const Mgr::CommandPointer &cmd)
50{
51 debugs(24, 8, "" );
52 return new SBufStatsAction(cmd);
53}
54void
55SBufStatsAction::add(const Mgr::Action& action)
56{
57 debugs(24, 8, "");
58 data.sbdata += dynamic_cast<const SBufStatsAction&>(action).data.sbdata;
59 data.mbdata += dynamic_cast<const SBufStatsAction&>(action).data.mbdata;
60}
61
62void
63SBufStatsAction::collect()
64{
65 debugs(24, 8, "" );
66 data.sbdata = SBuf::GetStats();
67 data.mbdata = MemBlob::GetStats();
68}
69
70void
71SBufStatsAction::dump(StoreEntry* entry)
72{
73 debugs(24, 8, "" );
74 Must(entry != NULL);
75 StoreEntryStream ses(entry);
76 data.sbdata.dump(ses);
77 data.mbdata.dump(ses);
78}
79
80void
81SBufStatsAction::pack(Ipc::TypedMsgHdr& msg) const
82{
83 debugs(24, 8, "" );
84 msg.setType(Ipc::mtCacheMgrResponse);
85 msg.putPod(data);
86}
87
88void
89SBufStatsAction::unpack(const Ipc::TypedMsgHdr& msg)
90{
91 debugs(24, 8, "" );
92 msg.checkType(Ipc::mtCacheMgrResponse);
93 msg.getPod(data);
94}
95
96class SBufStatsRegistrationHelperObject
97{
98public:
99 SBufStatsRegistrationHelperObject() {
100 Mgr::RegisterAction("sbuf", "String-Buffer statistics",
101 &SBufStatsAction::Create, 0 , 1);
102 }
103};
104static SBufStatsRegistrationHelperObject sbufstatsinstantiator;
0105
=== added file 'src/SBufExtras.h'
--- src/SBufExtras.h 1970-01-01 00:00:00 +0000
+++ src/SBufExtras.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,66 @@
1/*
2 * SBufExtras.h (C) 2008 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31/*
32 * This file contains various helper functions which are meant to be
33 * a bridge towards SBuf integration, but which do not belong to SBuf proper,
34 * such as functions shuttling to and from other data types.
35 */
36
37#ifndef SQUID_SBUFEXTRAS_H
38#define SQUID_SBUFEXTRAS_H
39
40#include "ipc/TypedMsgHdr.h"
41#include "MemBuf.h"
42#include "mgr/Action.h"
43#include "SBuf.h"
44#include "Store.h"
45
46class SBufStatsAction: public Mgr::Action
47{
48protected:
49 SBufStatsAction(const Mgr::CommandPointer &cmd);
50 virtual void collect();
51 virtual void dump(StoreEntry* entry);
52
53public:
54 static Pointer Create(const Mgr::CommandPointer &cmd);
55 virtual void add(const Mgr::Action& action);
56 virtual void pack(Ipc::TypedMsgHdr& msg) const;
57 virtual void unpack(const Ipc::TypedMsgHdr& msg);
58
59private:
60 struct SbufStatsActionData {
61 SBufStats sbdata;
62 MemBlobStats mbdata;
63 } data;
64};
65
66#endif /* SQUID_SBUFEXTRAS_H */
067
=== added file 'src/SBufList.cc'
--- src/SBufList.cc 1970-01-01 00:00:00 +0000
+++ src/SBufList.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,56 @@
1/*
2 * SBufList.cc (C) 2009 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#include "squid.h"
32#include "SBufList.h"
33
34SBufList& SBufList::add(SBuf S)
35{
36 push_back(S);
37 return *this;
38}
39
40bool SBufList::isMember(const SBuf &S, SBufCaseSensitive case_sensitive)
41{
42 iterator i;
43 for (i = begin(); i != end(); ++i)
44 if (i->compare(S,case_sensitive) == 0)
45 return true;
46 return false;
47}
48
49bool SBufList::isPrefix(const SBuf &s, SBufCaseSensitive case_sensitive)
50{
51 iterator i;
52 for (i = begin(); i != end(); ++i)
53 if (i->startsWith(s,case_sensitive))
54 return true;
55 return false;
56}
057
=== added file 'src/SBufList.h'
--- src/SBufList.h 1970-01-01 00:00:00 +0000
+++ src/SBufList.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,62 @@
1/*
2 * SBufList.h (C) 2009 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#ifndef SQUID_SBUFLIST_H
32#define SQUID_SBUFLIST_H
33
34#include "SBuf.h"
35#include <list>
36
37/** List of SBuf
38 *
39 */
40class SBufList : public std::list<SBuf>
41{
42public:
43 /** Add a SBuf to the list
44 *
45 * \note can be chained
46 */
47 SBufList& add(SBuf);
48
49 /** check for membership
50 *
51 * true if the supplied SBuf is a member of the list
52 * \param case_sensitive one of caseSensitive or caseInsensitive
53 */
54 bool isMember(const SBuf &, SBufCaseSensitive case_sensitive = caseSensitive);
55
56 /** check whether SBuf is prefix of any member in the list
57 * \param case_sensitive one of caseSensitive or caseInsensitive
58 */
59 bool isPrefix(const SBuf &, SBufCaseSensitive case_sensitive = caseSensitive);
60};
61
62#endif /* SQUID_SBUFLIST_H */
063
=== added file 'src/SBufStream.h'
--- src/SBufStream.h 1970-01-01 00:00:00 +0000
+++ src/SBufStream.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,141 @@
1/*
2 * SQUID Web Proxy Cache http://www.squid-cache.org/
3 * ----------------------------------------------------------
4 *
5 * Squid is the result of efforts by numerous individuals from
6 * the Internet community; see the CONTRIBUTORS file for full
7 * details. Many organizations have provided support for Squid's
8 * development; see the SPONSORS file for full details. Squid is
9 * Copyrighted (C) 2001 by the Regents of the University of
10 * California; see the COPYRIGHT file for full details. Squid
11 * incorporates software developed and/or copyrighted by other
12 * sources; see the CREDITS file for full details.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
27 *
28 */
29
30#ifndef SQUID_SBUFSTREAM_H
31#define SQUID_SBUFSTREAM_H
32
33#include "SBuf.h"
34
35#if HAVE_OSTREAM
36#include <ostream>
37#endif
38
39/**
40 * streambuf class for a SBuf-backed stream interface.
41 *
42 */
43class SBufStreamBuf : public std::streambuf
44{
45public:
46 /// initialize streambuf; use supplied SBuf as backing store
47 SBufStreamBuf(SBuf aBuf) : theBuf(aBuf) {}
48
49 /// get a copy of the stream's contents
50 SBuf getBuf() {
51 return theBuf;
52 }
53
54 /// clear the stream's store
55 void clearBuf() {
56 theBuf.clear();
57 }
58
59protected:
60 virtual int_type overflow(int_type aChar = traits_type::eof()) {
61 std::streamsize pending(pptr() - pbase());
62
63 if (pending && sync())
64 return traits_type::eof();
65
66 if (aChar != traits_type::eof()) {
67 char chars[1] = {static_cast<char>(aChar)};
68
69 if (aChar != traits_type::eof())
70 theBuf.append(chars, 0, 1);
71 }
72
73 pbump(-pending); // Reset pptr().
74 return aChar;
75 }
76
77 /* push the streambuf to the backing SBuf */
78 virtual int sync() {
79 std::streamsize pending(pptr() - pbase());
80
81 if (pending)
82 theBuf.append(pbase(), 0, pending);
83
84 return 0;
85 }
86
87 /* write multiple characters to the store entry
88 * - this is an optimisation method.
89 */
90 virtual std::streamsize xsputn(const char * chars, std::streamsize number) {
91 if (number)
92 theBuf.append(chars, 0, number);
93
94 return number;
95 }
96
97private:
98 SBuf theBuf;
99 SBufStreamBuf(); // no default constructor
100};
101
102/** Stream interface to write to a SBuf.
103 *
104 * Data is appended using standard operator << semantics, and extracted
105 * using the buf() method, in analogy with std::strstream .
106 */
107class SBufStream : public std::ostream
108{
109public:
110 /** Create a SBufStream preinitialized with the argument's SBuf.
111 *
112 * The supplied SBuf is not aliased: in order to retrieve the altered contents
113 * they must be fetched using the buf() class method.
114 */
115 SBufStream(SBuf aBuf): std::ostream(0), theBuffer(aBuf) {
116 rdbuf(&theBuffer); // set the buffer to now-initialized theBuffer
117 clear(); //clear badbit set by calling init(0)
118 }
119
120 /// Create an empty SBufStream
121 SBufStream(): std::ostream(0), theBuffer(SBuf()) {
122 rdbuf(&theBuffer); // set the buffer to now-initialized theBuffer
123 clear(); //clear badbit set by calling init(0)
124 }
125
126 /// Retrieve a copy of the current stream status
127 SBuf buf() {
128 return theBuffer.getBuf();
129 }
130
131 /// Clear the stream's backing store
132 SBufStream& clearBuf() {
133 theBuffer.clearBuf();
134 return *this;
135 }
136
137private:
138 SBufStreamBuf theBuffer;
139};
140
141#endif /* SQUID_SBUFSTREAM_H */
0142
=== added file 'src/SBufTokenizer.cc'
--- src/SBufTokenizer.cc 1970-01-01 00:00:00 +0000
+++ src/SBufTokenizer.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,68 @@
1/*
2 * SBufTokenizer.cc (C) 2008 Francesco Chemollli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#include "squid.h"
32#include "Debug.h"
33#include "SBufTokenizer.h"
34
35void SBufTokenizer::reset(const SBuf &toparse, const SBuf &delim)
36{
37 debugs(24, 4, "SBufTokenizer::reset()");
38 _toParse = toparse;
39 _delim = delim;
40 _lastToken.clear();
41 _lastDelim = 0;
42 next();
43}
44
45SBufTokenizer& SBufTokenizer::next()
46{
47 debugs(24, 7, "SBufTokenizer::next()");
48 SBuf::size_type tok;
49 tok = _toParse.find_first_of(_delim);
50 if (tok == SBuf::npos) {
51 debugs(24, 8, "SBufTokenizer::token(): separator not found");
52 _lastToken = _toParse;
53 _toParse.clear();
54 _lastDelim = '\0';
55 } else {
56 _lastDelim = _toParse[tok];
57 _lastToken = _toParse.consume(tok);
58 _toParse.consume(1); //the separator
59 }
60 return *this;
61}
62
63bool SBufTokenizer::atEnd() const
64{
65 debugs(24, 8, "result: " << (_toParse.length() == 0));
66 return (_toParse.length() == 0 && _lastToken.length() == 0);
67}
68
069
=== added file 'src/SBufTokenizer.h'
--- src/SBufTokenizer.h 1970-01-01 00:00:00 +0000
+++ src/SBufTokenizer.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,149 @@
1/*
2 * SBuTokenizer.h (C) 2008 Francesco Chemollli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#ifndef SQUID_SBUFTOKENIZER_H
32#define SQUID_SBUFTOKENIZER_H
33
34#include "SBuf.h"
35
36/**
37 * A tokenizer for SBuf
38 * example:
39 * \code
40 * SBuf toparse, sep;
41 * toparse = ...; sep = ...;
42 * for (SBufTokenizer st(toparse,sep);!st.atEnd();st.next()) {
43 * SBuf s = st.token();
44 * //...
45 * }
46 * \endcode
47 */
48class SBufTokenizer
49{
50public:
51 /** Constructor
52 *
53 * create a new SBufTokenizer to check over the contents of toparse,
54 * using any of the characters of delim as a token delimiter
55 * \param toparse the SBuf to be tokenized
56 * \param delim the token separator. It's a SBuf which is interpreted
57 * as a bag of chars, whose each is a possible token delimiter.
58 */
59 SBufTokenizer(const SBuf &toparse, const SBuf &delim)
60 {
61 reset(toparse,delim);
62 }
63
64 /** reset the Tokenizer
65 *
66 * reset the SBufTokenizer with a new SBuf to be parsed and a new
67 * delimiter set.
68 * \param toparse the SBuf to be tokenized
69 * \param delim the token separator. It's a SBuf which is interpreted
70 */
71 void reset(const SBuf &toparse, const SBuf &delim);
72
73 /** set a new delimiter set
74 *
75 * \param newdelim the token separator.
76 */
77 void setDelimiter(const SBuf &newdelim)
78 {
79 _delim = newdelim;
80 }
81
82 /** retrieve the current delimiter set
83 */
84 SBuf getDelimiter() const
85 {
86 return _delim;
87 }
88
89 /** Extract the next Token
90 *
91 * strtok()-equivalent.
92 * Will extract a token from the beginning of the SBuf, containing
93 * all chars up to the first occurrence of any of the chars in
94 * <i>delim</i> or end-of-SBuf if no delimiter can be found.
95 * The tokenized SBuf is modified, by removing its head
96 * the to-be-returned token AND the delimiter.
97 */
98 SBufTokenizer& next();
99
100 /** get last delimiter found
101 *
102 ** returns the delimiter which terminated the last-matched token
103 * If no token() has not been extracted or we are at the end of the
104 * SBuf to be tokenized, the result is undefined
105 */
106 char separator() const
107 {
108 return _lastDelim;
109 }
110
111 /** Move to the next token, specify new delimiter
112 *
113 * Move to the next token, and a new delimiter to parse it
114 */
115 SBufTokenizer &next(const SBuf &newdelim)
116 {
117 setDelimiter(newdelim);
118 return next();
119 }
120
121 /** Extract a token
122 *
123 * Extract a token from the SBuf. May be called repeatedly, in that case
124 * will return each time a fresh copy of the same token.
125 */
126 SBuf token() const
127 {
128 return _lastToken;
129 }
130
131 /** check whether we are done
132 *
133 * \retval true if we are at the SBuf to be parsed.
134 */
135 bool atEnd() const;
136
137private:
138 SBuf _toParse; /// the still-unparsed part of the buffer to parse
139 SBuf _lastToken;/// the last returned token
140 char _lastDelim;/// the delimiter last matched
141 SBuf _delim; /// a SBuf containing the delimiter characters
142
143 SBuf::size_type pbrk() const
144 {
145 return _toParse.find_first_of(_delim);
146 }
147};
148
149#endif
0150
=== added file 'src/SBufUtil.cc'
--- src/SBufUtil.cc 1970-01-01 00:00:00 +0000
+++ src/SBufUtil.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,64 @@
1/*
2 * SBufUtil.cc (C) 2009 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#include "squid.h"
32#include "SBufUtil.h"
33
34SBuf
35SBufListJoin(SBufList &list, const SBuf &separator)
36{
37 SBufList::iterator i;
38 SBuf::size_type sz = 0;
39 //first thing: calculate the length to reserveSpace
40 for (i = list.begin(); i!= list.end(); ++i)
41 sz += (*i).length()+separator.length();
42 SBuf rv;
43 rv.reserveSpace(sz);
44 i = list.begin();
45 if (i != list.end())
46 rv.append(*i);
47 ++i;
48 if (i != list.end()) {
49 for (; i!= list.end(); i++) {
50 rv.append(separator);
51 rv.append(*i);
52 }
53 }
54 return rv;
55}
56
57SBuf
58BaseName(const SBuf &s, char separator)
59{
60 SBuf::size_type pos = s.rfind(separator);
61 if (pos == SBuf::npos)
62 return s;
63 return s.substr(pos+1);
64}
065
=== added file 'src/SBufUtil.h'
--- src/SBufUtil.h 1970-01-01 00:00:00 +0000
+++ src/SBufUtil.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,51 @@
1/*
2 * SBufUtil.h (C) 2009 Francesco Chemolli <kinkie@squid-cache.org>
3 *
4 * SQUID Web Proxy Cache http://www.squid-cache.org/
5 * ----------------------------------------------------------
6 *
7 * Squid is the result of efforts by numerous individuals from
8 * the Internet community; see the CONTRIBUTORS file for full
9 * details. Many organizations have provided support for Squid's
10 * development; see the SPONSORS file for full details. Squid is
11 * Copyrighted (C) 2001 by the Regents of the University of
12 * California; see the COPYRIGHT file for full details. Squid
13 * incorporates software developed and/or copyrighted by other
14 * sources; see the CREDITS file for full details.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
29 */
30
31#ifndef SQUID_SBUFUTIL_H
32#define SQUID_SBUFUTIL_H
33
34#include "SBuf.h"
35#include "SBufList.h"
36#include "SBufTokenizer.h"
37
38/** join a SBufList into a SBuf using the supplied separator.
39 */
40SBuf SBufListJoin(SBufList &list, const SBuf &separator);
41
42/** Obtain the basename of a file.
43 *
44 * Returns the part of a SBuf after the last occurrence of the specified delimiter.
45 * If the delimiter is not found, return the whole SBuf
46 * \param s the SBuf to be analyzed
47 * \param separator the separating character (defaults to '/')
48 */
49SBuf BaseName(const SBuf &s, char separator = '/');
50
51#endif /* SQUID_SBUFUTIL_H */
052
=== modified file 'src/SquidString.h'
--- src/SquidString.h 2012-09-22 10:56:48 +0000
+++ src/SquidString.h 2013-07-04 15:56:30 +0000
@@ -43,40 +43,6 @@
43#define SQUIDSTRINGPRINT(s) (s).psize(),(s).rawBuf()43#define SQUIDSTRINGPRINT(s) (s).psize(),(s).rawBuf()
44#endif /* SQUIDSTRINGPH */44#endif /* SQUIDSTRINGPH */
4545
46#define DEBUGSTRINGS 0
47#if DEBUGSTRINGS
48#include "splay.h"
49
50class String;
51
52class StringRegistry
53{
54
55public:
56 static StringRegistry &Instance();
57
58 void add(String const *);
59
60 StringRegistry();
61
62 void remove(String const *);
63
64private:
65 static OBJH Stat;
66
67 static StringRegistry Instance_;
68
69 static SplayNode<String const *>::SPLAYWALKEE Stater;
70
71 Splay<String const *> entries;
72
73 bool registered;
74
75};
76
77class StoreEntry;
78#endif
79
80class String46class String
81{47{
8248
@@ -150,10 +116,6 @@
150116
151 _SQUID_INLINE_ void cut(size_type newLength);117 _SQUID_INLINE_ void cut(size_type newLength);
152118
153#if DEBUGSTRINGS
154 void stat(StoreEntry *) const;
155#endif
156
157private:119private:
158 void allocAndFill(const char *str, int len);120 void allocAndFill(const char *str, int len);
159 void allocBuffer(size_type sz);121 void allocBuffer(size_type sz);
160122
=== modified file 'src/StrList.h'
--- src/StrList.h 2012-09-21 14:57:30 +0000
+++ src/StrList.h 2013-07-04 15:56:30 +0000
@@ -1,7 +1,4 @@
1/*1/*
2 * DEBUG: section 66 HTTP Header Tools
3 * AUTHOR: Alex Rousskov
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/2 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------3 * ----------------------------------------------------------
7 *4 *
@@ -28,16 +25,77 @@
28 * along with this program; if not, write to the Free Software25 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *27 *
28 * Copyright (c) 2010 Francesco Chemolli <kinkie@squid-cache.org>
31 */29 */
3230
33#ifndef SQUID_STRLIST_H_31#ifndef STRLIST_H_
34#define SQUID_STRLIST_H_32#define STRLIST_H_
3533
36class String;34#include "SBufList.h"
35#include "SBufUtil.h"
36#include "SquidString.h"
37#include "protos.h"
3738
38void strListAdd(String * str, const char *item, char del);39void strListAdd(String * str, const char *item, char del);
39int strListIsMember(const String * str, const char *item, char del);40int strListIsMember(const String * str, const char *item, char del);
40int strListIsSubstr(const String * list, const char *s, char del);41int strListIsSubstr(const String * list, const char *s, char del);
41int strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos);42int strListGetItem(const String * str, char del, const char **item, int *ilen, const char **pos);
4243
43#endif /* SQUID_STRLIST_H_ */44#if 0
45/* incomplete code, do not use!
46 * It is meant to eventually turn the strList* functions into proper object
47 * manipulators.
48 * TODO: finish and use it.
49 */
50class StrList
51{
52public:
53 StrList() { }
54 explicit StrList(const SBufList &s) {
55 const SBuf sep(", ");
56 SBuf b=SBufListJoin(s,sep);
57 data_=b.toString();
58 }
59 explicit StrList(const char *s) {
60 data_=s;
61 }
62 explicit StrList (const SBuf &s) {
63 data_=s.toString();
64 }
65 ~StrList() { data_.clean(); };
66 void StrListAdd(const char *item, char del) {
67 strListAdd(&data_,item,del);
68 }
69 int StrListIsMember(const char *item, char del=',') {
70 return strListIsMember(&data_,item,del);
71 }
72 int StrListIsSubstr(const char *s, char del) {
73 return strListIsSubstr(&data_, s, del);
74 }
75 int StrListGetItem(char del, const char **item, int *ilen, const char **pos) {
76 return strListGetItem(&data_, del, item, ilen, pos);
77 }
78 String StrListGetString() {
79 return data_;
80 }
81 void clear() {
82 data_.clean();
83 }
84 void append(char const *buf, int len) {
85 data_.append(buf,len);
86 }
87 void append(char const *buf) {
88 data_.append(buf);
89 }
90 String::size_type size() const {
91 return data_.size();
92 }
93
94private:
95 String data_;
96 SBufList ndata;
97};
98
99#endif
100
101#endif /* STRLIST_H_ */
44102
=== modified file 'src/icmp/Makefile.am'
--- src/icmp/Makefile.am 2010-11-01 05:44:28 +0000
+++ src/icmp/Makefile.am 2013-07-04 15:56:30 +0000
@@ -22,6 +22,25 @@
2222
23noinst_LTLIBRARIES = libicmp-core.la libicmp.la23noinst_LTLIBRARIES = libicmp-core.la libicmp.la
2424
25SBUF_SOURCE= \
26 $(top_srcdir)/src/SBuf.h \
27 $(top_srcdir)/src/SBuf.cc \
28 $(top_srcdir)/src/MemBlob.h \
29 $(top_srcdir)/src/MemBlob.cc \
30 $(top_srcdir)/src/OutOfBoundsException.h \
31 $(top_srcdir)/src/SBufExceptions.h \
32 $(top_srcdir)/src/SBufExceptions.cc \
33 $(top_srcdir)/src/SBufTokenizer.h \
34 $(top_srcdir)/src/SBufTokenizer.cc \
35 $(top_srcdir)/src/SBufList.h \
36 $(top_srcdir)/src/SBufList.cc \
37 $(top_srcdir)/src/SBufUtil.h \
38 $(top_srcdir)/src/SBufUtil.cc \
39 $(top_srcdir)/src/String.cc \
40 $(top_srcdir)/src/SquidString.h \
41 $(top_srcdir)/src/base/TextException.h \
42 $(top_srcdir)/src/base/TextException.cc
43
25# ICMP API definition ...44# ICMP API definition ...
26libicmp_core_la_SOURCES = \45libicmp_core_la_SOURCES = \
27 Icmp.h \46 Icmp.h \
2847
=== added file 'src/tests/SBufFindTest.cc'
--- src/tests/SBufFindTest.cc 1970-01-01 00:00:00 +0000
+++ src/tests/SBufFindTest.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,418 @@
1#include "squid.h"
2#include "SBufFindTest.h"
3#include <cppunit/extensions/HelperMacros.h>
4#include <cppunit/Message.h>
5#include <limits>
6
7
8/* TODO: The whole SBufFindTest class is currently implemented as a single
9 CppUnit test case (because we do not want to register and report every one
10 of the thousands of generated test cases). Is there a better way to
11 integrate with CppUnit?
12 */
13
14
15SBufFindTest::SBufFindTest():
16 caseLimit(std::numeric_limits<int>::max()),
17 errorLimit(std::numeric_limits<int>::max()),
18 randomSeed(1),
19 hushSimilar(true),
20 maxHayLength(40),
21 thePos(0),
22 thePlacement(placeEof),
23 theStringPos(0),
24 theBareNeedlePos(0),
25 caseCount(0),
26 errorCount(0),
27 reportCount(0)
28{
29}
30
31void
32SBufFindTest::run()
33{
34 srandom(randomSeed);
35
36 for (SBuf::size_type hayLen = 0; hayLen <= maxHayLength; nextLen(hayLen, maxHayLength)) {
37 const SBuf cleanHay = RandomSBuf(hayLen);
38
39 const SBuf::size_type maxNeedleLen = hayLen + 10;
40 for (SBuf::size_type needleLen = 0; needleLen <= maxNeedleLen; nextLen(needleLen, maxNeedleLen)) {
41 theSBufNeedle = RandomSBuf(needleLen);
42
43 for (int i = 0; i < placeEof; i++) {
44 thePlacement = Placement(i);
45 placeNeedle(cleanHay);
46
47 const SBuf::size_type maxArg =
48 max(theSBufHay.length(), theSBufNeedle.length()) + 10;
49 for (thePos = 0; thePos <= maxArg; nextLen(thePos, maxArg))
50 testAllMethods();
51
52 // also test the special npos value
53 thePos = SBuf::npos;
54 testAllMethods();
55 }
56 }
57 }
58
59 if (errorCount > 0) {
60 std::cerr << "Generated SBuf test cases: " << caseCount << std::endl;
61 std::cerr << "\tfailed cases: " << errorCount << std::endl;
62 std::cerr << "\treported cases: " << reportCount << std::endl;
63 std::cerr << "Asserting because some cases failed..." << std::endl;
64 CPPUNIT_ASSERT(!SBufFindTest::errorCount);
65 }
66}
67
68/// tests SBuf::find(string needle)
69void
70SBufFindTest::testFindDefs() {
71 theFindString = theBareNeedlePos = theStringHay.find(theStringNeedle);
72 theFindSBuf = theSBufHay.find(theSBufNeedle);
73 checkResults("find");
74}
75
76/// tests SBuf::rfind(string needle)
77void
78SBufFindTest::testRFindDefs() {
79 theFindString = theBareNeedlePos = theStringHay.rfind(theStringNeedle);
80 theFindSBuf = theSBufHay.rfind(theSBufNeedle);
81 checkResults("rfind");
82}
83
84/// tests SBuf::find(string needle, pos)
85void
86SBufFindTest::testFind() {
87 theFindString = theStringHay.find(theStringNeedle, thePos);
88 theBareNeedlePos = theStringHay.find(theStringNeedle);
89 theFindSBuf = theSBufHay.find(theSBufNeedle, thePos);
90 checkResults("find");
91}
92
93/// tests SBuf::rfind(string needle, pos)
94void
95SBufFindTest::testRFind() {
96 theFindString = theStringHay.rfind(theStringNeedle, thePos);
97 theBareNeedlePos = theStringHay.rfind(theStringNeedle);
98 theFindSBuf = theSBufHay.rfind(theSBufNeedle, thePos);
99 checkResults("rfind");
100}
101
102/// tests SBuf::find(char needle)
103void
104SBufFindTest::testFindCharDefs() {
105 const char c = theStringNeedle[0];
106 theFindString = theBareNeedlePos = theStringHay.find(c);
107 theFindSBuf = theSBufHay.find(c);
108 checkResults("find");
109}
110
111/// tests SBuf::find(char needle, pos)
112void
113SBufFindTest::testFindChar() {
114 const char c = theStringNeedle[0];
115 theFindString = theStringHay.find(c, thePos);
116 theBareNeedlePos = theStringHay.find(c);
117 theFindSBuf = theSBufHay.find(c, thePos);
118 checkResults("find");
119}
120
121/// tests SBuf::rfind(char needle)
122void
123SBufFindTest::testRFindCharDefs() {
124 const char c = theStringNeedle[0];
125 theFindString = theBareNeedlePos = theStringHay.rfind(c);
126 theFindSBuf = theSBufHay.rfind(c);
127 checkResults("rfind");
128}
129
130/// tests SBuf::rfind(char needle, pos)
131void
132SBufFindTest::testRFindChar() {
133 const char c = theStringNeedle[0];
134 theFindString = theStringHay.rfind(c, thePos);
135 theBareNeedlePos = theStringHay.rfind(c);
136 theFindSBuf = theSBufHay.rfind(c, thePos);
137 checkResults("rfind");
138}
139
140/// whether the last SBuf and std::string find() results are the same
141bool
142SBufFindTest::resultsMatch() const {
143 // this method is needed because SBuf and std::string use different
144 // size_types (and npos values); comparing the result values directly
145 // would lead to bugs
146
147 if (theFindString == std::string::npos && theFindSBuf == SBuf::npos)
148 return true; // both npos
149
150 if (theFindSBuf < 0) // should not happen, treat as error
151 return false;
152
153 // now safe to cast a non-negative SBuf result
154 return theFindString == static_cast<std::string::size_type>(theFindSBuf);
155}
156
157/// called at the end of test case to update state, detect and report failures
158void
159SBufFindTest::checkResults(const char *method) {
160 ++caseCount;
161 if (!resultsMatch())
162 handleFailure(method);
163}
164
165/// helper function to convert "printable" Type to std::string
166template<typename Type>
167inline std::string
168AnyToString(const Type &value)
169{
170 std::stringstream sbuf;
171 sbuf << value;
172 return sbuf.str();
173}
174
175/// helper function to convert SBuf position to a human-friendly string
176inline std::string
177PosToString(const SBuf::size_type pos)
178{
179 return pos == SBuf::npos ? std::string("npos") : AnyToString(pos);
180}
181
182/// helper function to convert std::string position to a human-friendly string
183inline std::string
184PosToString(const std::string::size_type pos)
185{
186 return pos == std::string::npos ? std::string("npos") : AnyToString(pos);
187}
188
189/// tests each supported SBuf::*find() method using generated hay, needle, pos
190void
191SBufFindTest::testAllMethods() {
192 theStringHay = std::string(theSBufHay.rawContent(), theSBufHay.length());
193 theStringNeedle = std::string(theSBufNeedle.rawContent(), theSBufNeedle.length());
194 theBareNeedlePos = std::string::npos;
195 const std::string reportPos = PosToString(thePos);
196
197 // always test string search
198 {
199 theReportQuote = '"';
200 theReportNeedle = theStringNeedle;
201
202 theReportPos = "";
203 testFindDefs();
204 testRFindDefs();
205
206 theReportPos = reportPos;
207 testFind();
208 testRFind();
209 }
210
211 // if possible, test char search
212 if (!theStringNeedle.empty()) {
213 theReportQuote = '\'';
214 theReportNeedle = theStringNeedle[0];
215
216 theReportPos = "";
217 testFindCharDefs();
218 testRFindCharDefs();
219
220 theReportPos = reportPos;
221 testFindChar();
222 testRFindChar();
223 }
224}
225
226/// helper function to format a length-based key (part of case category string)
227inline std::string
228lengthKey(const std::string &str)
229{
230 if (str.length() == 0)
231 return "0";
232 if (str.length() == 1)
233 return "1";
234 return "N";
235}
236
237/// formats position key (part of the case category string)
238std::string
239SBufFindTest::posKey() const
240{
241 // the search position does not matter if needle is not in hay
242 if (theBareNeedlePos == std::string::npos)
243 return std::string();
244
245 if (thePos == SBuf::npos)
246 return ",npos";
247
248 if (thePos < 0)
249 return ",posN"; // negative
250
251 // we know Pos is not negative or special; avoid signed/unsigned warnings
252 const std::string::size_type pos =
253 static_cast<std::string::size_type>(thePos);
254
255 if (pos < theBareNeedlePos)
256 return ",posL"; // to the Left of the needle
257 if (pos == theBareNeedlePos)
258 return ",posB"; // Beginning of the needle
259 if (pos < theBareNeedlePos + theStringNeedle.length())
260 return ",posM"; // in the Middle of the needle
261 if (pos == theBareNeedlePos + theStringNeedle.length())
262 return ",posE"; // at the End of the needle
263 if (pos < theStringHay.length())
264 return ",posR"; // to the Right of the needle
265 return ",posP"; // past the hay
266}
267
268/// formats placement key (part of the case category string)
269std::string
270SBufFindTest::placementKey() const
271{
272 // Ignore thePlacement because theBareNeedlePos covers it better: we may
273 // try to place the needle somewhere, but hay limits the actual placement.
274
275 // the placent does not matter if needle is not in hay
276 if (theBareNeedlePos == std::string::npos)
277 return std::string();
278
279 if (theBareNeedlePos == 0)
280 return "@B"; // at the beggining of the hay string
281 if (theBareNeedlePos == theStringHay.length()-theStringNeedle.length())
282 return "@E"; // at the end of the hay string
283 return "@M"; // in the "middle" of the hay string
284}
285
286/// called when a test case fails; counts and possibly reports the failure
287void
288SBufFindTest::handleFailure(const char *method) {
289 // line break after "........." printed for previous tests
290 if (!errorCount)
291 std::cerr << std::endl;
292
293 ++errorCount;
294
295 if (errorCount > errorLimit) {
296 std::cerr << "Will stop generating SBuf test cases because the " <<
297 "number of failed ones is over the limit: " << errorCount <<
298 " (after " << caseCount << " test cases)" << std::endl;
299 CPPUNIT_ASSERT(errorCount <= errorLimit);
300 /* NOTREACHED */
301 }
302
303 // format test case category; category allows us to hush failure reports
304 // for already seen categories with failed cases (to reduce output noise)
305 std::string category = "hay" + lengthKey(theStringHay) +
306 "." + method + '(';
307 if (theReportQuote == '"')
308 category += "needle" + lengthKey(theStringNeedle);
309 else
310 category += "char";
311 category += placementKey();
312 category += posKey();
313 category += ')';
314
315 if (hushSimilar) {
316 if (failedCats.find(category) != failedCats.end())
317 return; // do not report another similar test case failure
318 failedCats.insert(category);
319 }
320
321 std::string reportPos = theReportPos;
322 if (!reportPos.empty())
323 reportPos = ", " + reportPos;
324
325 std::cerr << "case" << caseCount << ": " <<
326 "SBuf(\"" << theStringHay << "\")." << method <<
327 "(" << theReportQuote << theReportNeedle << theReportQuote <<
328 reportPos << ") returns " << PosToString(theFindSBuf) <<
329 " instead of " << PosToString(theFindString) <<
330 std::endl <<
331 " std::string(\"" << theStringHay << "\")." << method <<
332 "(" << theReportQuote << theReportNeedle << theReportQuote <<
333 reportPos << ") returns " << PosToString(theFindString) <<
334 std::endl <<
335 " category: " << category << std::endl;
336
337 ++reportCount;
338}
339
340/// generates a random string of the specified length
341SBuf
342SBufFindTest::RandomSBuf(const int length) {
343 static const char characters[] =
344 "0123456789"
345 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
346 "abcdefghijklomnpqrstuvwxyz";
347 // sizeof() counts the terminating zero at the end of characters
348 // TODO: add \0 character (needs reporting adjustments to print it as \0)
349 static const size_t charCount = sizeof(characters)-1;
350
351 char buf[length];
352 for (int i = 0; i < length; ++i) {
353 const unsigned int pos = random() % charCount;
354 assert(pos < sizeof(characters));
355 assert(characters[pos] > 32);
356 buf[i] = characters[random() % charCount];
357 }
358
359 return SBuf(buf, 0, length);
360}
361
362/// increments len to quickly cover [0, max] range, slowing down in risky areas
363/// jumps to max+1 if caseLimit is reached
364void
365SBufFindTest::nextLen(int &len, const int max) {
366 assert(len <= max);
367
368 if (caseCount >= caseLimit)
369 len = max+1; // avoid future test cases
370 else if (len <= 10)
371 ++len; // move slowly at the beginning of the [0,max] range
372 else if (len >= max - 10)
373 ++len; // move slowly at the end of the [0,max] range
374 else {
375 // move fast in the middle of the [0,max] range
376 len += len/10 + 1;
377
378 // but do not overshoot the interesting area at the end of the range
379 if (len > max - 10)
380 len = max - 10;
381 }
382}
383
384/// Places the needle into the hay using cleanHay as a starting point.
385void
386SBufFindTest::placeNeedle(const SBuf &cleanHay) {
387 // For simplicity, we do not overwrite clean hay characters but use them as
388 // needle suffix and/or prefix. Should not matter since hay length varies?
389
390 // TODO: support two needles per hay (explicitly)
391 // TODO: better handle cases where clean hay already contains needle
392 switch (thePlacement)
393 {
394 case placeBeginning:
395 theSBufHay.assign(theSBufNeedle).append(cleanHay);
396 break;
397
398 case placeMiddle:
399 {
400 const SBuf firstHalf = cleanHay.substr(0, cleanHay.length()/2);
401 const SBuf secondHalf = cleanHay.substr(cleanHay.length()/2);
402 theSBufHay.assign(firstHalf).append(theSBufNeedle).append(secondHalf);
403 break;
404 }
405
406 case placeEnd:
407 theSBufHay.assign(cleanHay).append(theSBufNeedle);
408 break;
409
410 case placeNowhere:
411 theSBufHay.assign(cleanHay);
412 break;
413
414 case placeEof:
415 assert(false); // should not happen
416 break;
417 }
418}
0419
=== added file 'src/tests/SBufFindTest.h'
--- src/tests/SBufFindTest.h 1970-01-01 00:00:00 +0000
+++ src/tests/SBufFindTest.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,85 @@
1#ifndef SQUID_SRC_TEST_SBUFFINDTEST_H
2#define SQUID_SRC_TEST_SBUFFINDTEST_H
3
4#include "SBuf.h"
5
6#if HAVE_STRING
7#include <string>
8#endif
9#include <set>
10
11/// Generates and executes a [configurable] large number of SBuf::*find()
12/// test cases using random strings. Reports detected failures.
13class SBufFindTest
14{
15public:
16 SBufFindTest();
17
18 void run(); ///< generates and executes cases using configuration params
19
20 /* test configuration parameters; can be optionally set before run() */
21 int caseLimit; ///< approximate caseCount limit
22 int errorLimit; ///< errorCount limit
23 unsigned int randomSeed; ///< pseudo-random sequence choice
24 /// whether to report only one failed test case per "category"
25 bool hushSimilar;
26 /// approximate maximum generated hay string length
27 SBuf::size_type maxHayLength;
28
29 /// Supported algorithms for placing needle in the hay.
30 typedef enum { placeBeginning, placeMiddle, placeEnd, placeNowhere,
31 placeEof } Placement; // placeLast marker must terminate
32protected:
33
34 static SBuf RandomSBuf(const int length);
35 void nextLen(int &len, const int max);
36 void placeNeedle(const SBuf &cleanHay);
37
38 void testAllMethods();
39 void testFindDefs();
40 void testFind();
41 void testRFindDefs();
42 void testRFind();
43 void testFindCharDefs();
44 void testFindChar();
45 void testRFindCharDefs();
46 void testRFindChar();
47
48 std::string posKey() const;
49 std::string placementKey() const;
50
51 bool resultsMatch() const;
52 void checkResults(const char *method);
53 void handleFailure(const char *method);
54
55private:
56 /* test case parameters */
57 SBuf theSBufHay; ///< the string to be searched
58 SBuf theSBufNeedle; ///< the string to be found
59 SBuf::size_type thePos; ///< search position limit
60 Placement thePlacement; ///< where in the hay the needle is placed
61 std::string::size_type theStringPos; ///< thePos converted to std::string::size_type
62 std::string theStringHay; ///< theHay converted to std::string
63 std::string theStringNeedle; ///< theNeedle converted to std::string
64
65 /// needle pos w/o thePos restrictions; used for case categorization
66 std::string::size_type theBareNeedlePos;
67
68 /* test case results */
69 std::string::size_type theFindString;
70 SBuf::size_type theFindSBuf;
71 std::string theReportFunc;
72 std::string theReportNeedle;
73 std::string theReportPos;
74 char theReportQuote;
75
76 /* test progress indicators */
77 int caseCount; ///< cases executed so far
78 int errorCount; ///< total number of failed test cases so far
79 int reportCount; ///< total number of test cases reported so far
80 std::set<std::string> failedCats; ///< reported failed categories
81};
82
83typedef SBufFindTest::Placement Placement;
84
85#endif
086
=== added file 'src/tests/testSBuf.cc'
--- src/tests/testSBuf.cc 1970-01-01 00:00:00 +0000
+++ src/tests/testSBuf.cc 2013-07-04 15:56:30 +0000
@@ -0,0 +1,603 @@
1#include "squid.h"
2#include "Mem.h"
3#include "SBuf.h"
4#include "SBufList.h"
5#include "SBufStream.h"
6#include "SBufTokenizer.h"
7#include "SBufUtil.h"
8#include "SquidString.h"
9#include "testSBuf.h"
10#include "SBufFindTest.h"
11
12#include <iostream>
13#include <stdexcept>
14
15CPPUNIT_TEST_SUITE_REGISTRATION( testSBuf );
16
17/* let this test link sanely */
18#include "event.h"
19#include "MemObject.h"
20void
21eventAdd(const char *name, EVH * func, void *arg, double when, int, bool cbdata)
22{}
23int64_t
24MemObject::endOffset() const
25{ return 0; }
26/* end of stubs */
27
28// test string
29static char fox[]="The quick brown fox jumped over the lazy dog";
30static char fox1[]="The quick brown fox ";
31static char fox2[]="jumped over the lazy dog";
32
33// TEST: globals variables (default/empty and with contents) are
34// created outside and before any unit tests and memory subsystem
35// initialization. Check for correct constructor operation.
36SBuf empty_sbuf;
37SBuf literal("The quick brown fox jumped over the lazy dog");
38
39void
40testSBuf::testSBufConstructDestruct()
41{
42 /* NOTE: Do not initialize memory here because we need
43 * to test correct operation before and after Mem::Init
44 */
45
46 // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test
47 // is working on local-scope variables constructed fresh for the test, and destructed when
48 // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc)
49
50 // TEST: default constructor (implicit destructor non-crash test)
51 // test accessors on empty SBuf.
52 {
53 SBuf s1;
54 CPPUNIT_ASSERT_EQUAL(s1.length(),0);
55 CPPUNIT_ASSERT_EQUAL(s1,SBuf(""));
56 CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf);
57 CPPUNIT_ASSERT(0==strcmp("",s1.c_str()));
58 }
59
60 // TEST: copy-construct NULL string (implicit destructor non-crash test)
61 {
62 SBuf s1(NULL);
63 CPPUNIT_ASSERT_EQUAL(s1.length(),0);
64 CPPUNIT_ASSERT_EQUAL(s1,SBuf(""));
65 CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf);
66 CPPUNIT_ASSERT(0==strcmp("",s1.c_str()));
67 }
68
69 // TEST: copy-construct empty string (implicit destructor non-crash test)
70 {
71 SBuf s1("");
72 CPPUNIT_ASSERT_EQUAL(s1.length(),0);
73 CPPUNIT_ASSERT_EQUAL(s1,SBuf(""));
74 CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf);
75 CPPUNIT_ASSERT(0==strcmp("",s1.c_str()));
76 }
77
78 // TEST: copy-construct from a SBuf
79 {
80 SBuf s1(empty_sbuf);
81 CPPUNIT_ASSERT_EQUAL(s1.length(),0);
82 CPPUNIT_ASSERT_EQUAL(s1,SBuf(""));
83 CPPUNIT_ASSERT_EQUAL(s1,empty_sbuf);
84 CPPUNIT_ASSERT(0==strcmp("",s1.c_str()));
85
86 SBuf s5(literal);
87 CPPUNIT_ASSERT_EQUAL(s5,literal);
88 SBuf s6(fox);
89 CPPUNIT_ASSERT_EQUAL(s6,literal);
90 // XXX: other state checks. expected result of calling any state accessor on s4 ?
91 }
92
93 // TEST: check that COW doesn't happen upon copy-construction
94 {
95 SBuf s1(empty_sbuf), s2(s1);
96 CPPUNIT_ASSERT_EQUAL(s1.rawContent(), s2.rawContent());
97 SBuf s3(literal), s4(literal);
98 CPPUNIT_ASSERT_EQUAL(s3.rawContent(), s4.rawContent());
99 }
100
101 // TEST: sub-string copy
102 {
103 SBuf s1=SBuf(fox,4), s2(fox);
104 SBuf s3=s2.substr(4,s2.length()); //n is out-of-bounds
105 CPPUNIT_ASSERT_EQUAL(s1,s3);
106 SBuf s4=SBuf(fox,0,4);
107 s3=s2.substr(0,4);
108 CPPUNIT_ASSERT_EQUAL(s4,s3);
109 }
110
111 // TEST: go via SquidString adapters.
112 {
113 String str(fox);
114 SBuf s1(str);
115 CPPUNIT_ASSERT_EQUAL(s1,literal);
116 }
117}
118
119void
120testSBuf::testSBufConstructDestructAfterMemInit()
121{
122 Mem::Init();
123 testSBufConstructDestruct();
124
125// XXX: or perhapse ...
126// repeat all of the tests inside testSBufConstructDestructBeforeMemInit()
127// with additional checks on Mem usage stats after each operation ??
128}
129
130void
131testSBuf::testEqualityTest()
132{
133 SBuf s1(fox),s2(fox);
134 CPPUNIT_ASSERT_EQUAL(s1,s1); //self-equality
135 CPPUNIT_ASSERT_EQUAL(s1,s2); //same contents
136 s2.assign("The quick brown fox jumped over the lazy doe");
137 CPPUNIT_ASSERT(!(s1 == s2)); //same length, different contents
138 s2.assign("foo");
139 CPPUNIT_ASSERT(!(s1 == s2)); //different length and contents
140 CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
141 s2.clear();
142 CPPUNIT_ASSERT(!(s1 == s2)); //null and not-null
143 CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
144 s1.clear();
145 CPPUNIT_ASSERT_EQUAL(s1,s2); //null and null
146}
147
148void
149testSBuf::testAppendSBuf()
150{
151 SBuf s1(fox1),s2(fox2);
152 s1.append(s2);
153 CPPUNIT_ASSERT_EQUAL(s1,literal);
154}
155
156void
157testSBuf::testPrintf()
158{
159 SBuf s1,s2;
160 s1.Printf("%s:%d:%03.3f","fox",10,12345.67);
161 s2.assign("fox:10:12345.670");
162 CPPUNIT_ASSERT_EQUAL(s1,s2);
163}
164
165void
166testSBuf::testAppendCString()
167{
168 SBuf s1(fox1);
169 s1.append(fox2);
170 CPPUNIT_ASSERT_EQUAL(s1,literal);
171}
172
173void
174testSBuf::testAppendStdString()
175{
176 SBuf s1(fox1);
177 std::string str(fox2);
178 s1.append(str);
179 CPPUNIT_ASSERT_EQUAL(s1,literal);
180}
181
182void
183testSBuf::testAppendf()
184{
185 SBuf s1,s2;
186 s1.appendf("%s:%d:%03.2f",fox,1234,1234.56);
187 s2.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
188 CPPUNIT_ASSERT_EQUAL(s1,s2);
189}
190
191void
192testSBuf::testDumpStats()
193{
194 SBuf::GetStats().dump(std::cout);
195 MemBlob::GetStats().dump(std::cout);
196 std::cout << "sizeof(SBuf): " << sizeof(SBuf) << std::endl;
197 std::cout << "sizeof(MemBlob): " << sizeof(MemBlob) << std::endl;
198}
199
200void
201testSBuf::testSubscriptOp()
202{
203 SBuf chg(literal);
204 CPPUNIT_ASSERT_EQUAL(chg[5],'u');
205 chg.setAt(5,'e');
206 CPPUNIT_ASSERT_EQUAL(literal[5],'u');
207 CPPUNIT_ASSERT_EQUAL(chg[5],'e');
208// std::cout << chg << std::endl << empty_sbuf << std::endl ;
209}
210
211// note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and
212// so the test can't be properly completed.
213void
214testSBuf::testSubscriptOpFail()
215{
216 char c;
217 c=literal.at(1234); //out of bounds
218 //notreached
219 std::cout << c << std::endl;
220}
221
222static int sign(int v)
223{
224 if (v < 0)
225 return -1;
226 if (v>0)
227 return 1;
228 return 0;
229}
230
231void
232testSBuf::testComparisons()
233{
234 //same length
235 SBuf s1("foo"),s2("foe");
236 CPPUNIT_ASSERT(s1.cmp(s2)>0);
237 CPPUNIT_ASSERT(s1.casecmp(s2)>0);
238 CPPUNIT_ASSERT(s2.cmp(s1)<0);
239 CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
240 CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2,2));
241 CPPUNIT_ASSERT(s1 > s2);
242 CPPUNIT_ASSERT(s2 < s1);
243 CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
244 //different lengths
245 s1.assign("foo");
246 s2.assign("foof");
247 CPPUNIT_ASSERT(s1.cmp(s2)<0);
248 CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
249 CPPUNIT_ASSERT(s1 < s2);
250 // specifying the max-length and overhanging size
251 CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").casecmp(SBuf("foo"), 5));
252 // case-insensive comaprison
253 s1 = "foo";
254 s2 = "fOo";
255 CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2));
256 CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2,2));
257 // \0-clenliness test
258 s1.assign("f\0oo",0,4);
259 s2.assign("f\0Oo",0,4);
260 CPPUNIT_ASSERT_EQUAL(1,s1.cmp(s2));
261 CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2));
262 CPPUNIT_ASSERT_EQUAL(0,s1.casecmp(s2,3));
263}
264
265void
266testSBuf::testConsume()
267{
268 SBuf s1(literal),s2,s3;
269 s2=s1.consume(4);
270 s3.assign("The ");
271 CPPUNIT_ASSERT_EQUAL(s2,s3);
272 s3.assign("quick brown fox jumped over the lazy dog");
273 CPPUNIT_ASSERT_EQUAL(s1,s3);
274 s1.consume(40);
275 CPPUNIT_ASSERT_EQUAL(s1,SBuf());
276}
277
278void
279testSBuf::testRawContent()
280{
281 SBuf s1(literal);
282 SBuf s2(s1);
283 s2.append("foo");
284 const char *foo;
285 foo = s1.rawContent();
286 CPPUNIT_ASSERT(strncmp(fox,foo,s1.length())==0);
287 foo = s1.c_str();
288 CPPUNIT_ASSERT(!strcmp(fox,foo));
289}
290
291void
292testSBuf::testRawSpace()
293{
294 SBuf s1(literal);
295 SBuf s2(fox1);
296 char *rb=s2.rawSpace(strlen(fox2)+1);
297 strcat(rb,fox2);
298 CPPUNIT_ASSERT_EQUAL(s1,s2);
299}
300
301void
302testSBuf::testChop()
303{
304 SBuf s1(literal),s2;
305 s1.chop(4,5);
306 s2.assign("quick");
307 CPPUNIT_ASSERT_EQUAL(s1,s2);
308 s1=literal;
309 s2.clear();
310 s1.chop(5,0);
311 CPPUNIT_ASSERT_EQUAL(s1,s2);
312}
313
314void
315testSBuf::testChomp()
316{
317 SBuf s1("complete string");
318 SBuf s2(s1);
319 s2.trim(SBuf(" ,"));
320 CPPUNIT_ASSERT_EQUAL(s1,s2);
321 s2.assign(" complete string ,");
322 s2.trim(SBuf(" ,"));
323 CPPUNIT_ASSERT_EQUAL(s1,s2);
324 s1.assign(", complete string ,");
325 s2=s1;
326 s2.trim(SBuf(" "));
327 CPPUNIT_ASSERT_EQUAL(s1,s2);
328}
329
330void
331testSBuf::testSubstr()
332{
333 SBuf s1(literal),s2,s3;
334 s2=s1.substr(4,5);
335 s3.assign("quick");
336 CPPUNIT_ASSERT_EQUAL(s2,s3);
337 s1.chop(4,5);
338 CPPUNIT_ASSERT_EQUAL(s1,s2);
339}
340
341void
342testSBuf::testFindChar()
343{
344 const char *alphabet="abcdefghijklmnopqrstuvwxyz";
345 SBuf s1(alphabet);
346 SBuf::size_type idx;
347 idx=s1.find('d');
348 CPPUNIT_ASSERT(idx == 3);
349 CPPUNIT_ASSERT(s1[idx]=='d');
350 idx=s1.find(' '); //fails
351 CPPUNIT_ASSERT(idx==SBuf::npos);
352 idx=s1.find('e',5);
353 CPPUNIT_ASSERT(idx==SBuf::npos);
354 idx=s1.rfind('x',s1.length()-4);
355 CPPUNIT_ASSERT(idx==SBuf::npos);
356}
357
358void
359testSBuf::testFindSBuf()
360{
361 SBuf haystack(literal),afox("fox"),foobar("foobar"),foe("foe"), dog("dog");
362 SBuf toolong(literal), g;
363 //very long string matching at the end
364 toolong.append(literal).append(literal).append(literal).append(literal);
365 SBuf::size_type idx;
366 idx=haystack.find(afox);
367 CPPUNIT_ASSERT_EQUAL(16,idx);
368 idx=haystack.find(foobar); //fails
369 CPPUNIT_ASSERT(idx==SBuf::npos);
370 idx=haystack.find(foe); //fails
371 CPPUNIT_ASSERT(idx==SBuf::npos);
372 idx=haystack.find(foe);
373 CPPUNIT_ASSERT(idx==SBuf::npos);
374 idx=haystack.find(dog);
375 CPPUNIT_ASSERT_EQUAL(haystack.length()-dog.length(),idx);
376 dog.append("foo");
377 idx=haystack.find(dog);
378 CPPUNIT_ASSERT(idx==SBuf::npos);
379 idx=haystack.find(toolong);
380 CPPUNIT_ASSERT(SBuf::npos==idx); //consistent with std::string
381 g="g"; //match at the last char
382 idx=haystack.find(g);
383 CPPUNIT_ASSERT_EQUAL(43,idx);
384 CPPUNIT_ASSERT_EQUAL('g',haystack[idx]);
385}
386
387void
388testSBuf::testRFindChar()
389{
390 SBuf s1(literal);
391 SBuf::size_type idx;
392 idx=s1.rfind(' ');
393 CPPUNIT_ASSERT_EQUAL(40,idx);
394 CPPUNIT_ASSERT_EQUAL(' ',s1[idx]);
395}
396
397void
398testSBuf::testRFindSBuf()
399{
400 SBuf haystack(literal),afox("fox");
401 SBuf goobar("goobar");
402 SBuf::size_type idx;
403
404 // corner case: search for a zero-length SBuf
405 idx=haystack.rfind(SBuf(""));
406 CPPUNIT_ASSERT_EQUAL(haystack.length(),idx);
407
408 // corner case: search for a needle longer than the haystack
409 idx=afox.rfind(SBuf(" "));
410 CPPUNIT_ASSERT(idx==SBuf::npos);
411
412 idx=haystack.rfind(SBuf("fox"));
413 CPPUNIT_ASSERT_EQUAL(16,idx);
414
415 // needle not found, no match for first char
416 idx=goobar.rfind(SBuf("foo"));
417 CPPUNIT_ASSERT(idx==SBuf::npos);
418
419 // needle not found, match for first char but no match for SBuf
420 idx=haystack.rfind(SBuf("foe"));
421 CPPUNIT_ASSERT(idx==SBuf::npos);
422
423 SBuf g("g"); //match at the last char
424 idx=haystack.rfind(g);
425 CPPUNIT_ASSERT_EQUAL(43,idx);
426 CPPUNIT_ASSERT_EQUAL('g',haystack[idx]);
427
428 idx=haystack.rfind(SBuf("The"));
429 CPPUNIT_ASSERT_EQUAL(0,idx);
430
431 haystack.append("The");
432 idx=haystack.rfind(SBuf("The"));
433 CPPUNIT_ASSERT_EQUAL(44,idx);
434
435 //partial match
436 haystack="The quick brown fox";
437 SBuf needle("foxy lady");
438 idx=haystack.rfind(needle);
439 CPPUNIT_ASSERT(idx==SBuf::npos);
440}
441
442void
443testSBuf::testSBufLength()
444{
445 SBuf s(fox);
446 CPPUNIT_ASSERT((size_t)s.length()==strlen(fox));
447}
448
449void
450testSBuf::testScanf()
451{
452 SBuf s1;
453 char s[128];
454 int i;
455 float f;
456 int rv;
457 s1.assign("string , 123 , 123.50");
458 rv=s1.scanf("%s , %d , %f",s,&i,&f);
459 CPPUNIT_ASSERT(3 == rv);
460 CPPUNIT_ASSERT(0 == strcmp(s,"string"));
461 CPPUNIT_ASSERT(i == 123);
462 CPPUNIT_ASSERT(f == 123.5);
463}
464
465void testSBuf::testCopy()
466{
467 char buf[40]; //shorter than literal()
468 SBuf s(fox1),s2;
469 CPPUNIT_ASSERT(s.copy(buf,40)==s.length());
470 CPPUNIT_ASSERT(strncmp(s.rawContent(),buf,s.length())==0);
471 s=literal;
472 CPPUNIT_ASSERT(s.copy(buf,40)==40);
473 s2.assign(buf,0,40);
474 s.chop(0,40);
475 CPPUNIT_ASSERT(s==s2);
476}
477
478// XXX: please split each class into a separate unit-test .cc / even if they share a binary.
479// rule-of-thumb guideline for layering is 'one class Foo -> one Foo.cc, one Foo.cc -> one testFoo.cc'
480
481static int sbuf_tokens_number=9;
482static SBuf tokens[]={
483 SBuf("The",0,3), SBuf("quick",0,5), SBuf("brown",0,5), SBuf("fox",0,3),
484 SBuf("jumped",0,6), SBuf("over",0,4), SBuf("the",0,3), SBuf("lazy",0,4),
485 SBuf("dog",0,3)
486};
487
488void testSBuf::testSBufTokenizer()
489{
490 int j=0;
491 SBuf s;
492 for (SBufTokenizer st(literal,SBuf(" ",0,1)); !st.atEnd(); st.next()) {
493 s=st.token();
494 CPPUNIT_ASSERT(s==tokens[j]);
495 j++;
496 }
497 CPPUNIT_ASSERT(j==9);
498}
499
500void testSBuf::testStringOps()
501{
502 SBuf sng(literal),
503 ref("the quick brown fox jumped over the lazy dog");
504 sng=sng.toLower();
505 CPPUNIT_ASSERT_EQUAL(ref,sng);
506 sng=literal;
507 CPPUNIT_ASSERT_EQUAL(0,sng.compare(ref,caseInsensitive));
508}
509
510void testSBuf::testGrow()
511{
512 SBuf t;
513 t.assign("foo");
514 const char *ref=t.rawContent();
515 t.reserveCapacity(10240);
516 const char *match=t.rawContent();
517 CPPUNIT_ASSERT(match!=ref);
518 ref=match;
519 t.append(literal).append(literal).append(literal).append(literal).append(literal);
520 t.append(t).append(t).append(t).append(t).append(t);
521 CPPUNIT_ASSERT(match==ref);
522}
523
524void testSBuf::testStartsWith()
525{
526 static SBuf casebuf("THE QUICK");
527 CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1)));
528 CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1))); //too short
529 CPPUNIT_ASSERT(!literal.startsWith(SBuf(fox2))); //different contents
530
531 // case-insensitive checks
532 CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
533 casebuf=SBuf(fox1).toUpper();
534 CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
535 CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1),caseInsensitive));
536 casebuf = "tha quick";
537 CPPUNIT_ASSERT_EQUAL(false,literal.startsWith(casebuf,caseInsensitive));
538}
539
540void testSBuf::testSBufList()
541{
542 SBufList foo;
543 for (int j=0; j<sbuf_tokens_number; ++j)
544 foo.add(tokens[j]);
545 CPPUNIT_ASSERT(foo.isMember(SBuf("fox")));
546 CPPUNIT_ASSERT(foo.isMember(SBuf("Fox"),caseInsensitive));
547 CPPUNIT_ASSERT(!foo.isMember(SBuf("garble")));
548 CPPUNIT_ASSERT(foo.isPrefix(SBuf("qui")));
549 CPPUNIT_ASSERT(foo.isPrefix(SBuf("qUi"),caseInsensitive));
550 CPPUNIT_ASSERT(!foo.isPrefix(SBuf("qUa"),caseInsensitive));
551}
552
553void testSBuf::testBaseName()
554{
555 SBuf totest("/foo/bar/gazonk");
556 CPPUNIT_ASSERT_EQUAL(BaseName(totest),SBuf("gazonk"));
557 CPPUNIT_ASSERT_EQUAL(BaseName(totest,'.'),totest);
558}
559
560void testSBuf::testSBufStream()
561{
562 SBuf b("const.string, int 10 and a float 10.5");
563 SBufStream ss;
564 ss << "const.string, int " << 10 << " and a float " << 10.5;
565 SBuf o=ss.buf();
566 CPPUNIT_ASSERT_EQUAL(b,o);
567 ss.clearBuf();
568 o=ss.buf();
569 CPPUNIT_ASSERT_EQUAL(SBuf(),o);
570 SBuf f1(fox1);
571 SBufStream ss2(f1);
572 ss2 << fox2;
573 CPPUNIT_ASSERT_EQUAL(ss2.buf(),literal);
574 CPPUNIT_ASSERT_EQUAL(f1,SBuf(fox1));
575}
576
577void testSBuf::testFindFirstOf()
578{
579 SBuf haystack(literal);
580 SBuf::size_type idx;
581
582 // not found
583 idx=haystack.find_first_of(SBuf("ADHRWYP"));
584 CPPUNIT_ASSERT(idx==SBuf::npos);
585
586 // found at beginning
587 idx=haystack.find_first_of(SBuf("THANDF"));
588 CPPUNIT_ASSERT_EQUAL(0,idx);
589
590 //found at end of haystack
591 idx=haystack.find_first_of(SBuf("QWERYVg"));
592 CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
593
594 //found in the middle of haystack
595 idx=haystack.find_first_of(SBuf("QWERqYV"));
596 CPPUNIT_ASSERT_EQUAL(4,idx);
597}
598
599void testSBuf::testAutoFind()
600{
601 SBufFindTest test;
602 test.run();
603}
0604
=== added file 'src/tests/testSBuf.h'
--- src/tests/testSBuf.h 1970-01-01 00:00:00 +0000
+++ src/tests/testSBuf.h 2013-07-04 15:56:30 +0000
@@ -0,0 +1,92 @@
1#ifndef SQUID_SRC_TEST_TESTSBUF_H
2#define SQUID_SRC_TEST_TESTSBUF_H
3
4#include <cppunit/extensions/HelperMacros.h>
5
6#include "OutOfBoundsException.h"
7
8/*
9 * test the SBuf functionalities
10 */
11
12class testSBuf : public CPPUNIT_NS::TestFixture
13{
14 CPPUNIT_TEST_SUITE( testSBuf );
15 CPPUNIT_TEST( testSBufConstructDestruct );
16 CPPUNIT_TEST( testSBufConstructDestructAfterMemInit );
17 CPPUNIT_TEST( testSBufLength );
18 CPPUNIT_TEST( testEqualityTest );
19 CPPUNIT_TEST( testStartsWith );
20 CPPUNIT_TEST( testAppendSBuf );
21 CPPUNIT_TEST( testAppendCString );
22 CPPUNIT_TEST( testAppendStdString );
23 CPPUNIT_TEST( testAppendf );
24 CPPUNIT_TEST( testSubscriptOp );
25 CPPUNIT_TEST_EXCEPTION( testSubscriptOpFail , OutOfBoundsException );
26 CPPUNIT_TEST( testComparisons );
27 CPPUNIT_TEST( testConsume );
28 CPPUNIT_TEST( testRawContent );
29 //CPPUNIT_TEST( testRawSpace );
30 CPPUNIT_TEST( testChop );
31 CPPUNIT_TEST( testChomp );
32 CPPUNIT_TEST( testSubstr );
33 CPPUNIT_TEST( testFindChar );
34 CPPUNIT_TEST( testFindSBuf );
35 CPPUNIT_TEST( testRFindChar );
36 CPPUNIT_TEST( testRFindSBuf );
37 CPPUNIT_TEST( testFindFirstOf );
38 CPPUNIT_TEST( testPrintf );
39 CPPUNIT_TEST( testScanf );
40 CPPUNIT_TEST( testCopy );
41 CPPUNIT_TEST( testSBufTokenizer );
42 CPPUNIT_TEST( testStringOps );
43 CPPUNIT_TEST( testGrow );
44 CPPUNIT_TEST( testSBufList );
45 CPPUNIT_TEST( testBaseName );
46 CPPUNIT_TEST( testSBufStream );
47 CPPUNIT_TEST( testAutoFind );
48
49// CPPUNIT_TEST( testDumpStats ); //fake test, to print alloc stats
50
51 CPPUNIT_TEST_SUITE_END();
52protected:
53 void commonInit();
54 void testSBufConstructDestruct();
55 void testSBufConstructDestructAfterMemInit();
56 void testEqualityTest();
57 void testAppendSBuf();
58 void testAppendCString();
59 void testAppendStdString();
60 void testAppendf();
61 void testPrintf();
62 void testScanf();
63 void testSubscriptOp();
64 void testSubscriptOpFail();
65 void testDumpStats();
66 void testComparisons();
67 void testConsume();
68 void testRawContent();
69 void testRawSpace();
70 void testChop();
71 void testChomp();
72 void testSubstr();
73 void testTailCopy();
74 void testSBufLength();
75 void testFindChar();
76 void testFindSBuf();
77 void testRFindChar();
78 void testRFindSBuf();
79 void testSearchFail();
80 void testCopy();
81 void testSBufTokenizer();
82 void testStringOps();
83 void testGrow();
84 void testStartsWith();
85 void testSBufList();
86 void testBaseName();
87 void testSBufStream();
88 void testFindFirstOf();
89 void testAutoFind();
90};
91
92#endif

Subscribers

People subscribed via source and target branches