testSBuf.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "base/CharacterSet.h"
11 #include "base/TextException.h"
12 #include "compat/cppunit.h"
13 #include "event.h"
14 #include "HttpReply.h"
15 #include "MemObject.h"
16 #include "sbuf/Algorithms.h"
17 #include "sbuf/SBuf.h"
18 #include "sbuf/Stream.h"
19 #include "tests/SBufFindTest.h"
20 #include "unitTestMain.h"
21 
22 #include <algorithm>
23 #include <iostream>
24 #include <stdexcept>
25 #include <unordered_map>
26 
27 /*
28  * test the SBuf functionalities
29  */
30 
31 class TestSBuf : public CPPUNIT_NS::TestFixture
32 {
69  // CPPUNIT_TEST( testDumpStats ); //fake test, to print alloc stats
71 
72 protected:
73  void commonInit();
76  void testEqualityTest();
77  void testAppendSBuf();
78  void testAppendCString();
79  void testAppendStdString();
80  void testAppendf();
81  void testPrintf();
82  void testSubscriptOp();
83  void testSubscriptOpFail();
84  void testDumpStats();
85  void testComparisons();
86  void testConsume();
87  void testRawContent();
88  void testRawSpace();
89  void testChop();
90  void testChomp();
91  void testSubstr();
92  void testTailCopy();
93  void testSBufLength();
94  void testFindChar();
95  void testFindSBuf();
96  void testRFindChar();
97  void testRFindSBuf();
98  void testSearchFail();
99  void testCopy();
100  void testStringOps();
101  void testGrow();
102  void testReserve();
103  void testStartsWith();
104  void testSBufStream();
105  void testFindFirstOf();
106  void testFindFirstNotOf();
107  void testAutoFind();
108  void testStdStringOps();
109  void testIterators();
110  void testSBufHash();
111  void testStdAlgorithm();
112 };
114 
115 /* let this test link sanely */
116 void
117 eventAdd(const char *, EVH *, void *, double, int, bool)
118 {}
119 int64_t
120 MemObject::endOffset() const
121 { return 0; }
122 /* end of stubs */
123 
124 // test string
125 static const char fox[] = "The quick brown fox jumped over the lazy dog";
126 static const char fox1[] = "The quick brown fox ";
127 static const char fox2[] = "jumped over the lazy dog";
128 
129 // TEST: globals variables (default/empty and with contents) are
130 // created outside and before any unit tests and memory subsystem
131 // initialization. Check for correct constructor operation.
133 SBuf literal("The quick brown fox jumped over the lazy dog");
134 
135 void
137 {
138  /* NOTE: Do not initialize memory here because we need
139  * to test correct operation before and after Mem::Init
140  */
141 
142  // XXX: partial demo below of how to do constructor unit-test. use scope to ensure each test
143  // is working on local-scope variables constructed fresh for the test, and destructed when
144  // scope exists. use nested scopes to test destructor affects on copied data (MemBlob etc)
145 
146  // TEST: default constructor (implicit destructor non-crash test)
147  // test accessors on empty SBuf.
148  {
149  SBuf s1;
150  CPPUNIT_ASSERT_EQUAL(0U,s1.length());
151  CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
152  CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
153  CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
154  }
155 
156  // TEST: copy-construct NULL string (implicit destructor non-crash test)
157  {
158  SBuf s1(nullptr);
159  CPPUNIT_ASSERT_EQUAL(0U,s1.length());
160  CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
161  CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
162  CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
163  }
164 
165  // TEST: copy-construct empty string (implicit destructor non-crash test)
166  {
167  SBuf s1("");
168  CPPUNIT_ASSERT_EQUAL(0U,s1.length());
169  CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
170  CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
171  CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
172  }
173 
174  // TEST: copy-construct from a SBuf
175  {
176  SBuf s1(empty_sbuf);
177  CPPUNIT_ASSERT_EQUAL(0U,s1.length());
178  CPPUNIT_ASSERT_EQUAL(SBuf(""),s1);
179  CPPUNIT_ASSERT_EQUAL(empty_sbuf,s1);
180  CPPUNIT_ASSERT_EQUAL(0,strcmp("",s1.c_str()));
181 
182  SBuf s5(literal);
183  CPPUNIT_ASSERT_EQUAL(literal,s5);
184  SBuf s6(fox);
185  CPPUNIT_ASSERT_EQUAL(literal,s6);
186  // XXX: other state checks. expected result of calling any state accessor on s4 ?
187  }
188 
189  // TEST: check that COW doesn't happen upon copy-construction
190  {
191  SBuf s1(empty_sbuf), s2(s1);
192  CPPUNIT_ASSERT_EQUAL(s1.rawContent(), s2.rawContent());
193  SBuf s3(literal), s4(literal);
194  CPPUNIT_ASSERT_EQUAL(s3.rawContent(), s4.rawContent());
195  }
196 
197  // TEST: sub-string copy
198  {
199  SBuf s1=SBuf(fox+4), s2(fox);
200  SBuf s3=s2.substr(4,s2.length()); //n is out-of-bounds
201  CPPUNIT_ASSERT_EQUAL(s1,s3);
202  SBuf s4=SBuf(fox,4);
203  s3=s2.substr(0,4);
204  CPPUNIT_ASSERT_EQUAL(s4,s3);
205  }
206 
207  // TEST: go via std::string adapter.
208  {
209  std::string str(fox);
210  SBuf s1(str);
211  CPPUNIT_ASSERT_EQUAL(literal,s1);
212  }
213 }
214 
215 void
217 {
218  Mem::Init();
220 }
221 
222 void
224 {
225  SBuf s1(fox),s2(fox);
226  CPPUNIT_ASSERT_EQUAL(s1,s1); //self-equality
227  CPPUNIT_ASSERT_EQUAL(s1,s2); //same contents
228  s2.assign("The quick brown fox jumped over the lazy doe");
229  CPPUNIT_ASSERT(!(s1 == s2)); //same length, different contents
230  s2.assign("foo");
231  CPPUNIT_ASSERT(!(s1 == s2)); //different length and contents
232  CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
233  s2.clear();
234  CPPUNIT_ASSERT(!(s1 == s2)); //null and not-null
235  CPPUNIT_ASSERT(s1 != s2); //while we're ready, let's test inequality
236  s1.clear();
237  CPPUNIT_ASSERT_EQUAL(s1,s2); //null and null
238 }
239 
240 void
242 {
243  const SBuf appendix(fox1);
244  const char * const rawAppendix = appendix.rawContent();
245 
246  // check whether the optimization that prevents copying when append()ing to
247  // default-constructed SBuf actually works
248  SBuf s0;
249  s0.append(appendix);
250  CPPUNIT_ASSERT_EQUAL(s0.rawContent(), appendix.rawContent());
251  CPPUNIT_ASSERT_EQUAL(s0, appendix);
252 
253  // paranoid: check that the above code can actually detect copies
254  SBuf s1(fox1);
255  s1.append(appendix);
256  CPPUNIT_ASSERT(s1.rawContent() != appendix.rawContent());
257  CPPUNIT_ASSERT(s1 != appendix);
258  CPPUNIT_ASSERT_EQUAL(rawAppendix, appendix.rawContent());
259 }
260 
261 void
263 {
264  SBuf s1,s2;
265  s1.Printf("%s:%d:%03.3f","fox",10,12345.67);
266  s2.assign("fox:10:12345.670");
267  CPPUNIT_ASSERT_EQUAL(s1,s2);
268 }
269 
270 void
272 {
273  SBuf s1(fox1);
274  s1.append(fox2);
275  CPPUNIT_ASSERT_EQUAL(s1,literal);
276 }
277 
278 void
280 {
281  const char *alphabet="abcdefghijklmnopqrstuvwxyz";
282  {
283  SBuf alpha(alphabet), s;
284  s.append(alphabet,5).append(alphabet+5);
285  CPPUNIT_ASSERT_EQUAL(alpha,s);
286  }
287  {
288  SBuf s;
289  std::string control;
290  s.append(alphabet,5).append("\0",1).append(alphabet+6,SBuf::npos);
291  control.append(alphabet,5).append(1,'\0').append(alphabet,6,std::string::npos);
292  SBuf scontrol(control); // we need this to test the equality. sigh.
293  CPPUNIT_ASSERT_EQUAL(scontrol,s);
294  }
295  {
296  const char *alphazero="abcdefghijk\0mnopqrstuvwxyz";
297  SBuf s(alphazero,26);
298  std::string str(alphazero,26);
299  CPPUNIT_ASSERT_EQUAL(0,memcmp(str.data(),s.rawContent(),26));
300  }
301 }
302 
303 void
305 {
306  SBuf s1,s2;
307  s1.appendf("%s:%d:%03.2f",fox,1234,1234.56);
308  s2.assign("The quick brown fox jumped over the lazy dog:1234:1234.56");
309  CPPUNIT_ASSERT_EQUAL(s2,s1);
310 }
311 
312 void
314 {
315  SBuf::GetStats().dump(std::cout);
316  MemBlob::GetStats().dump(std::cout);
317  std::cout << "sizeof(SBuf): " << sizeof(SBuf) << std::endl;
318  std::cout << "sizeof(MemBlob): " << sizeof(MemBlob) << std::endl;
319 }
320 
321 void
323 {
324  SBuf chg(literal);
325  CPPUNIT_ASSERT_EQUAL(chg[5],'u');
326  chg.setAt(5,'e');
327  CPPUNIT_ASSERT_EQUAL(literal[5],'u');
328  CPPUNIT_ASSERT_EQUAL(chg[5],'e');
329 }
330 
331 // note: can't use cppunit's CPPUNIT_TEST_EXCEPTION because TextException asserts, and
332 // so the test can't be properly completed.
333 void
335 {
336  char c;
337  c=literal.at(literal.length()); //out of bounds by 1
338  //notreached
339  std::cout << c << std::endl;
340 }
341 
342 static int sign(int v)
343 {
344  if (v < 0)
345  return -1;
346  if (v>0)
347  return 1;
348  return 0;
349 }
350 
351 static void
352 testComparisonStdFull(const char *left, const char *right)
353 {
354  if (sign(strcmp(left, right)) != sign(SBuf(left).cmp(SBuf(right))))
355  std::cerr << std::endl << " cmp(SBuf) npos " << left << " ?= " << right << std::endl;
356  CPPUNIT_ASSERT_EQUAL(sign(strcmp(left, right)), sign(SBuf(left).cmp(SBuf(right))));
357 
358  if (sign(strcmp(left, right)) != sign(SBuf(left).cmp(right)))
359  std::cerr << std::endl << " cmp(char*) npos " << left << " ?= " << right << std::endl;
360  CPPUNIT_ASSERT_EQUAL(sign(strcmp(left, right)), sign(SBuf(left).cmp(right)));
361 
362  if (sign(strcasecmp(left, right)) != sign(SBuf(left).caseCmp(SBuf(right))))
363  std::cerr << std::endl << " caseCmp(SBuf) npos " << left << " ?= " << right << std::endl;
364  CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left, right)), sign(SBuf(left).caseCmp(SBuf(right))));
365 
366  if (sign(strcasecmp(left, right)) != sign(SBuf(left).caseCmp(right)))
367  std::cerr << std::endl << " caseCmp(char*) npos " << left << " ?= " << right << std::endl;
368  CPPUNIT_ASSERT_EQUAL(sign(strcasecmp(left, right)), sign(SBuf(left).caseCmp(right)));
369 }
370 
371 static void
372 testComparisonStdN(const char *left, const char *right, const size_t n)
373 {
374  if (sign(strncmp(left, right, n)) != sign(SBuf(left).cmp(SBuf(right), n)))
375  std::cerr << std::endl << " cmp(SBuf) " << n << ' ' << left << " ?= " << right << std::endl;
376  CPPUNIT_ASSERT_EQUAL(sign(strncmp(left, right, n)), sign(SBuf(left).cmp(SBuf(right), n)));
377 
378  if (sign(strncmp(left, right, n)) != sign(SBuf(left).cmp(right, n)))
379  std::cerr << std::endl << " cmp(char*) " << n << ' ' << SBuf(left) << " ?= " << right << std::endl;
380  CPPUNIT_ASSERT_EQUAL(sign(strncmp(left, right, n)), sign(SBuf(left).cmp(right, n)));
381 
382  if (sign(strncasecmp(left, right, n)) != sign(SBuf(left).caseCmp(SBuf(right), n)))
383  std::cerr << std::endl << " caseCmp(SBuf) " << n << ' ' << left << " ?= " << right << std::endl;
384  CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left, right, n)), sign(SBuf(left).caseCmp(SBuf(right), n)));
385 
386  if (sign(strncasecmp(left, right, n)) != sign(SBuf(left).caseCmp(right, n)))
387  std::cerr << std::endl << " caseCmp(char*) " << n << ' ' << SBuf(left) << " ?= " << right << std::endl;
388  CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left, right, n)), sign(SBuf(left).caseCmp(right, n)));
389 }
390 
391 static void
392 testComparisonStdOneWay(const char *left, const char *right)
393 {
394  testComparisonStdFull(left, right);
395  const size_t maxN = 2 + min(strlen(left), strlen(right));
396  for (size_t n = 0; n <= maxN; ++n) {
397  testComparisonStdN(left, right, n);
398  }
399 }
400 
401 static void
402 testComparisonStd(const char *s1, const char *s2)
403 {
406 }
407 
408 void
410 {
411  //same length
412  SBuf s1("foo"),s2("foe");
413  CPPUNIT_ASSERT(s1.cmp(s2)>0);
414  CPPUNIT_ASSERT(s1.caseCmp(s2)>0);
415  CPPUNIT_ASSERT(s2.cmp(s1)<0);
416  CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
417  CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
418  CPPUNIT_ASSERT(s1 > s2);
419  CPPUNIT_ASSERT(s2 < s1);
420  CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
421  //different lengths
422  s1.assign("foo");
423  s2.assign("foof");
424  CPPUNIT_ASSERT(s1.cmp(s2)<0);
425  CPPUNIT_ASSERT_EQUAL(sign(s1.cmp(s2)),sign(strcmp(s1.c_str(),s2.c_str())));
426  CPPUNIT_ASSERT(s1 < s2);
427  // specifying the max-length and overhanging size
428  CPPUNIT_ASSERT_EQUAL(1,SBuf("foolong").caseCmp(SBuf("foo"), 5));
429  // case-insensive comaprison
430  s1 = "foo";
431  s2 = "fOo";
432  CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2));
433  CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
434  // \0-clenliness test
435  s1.assign("f\0oo",4);
436  s2.assign("f\0Oo",4);
437  CPPUNIT_ASSERT(s1.cmp(s2) > 0);
438  CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2));
439  CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,3));
440  CPPUNIT_ASSERT_EQUAL(0,s1.caseCmp(s2,2));
441  CPPUNIT_ASSERT_EQUAL(0,s1.cmp(s2,2));
442 
443  testComparisonStd("foo", "fooz");
444  testComparisonStd("foo", "foo");
445  testComparisonStd("foo", "f");
446  testComparisonStd("foo", "bar");
447 
448  testComparisonStd("foo", "FOOZ");
449  testComparisonStd("foo", "FOO");
450  testComparisonStd("foo", "F");
451 
452  testComparisonStdOneWay("", "");
453 
454  // rare case C-string input matching SBuf with N>strlen(s)
455  {
456  char *right = xstrdup("foo34567890123456789012345678");
457  SBuf left("fooZYXWVUTSRQPONMLKJIHGFEDCBA");
458  // is 3 bytes in length. NEVER more.
459  right[3] = '\0';
460  left.setAt(3, '\0');
461 
462  // pick another spot to truncate at if something goes horribly wrong.
463  right[14] = '\0';
464  left.setAt(14, '\0');
465 
466  const SBuf::size_type maxN = 20 + min(left.length(), static_cast<SBuf::size_type>(strlen(right)));
467  for (SBuf::size_type n = 0; n <= maxN; ++n) {
468  if (sign(strncmp(left.rawContent(), right, n)) != sign(left.cmp(right, n)) )
469  std::cerr << std::endl << " cmp(char*) " << n << ' ' << left << " ?= " << right;
470  CPPUNIT_ASSERT_EQUAL(sign(strncmp(left.rawContent(), right, n)), sign(left.cmp(right, n)));
471  if (sign(strncasecmp(left.rawContent(), right, n)) != sign(left.caseCmp(right, n)))
472  std::cerr << std::endl << " caseCmp(char*) " << n << ' ' << left << " ?= " << right;
473  CPPUNIT_ASSERT_EQUAL(sign(strncasecmp(left.rawContent(), right, n)), sign(left.caseCmp(right, n)));
474  }
475  xfree(right);
476  }
477 }
478 
479 void
481 {
482  SBuf s1(literal),s2,s3;
483  s2=s1.consume(4);
484  s3.assign("The ");
485  CPPUNIT_ASSERT_EQUAL(s2,s3);
486  s3.assign("quick brown fox jumped over the lazy dog");
487  CPPUNIT_ASSERT_EQUAL(s1,s3);
488  s1.consume(40);
489  CPPUNIT_ASSERT_EQUAL(s1,SBuf());
490 }
491 
492 void
494 {
495  SBuf s1(literal);
496  SBuf s2(s1);
497  s2.append("foo");
498  const char *foo;
499  foo = s1.rawContent();
500  CPPUNIT_ASSERT_EQUAL(0,strncmp(fox,foo,s1.length()));
501  foo = s1.c_str();
502  CPPUNIT_ASSERT(!strcmp(fox,foo));
503 }
504 
505 void
507 {
508  SBuf s1(literal);
509  SBuf s2(fox1);
510  char *rb=s2.rawAppendStart(strlen(fox2)+1);
511  strcpy(rb,fox2);
512  s2.rawAppendFinish(rb, strlen(fox2));
513  CPPUNIT_ASSERT_EQUAL(s1,s2);
514 }
515 
516 void
518 {
519  SBuf s1(literal),s2;
520  s1.chop(4,5);
521  s2.assign("quick");
522  CPPUNIT_ASSERT_EQUAL(s1,s2);
523  s1=literal;
524  s2.clear();
525  s1.chop(5,0);
526  CPPUNIT_ASSERT_EQUAL(s1,s2);
527  const char *alphabet="abcdefghijklmnopqrstuvwxyz";
528  SBuf a(alphabet);
529  std::string s(alphabet); // TODO
530  { //regular chopping
531  SBuf b(a);
532  b.chop(3,3);
533  SBuf ref("def");
534  CPPUNIT_ASSERT_EQUAL(ref,b);
535  }
536  { // chop at end
537  SBuf b(a);
538  b.chop(b.length()-3);
539  SBuf ref("xyz");
540  CPPUNIT_ASSERT_EQUAL(ref,b);
541  }
542  { // chop at beginning
543  SBuf b(a);
544  b.chop(0,3);
545  SBuf ref("abc");
546  CPPUNIT_ASSERT_EQUAL(ref,b);
547  }
548  { // chop to zero length
549  SBuf b(a);
550  b.chop(5,0);
551  SBuf ref("");
552  CPPUNIT_ASSERT_EQUAL(ref,b);
553  }
554  { // chop beyond end (at npos)
555  SBuf b(a);
556  b.chop(SBuf::npos,4);
557  SBuf ref("");
558  CPPUNIT_ASSERT_EQUAL(ref,b);
559  }
560  { // chop beyond end
561  SBuf b(a);
562  b.chop(b.length()+2,4);
563  SBuf ref("");
564  CPPUNIT_ASSERT_EQUAL(ref,b);
565  }
566  { // null-chop
567  SBuf b(a);
568  b.chop(0,b.length());
569  SBuf ref(a);
570  CPPUNIT_ASSERT_EQUAL(ref,b);
571  }
572  { // overflow chopped area
573  SBuf b(a);
574  b.chop(b.length()-3,b.length());
575  SBuf ref("xyz");
576  CPPUNIT_ASSERT_EQUAL(ref,b);
577  }
578 }
579 
580 void
582 {
583  SBuf s1("complete string");
584  SBuf s2(s1);
585  s2.trim(SBuf(" ,"));
586  CPPUNIT_ASSERT_EQUAL(s1,s2);
587  s2.assign(" complete string ,");
588  s2.trim(SBuf(" ,"));
589  CPPUNIT_ASSERT_EQUAL(s1,s2);
590  s1.assign(", complete string ,");
591  s2=s1;
592  s2.trim(SBuf(" "));
593  CPPUNIT_ASSERT_EQUAL(s1,s2);
594 }
595 
596 // inspired by SBufFindTest; to be expanded.
598 {
600  std::string fullReference, str;
601 public:
603  SBuf ref(str);
604  CPPUNIT_ASSERT_EQUAL(ref,sb);
605  }
607  for (int offset=fullString.length()-1; offset >= 0; --offset ) {
608  for (int length=fullString.length()-1-offset; length >= 0; --length) {
609  sb=fullString.substr(offset,length);
610  str=fullReference.substr(offset,length);
612  }
613  }
614  }
615 };
616 
617 void
619 {
620  SBuf s1(literal),s2,s3;
621  s2=s1.substr(4,5);
622  s3.assign("quick");
623  CPPUNIT_ASSERT_EQUAL(s2,s3);
624  s1.chop(4,5);
625  CPPUNIT_ASSERT_EQUAL(s1,s2);
626  SBufSubstrAutoTest sat; // work done in the constructor
627 }
628 
629 void
631 {
632  const char *alphabet="abcdefghijklmnopqrstuvwxyz";
633  SBuf s1(alphabet);
634  SBuf::size_type idx;
635  SBuf::size_type nposResult=SBuf::npos;
636 
637  // FORWARD SEARCH
638  // needle in haystack
639  idx=s1.find('d');
640  CPPUNIT_ASSERT_EQUAL(3U,idx);
641  CPPUNIT_ASSERT_EQUAL('d',s1[idx]);
642 
643  // needle not present in haystack
644  idx=s1.find(' '); //fails
645  CPPUNIT_ASSERT_EQUAL(nposResult,idx);
646 
647  // search in portion
648  idx=s1.find('e',3U);
649  CPPUNIT_ASSERT_EQUAL(4U,idx);
650 
651  // char not in searched portion
652  idx=s1.find('e',5U);
653  CPPUNIT_ASSERT_EQUAL(nposResult,idx);
654 
655  // invalid start position
656  idx=s1.find('d',SBuf::npos);
657  CPPUNIT_ASSERT_EQUAL(nposResult,idx);
658 
659  // search outside of haystack
660  idx=s1.find('d',s1.length()+1);
661  CPPUNIT_ASSERT_EQUAL(nposResult,idx);
662 
663  // REVERSE SEARCH
664  // needle in haystack
665  idx=s1.rfind('d');
666  CPPUNIT_ASSERT_EQUAL(3U, idx);
667  CPPUNIT_ASSERT_EQUAL('d', s1[idx]);
668 
669  // needle not present in haystack
670  idx=s1.rfind(' '); //fails
671  CPPUNIT_ASSERT_EQUAL(nposResult,idx);
672 
673  // search in portion
674  idx=s1.rfind('e',5);
675  CPPUNIT_ASSERT_EQUAL(4U,idx);
676 
677  // char not in searched portion
678  idx=s1.rfind('e',3);
679  CPPUNIT_ASSERT_EQUAL(nposResult,idx);
680 
681  // overlong haystack specification
682  idx=s1.rfind('d',s1.length()+1);
683  CPPUNIT_ASSERT_EQUAL(3U,idx);
684 }
685 
686 void
688 {
689  const char *alphabet="abcdefghijklmnopqrstuvwxyz";
690  SBuf haystack(alphabet);
691  SBuf::size_type idx;
692  SBuf::size_type nposResult=SBuf::npos;
693 
694  // FORWARD search
695  // needle in haystack
696  idx = haystack.find(SBuf("def"));
697  CPPUNIT_ASSERT_EQUAL(3U,idx);
698 
699  idx = haystack.find(SBuf("xyz"));
700  CPPUNIT_ASSERT_EQUAL(23U,idx);
701 
702  // needle not in haystack, no initial char match
703  idx = haystack.find(SBuf(" eq"));
704  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
705 
706  // needle not in haystack, initial sequence match
707  idx = haystack.find(SBuf("deg"));
708  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
709 
710  // needle past end of haystack
711  idx = haystack.find(SBuf("xyz1"));
712  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
713 
714  // search in portion: needle not in searched part
715  idx = haystack.find(SBuf("def"),7);
716  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
717 
718  // search in portion: overhang
719  idx = haystack.find(SBuf("def"),4);
720  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
721 
722  // invalid start position
723  idx = haystack.find(SBuf("def"),SBuf::npos);
724  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
725 
726  // needle bigger than haystack
727  idx = SBuf("def").find(haystack);
728  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
729 
730  // search in a double-matching haystack
731  {
732  SBuf h2=haystack;
733  h2.append(haystack);
734 
735  idx = h2.find(SBuf("def"));
736  CPPUNIT_ASSERT_EQUAL(3U,idx);
737 
738  idx = h2.find(SBuf("xyzab"));
739  CPPUNIT_ASSERT_EQUAL(23U,idx);
740  }
741 
742  // REVERSE search
743  // needle in haystack
744  idx = haystack.rfind(SBuf("def"));
745  CPPUNIT_ASSERT_EQUAL(3U,idx);
746 
747  idx = haystack.rfind(SBuf("xyz"));
748  CPPUNIT_ASSERT_EQUAL(23U,idx);
749 
750  // needle not in haystack, no initial char match
751  idx = haystack.rfind(SBuf(" eq"));
752  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
753 
754  // needle not in haystack, initial sequence match
755  idx = haystack.rfind(SBuf("deg"));
756  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
757 
758  // needle past end of haystack
759  idx = haystack.rfind(SBuf("xyz1"));
760  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
761 
762  // search in portion: needle in searched part
763  idx = haystack.rfind(SBuf("def"),7);
764  CPPUNIT_ASSERT_EQUAL(3U, idx);
765 
766  // search in portion: needle not in searched part
767  idx = haystack.rfind(SBuf("mno"),3);
768  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
769 
770  // search in portion: overhang
771  idx = haystack.rfind(SBuf("def"),4);
772  CPPUNIT_ASSERT_EQUAL(3U, idx);
773 
774  // npos start position
775  idx = haystack.rfind(SBuf("def"),SBuf::npos);
776  CPPUNIT_ASSERT_EQUAL(3U, idx);
777 
778  // needle bigger than haystack
779  idx = SBuf("def").rfind(haystack);
780  CPPUNIT_ASSERT_EQUAL(nposResult, idx);
781 
782  // search in a double-matching haystack
783  {
784  SBuf h2=haystack;
785  h2.append(haystack);
786 
787  idx = h2.rfind(SBuf("def"));
788  CPPUNIT_ASSERT_EQUAL(29U,idx);
789 
790  idx = h2.find(SBuf("xyzab"));
791  CPPUNIT_ASSERT_EQUAL(23U,idx);
792  }
793 }
794 
795 void
797 {
798  SBuf s1(literal);
799  SBuf::size_type idx;
800  idx=s1.rfind(' ');
801  CPPUNIT_ASSERT_EQUAL(40U,idx);
802  CPPUNIT_ASSERT_EQUAL(' ',s1[idx]);
803 }
804 
805 void
807 {
808  SBuf haystack(literal),afox("fox");
809  SBuf goobar("goobar");
810  SBuf::size_type idx;
811 
812  // corner case: search for a zero-length SBuf
813  idx=haystack.rfind(SBuf(""));
814  CPPUNIT_ASSERT_EQUAL(haystack.length(),idx);
815 
816  // corner case: search for a needle longer than the haystack
817  idx=afox.rfind(SBuf(" "));
818  CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
819 
820  idx=haystack.rfind(SBuf("fox"));
821  CPPUNIT_ASSERT_EQUAL(16U,idx);
822 
823  // needle not found, no match for first char
824  idx=goobar.rfind(SBuf("foo"));
825  CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
826 
827  // needle not found, match for first char but no match for SBuf
828  idx=haystack.rfind(SBuf("foe"));
829  CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
830 
831  SBuf g("g"); //match at the last char
832  idx=haystack.rfind(g);
833  CPPUNIT_ASSERT_EQUAL(43U,idx);
834  CPPUNIT_ASSERT_EQUAL('g',haystack[idx]);
835 
836  idx=haystack.rfind(SBuf("The"));
837  CPPUNIT_ASSERT_EQUAL(0U,idx);
838 
839  haystack.append("The");
840  idx=haystack.rfind(SBuf("The"));
841  CPPUNIT_ASSERT_EQUAL(44U,idx);
842 
843  //partial match
844  haystack="The quick brown fox";
845  SBuf needle("foxy lady");
846  idx=haystack.rfind(needle);
847  CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
848 }
849 
850 void
852 {
853  SBuf s(fox);
854  CPPUNIT_ASSERT_EQUAL(strlen(fox),(size_t)s.length());
855 }
856 
857 void
859 {
860  char buf[40]; //shorter than literal()
861  SBuf s(fox1),s2;
862  CPPUNIT_ASSERT_EQUAL(s.length(),s.copy(buf,40));
863  CPPUNIT_ASSERT_EQUAL(0,strncmp(s.rawContent(),buf,s.length()));
864  s=literal;
865  CPPUNIT_ASSERT_EQUAL(40U,s.copy(buf,40));
866  s2.assign(buf,40);
867  s.chop(0,40);
868  CPPUNIT_ASSERT_EQUAL(s2,s);
869 }
870 
871 void
873 {
874  SBuf sng(ToLower(literal)),
875  ref("the quick brown fox jumped over the lazy dog");
876  CPPUNIT_ASSERT_EQUAL(ref,sng);
877  sng=literal;
878  CPPUNIT_ASSERT_EQUAL(0,sng.compare(ref,caseInsensitive));
879  // max-size comparison
880  CPPUNIT_ASSERT_EQUAL(0,ref.compare(SBuf("THE"),caseInsensitive,3));
881  CPPUNIT_ASSERT_EQUAL(1,ref.compare(SBuf("THE"),caseInsensitive,6));
882  CPPUNIT_ASSERT_EQUAL(0,SBuf("the").compare(SBuf("THE"),caseInsensitive,6));
883 }
884 
885 void
887 {
888  SBuf t;
889  t.assign("foo");
890  const char *ref=t.rawContent();
891  t.reserveCapacity(10240);
892  const char *match=t.rawContent();
893  CPPUNIT_ASSERT(match!=ref);
894  ref=match;
896  t.append(t).append(t).append(t).append(t).append(t);
897  CPPUNIT_ASSERT_EQUAL(ref,match);
898 }
899 
900 void
902 {
903  SBufReservationRequirements requirements;
904  // use unusual numbers to ensure we do not hit a lucky boundary situation
905  requirements.minSpace = 10;
906  requirements.idealSpace = 82;
907  requirements.maxCapacity = 259;
908  requirements.allowShared = true;
909 
910  // for each possible starting buffer length within the capacity
911  for (SBuf::size_type startLength = 0; startLength <= requirements.maxCapacity; ++startLength) {
912  std::cerr << ".";
913  SBuf b;
914  b.reserveCapacity(startLength);
915  CPPUNIT_ASSERT_EQUAL(b.length(), static_cast<unsigned int>(0));
916  CPPUNIT_ASSERT_EQUAL(b.spaceSize(), startLength);
917 
918  // check that it never grows outside capacity.
919  // do 5 excess cycles to check that.
920  for (SBuf::size_type filled = 0; filled < requirements.maxCapacity +5; ++filled) {
921  CPPUNIT_ASSERT_EQUAL(b.length(), min(filled, requirements.maxCapacity));
922  auto x = b.reserve(requirements);
923  // the amount of space advertized must not cause users to exceed capacity
924  CPPUNIT_ASSERT(x <= requirements.maxCapacity - filled);
925  CPPUNIT_ASSERT(b.spaceSize() <= requirements.maxCapacity - filled);
926  // the total size of buffer must not cause users to exceed capacity
927  CPPUNIT_ASSERT(b.length() + b.spaceSize() <= requirements.maxCapacity);
928  if (x > 0)
929  b.append('X');
930  }
931  }
932 
933  // the minimal space requirement should overwrite idealSpace preferences
934  requirements.minSpace = 10;
935  for (const int delta: {-1,0,+1}) {
936  requirements.idealSpace = requirements.minSpace + delta;
937  SBuf buffer;
938  buffer.reserve(requirements);
939  CPPUNIT_ASSERT(buffer.spaceSize() >= requirements.minSpace);
940  }
941 
942  // TODO: Decide whether to encapsulate the (nearly identical) code of the
943  // gap-related test cases below into a function, obscuring each case logic a
944  // little, but facilitating new test cases (and removing code duplication).
945 
946  { // reserveSpace() uses the trailing space before the front gap
947  SBuf buffer(fox);
948 
949  // assure there is some trailing space
950  buffer.reserveSpace(1);
951  CPPUNIT_ASSERT(buffer.spaceSize() > 0);
952 
953  // create a leading gap and (weak-)check that it was created
954  const auto gap = 1U; // the smallest gap may be the most challenging
955  CPPUNIT_ASSERT(gap < buffer.length());
956  const void *gapEnd = buffer.rawContent() + gap;
957  buffer.consume(gap);
958  CPPUNIT_ASSERT_EQUAL(gapEnd, static_cast<const void*>(buffer.rawContent()));
959 
960  const auto before = SBuf::GetStats();
961  const auto beforeSpaceSize = buffer.spaceSize();
962  const void * const beforePosition = buffer.rawContent();
963  buffer.reserveSpace(beforeSpaceSize);
964  const auto after = SBuf::GetStats();
965  const void * const afterPosition = buffer.rawContent();
966  CPPUNIT_ASSERT_EQUAL(before.cowAvoided + 1, after.cowAvoided);
967  CPPUNIT_ASSERT_EQUAL(before.cowShift, after.cowShift);
968  CPPUNIT_ASSERT_EQUAL(before.cowJustAlloc, after.cowJustAlloc);
969  CPPUNIT_ASSERT_EQUAL(before.cowAllocCopy, after.cowAllocCopy);
970  CPPUNIT_ASSERT_EQUAL(beforeSpaceSize, buffer.spaceSize());
971  CPPUNIT_ASSERT_EQUAL(beforePosition, afterPosition);
972  CPPUNIT_ASSERT(strcmp(fox + gap, buffer.c_str()) == 0);
973  }
974 
975  { // reserveSpace() uses the front gap when the trailing space is not enough
976  SBuf buffer(fox);
977 
978  // assure there is some trailing space to keep the test case challenging
979  buffer.reserveSpace(1);
980  CPPUNIT_ASSERT(buffer.spaceSize() > 0);
981  const void * const initialStorage = buffer.rawContent();
982 
983  // create a leading gap and (weak-)check that it was created
984  const auto gap = 1U; // the smallest gap may be the most challenging
985  CPPUNIT_ASSERT(gap < buffer.length());
986  const void *gapEnd = buffer.rawContent() + gap;
987  buffer.consume(gap);
988  CPPUNIT_ASSERT_EQUAL(gapEnd, static_cast<const void*>(buffer.rawContent()));
989 
990  const auto before = SBuf::GetStats();
991  const auto beforeSpaceSize = buffer.spaceSize();
992  buffer.reserveSpace(beforeSpaceSize + gap); // force (entire) gap use
993  const auto after = SBuf::GetStats();
994  const void * const afterStorage = buffer.rawContent();
995  CPPUNIT_ASSERT_EQUAL(before.cowAvoided, after.cowAvoided);
996  CPPUNIT_ASSERT_EQUAL(before.cowShift + 1, after.cowShift);
997  CPPUNIT_ASSERT_EQUAL(before.cowJustAlloc, after.cowJustAlloc);
998  CPPUNIT_ASSERT_EQUAL(before.cowAllocCopy, after.cowAllocCopy);
999  CPPUNIT_ASSERT_EQUAL(initialStorage, afterStorage);
1000  CPPUNIT_ASSERT(beforeSpaceSize + gap <= buffer.spaceSize());
1001  CPPUNIT_ASSERT(strcmp(fox + gap, buffer.c_str()) == 0);
1002  }
1003 
1004  { // reserveSpace() uses the entire front gap when using the front gap
1005  SBuf buffer(fox);
1006 
1007  // assure there is some trailing space to keep the test case challenging
1008  buffer.reserveSpace(1);
1009  CPPUNIT_ASSERT(buffer.spaceSize() > 0);
1010  const void * const initialStorage = buffer.rawContent();
1011 
1012  // create a leading gap and (weak-)check that it was created
1013  const auto gap = 2U; // the smallest extra gap may be the most challenging
1014  CPPUNIT_ASSERT(gap < buffer.length());
1015  const void *gapEnd = buffer.rawContent() + gap;
1016  buffer.consume(gap);
1017  CPPUNIT_ASSERT_EQUAL(gapEnd, static_cast<const void*>(buffer.rawContent()));
1018 
1019  const auto before = SBuf::GetStats();
1020  const auto beforeSpaceSize = buffer.spaceSize();
1021  buffer.reserveSpace(beforeSpaceSize + 1); // force (minimal) gap use
1022  const auto after = SBuf::GetStats();
1023  const void * const afterStorage = buffer.rawContent();
1024  CPPUNIT_ASSERT_EQUAL(before.cowAvoided, after.cowAvoided);
1025  CPPUNIT_ASSERT_EQUAL(before.cowShift + 1, after.cowShift);
1026  CPPUNIT_ASSERT_EQUAL(before.cowJustAlloc, after.cowJustAlloc);
1027  CPPUNIT_ASSERT_EQUAL(before.cowAllocCopy, after.cowAllocCopy);
1028  CPPUNIT_ASSERT_EQUAL(initialStorage, afterStorage);
1029  CPPUNIT_ASSERT(beforeSpaceSize + gap <= buffer.spaceSize());
1030  CPPUNIT_ASSERT(strcmp(fox + gap, buffer.c_str()) == 0);
1031  }
1032 }
1033 
1034 void
1036 {
1037  static SBuf casebuf("THE QUICK");
1038  CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1)));
1039  CPPUNIT_ASSERT(!SBuf("The quick brown").startsWith(SBuf(fox1))); //too short
1040  CPPUNIT_ASSERT(!literal.startsWith(SBuf(fox2))); //different contents
1041 
1042  // case-insensitive checks
1043  CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
1044  casebuf=ToUpper(SBuf(fox1));
1045  CPPUNIT_ASSERT(literal.startsWith(casebuf,caseInsensitive));
1046  CPPUNIT_ASSERT(literal.startsWith(SBuf(fox1),caseInsensitive));
1047  casebuf = "tha quick";
1048  CPPUNIT_ASSERT_EQUAL(false,literal.startsWith(casebuf,caseInsensitive));
1049 }
1050 
1051 void
1053 {
1054  SBuf b("const.string, int 10 and a float 10.5");
1055  SBufStream ss;
1056  ss << "const.string, int " << 10 << " and a float " << 10.5;
1057  SBuf o=ss.buf();
1058  CPPUNIT_ASSERT_EQUAL(b,o);
1059  ss.clearBuf();
1060  o=ss.buf();
1061  CPPUNIT_ASSERT_EQUAL(SBuf(),o);
1062  SBuf f1(fox1);
1063  SBufStream ss2(f1);
1064  ss2 << fox2;
1065  CPPUNIT_ASSERT_EQUAL(ss2.buf(),literal);
1066  CPPUNIT_ASSERT_EQUAL(f1,SBuf(fox1));
1067 }
1068 
1069 void
1071 {
1072  SBuf haystack(literal);
1073  SBuf::size_type idx;
1074 
1075  // not found
1076  idx=haystack.findFirstOf(CharacterSet("t1","ADHRWYP"));
1077  CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
1078 
1079  // found at beginning
1080  idx=haystack.findFirstOf(CharacterSet("t2","THANDF"));
1081  CPPUNIT_ASSERT_EQUAL(0U,idx);
1082 
1083  //found at end of haystack
1084  idx=haystack.findFirstOf(CharacterSet("t3","QWERYVg"));
1085  CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
1086 
1087  //found in the middle of haystack
1088  idx=haystack.findFirstOf(CharacterSet("t4","QWERqYV"));
1089  CPPUNIT_ASSERT_EQUAL(4U,idx);
1090 }
1091 
1092 void
1094 {
1095  SBuf haystack(literal);
1096  SBuf::size_type idx;
1097 
1098  // all chars from the set
1099  idx=haystack.findFirstNotOf(CharacterSet("t1",literal.c_str()));
1100  CPPUNIT_ASSERT_EQUAL(SBuf::npos,idx);
1101 
1102  // found at beginning
1103  idx=haystack.findFirstNotOf(CharacterSet("t2","a"));
1104  CPPUNIT_ASSERT_EQUAL(0U,idx);
1105 
1106  //found at end of haystack
1107  idx=haystack.findFirstNotOf(CharacterSet("t3",literal.substr(0,literal.length()-1).c_str()));
1108  CPPUNIT_ASSERT_EQUAL(haystack.length()-1,idx);
1109 
1110  //found in the middle of haystack
1111  idx=haystack.findFirstNotOf(CharacterSet("t4","The"));
1112  CPPUNIT_ASSERT_EQUAL(3U,idx);
1113 }
1114 
1115 void
1117 {
1118  SBufFindTest test;
1119  test.run();
1120 }
1121 
1122 void
1124 {
1125  const char *alphabet="abcdefghijklmnopqrstuvwxyz";
1126  std::string astr(alphabet);
1127  SBuf sb(alphabet);
1128  CPPUNIT_ASSERT_EQUAL(astr,sb.toStdString());
1129 }
1130 
1131 void
1133 {
1134  SBuf text("foo"), text2("foo");
1135  CPPUNIT_ASSERT(text.begin() == text.begin());
1136  CPPUNIT_ASSERT(text.begin() != text.end());
1137  CPPUNIT_ASSERT(text.begin() != text2.begin());
1138  {
1139  auto i = text.begin();
1140  auto e = text.end();
1141  CPPUNIT_ASSERT_EQUAL('f', *i);
1142  CPPUNIT_ASSERT(i != e);
1143  ++i;
1144  CPPUNIT_ASSERT_EQUAL('o', *i);
1145  CPPUNIT_ASSERT(i != e);
1146  ++i;
1147  CPPUNIT_ASSERT_EQUAL('o', *i);
1148  CPPUNIT_ASSERT(i != e);
1149  ++i;
1150  CPPUNIT_ASSERT(i == e);
1151  }
1152  {
1153  auto i = text.rbegin();
1154  auto e = text.rend();
1155  CPPUNIT_ASSERT_EQUAL('o', *i);
1156  CPPUNIT_ASSERT(i != e);
1157  ++i;
1158  CPPUNIT_ASSERT_EQUAL('o', *i);
1159  CPPUNIT_ASSERT(i != e);
1160  ++i;
1161  CPPUNIT_ASSERT_EQUAL('f', *i);
1162  CPPUNIT_ASSERT(i != e);
1163  ++i;
1164  CPPUNIT_ASSERT(i == e);
1165  }
1166 }
1167 
1168 void
1170 {
1171  // same SBuf must have same hash
1172  auto hasher=std::hash<SBuf>();
1173  CPPUNIT_ASSERT_EQUAL(hasher(literal),hasher(literal));
1174 
1175  // same content must have same hash
1176  CPPUNIT_ASSERT_EQUAL(hasher(literal),hasher(SBuf(fox)));
1177  CPPUNIT_ASSERT_EQUAL(hasher(SBuf(fox)),hasher(SBuf(fox)));
1178 
1179  //different content should have different hash
1180  CPPUNIT_ASSERT(hasher(SBuf(fox)) != hasher(SBuf(fox1)));
1181 
1182  {
1183  std::unordered_map<SBuf, int> um;
1184  um[SBuf("one")] = 1;
1185  um[SBuf("two")] = 2;
1186 
1187  auto i = um.find(SBuf("one"));
1188  CPPUNIT_ASSERT(i != um.end());
1189  CPPUNIT_ASSERT(i->second == 1);
1190 
1191  i = um.find(SBuf("eleventy"));
1192  CPPUNIT_ASSERT(i == um.end());
1193  }
1194 }
1195 
1196 void
1198 {
1199  {
1200  SBuf src(fox), dst;
1201  std::copy(src.begin(), src.end(), std::back_inserter(dst));
1202  CPPUNIT_ASSERT_EQUAL(src, dst);
1203  }
1204 
1205  {
1206  SBuf src(fox), dst;
1207  std::copy_if(src.begin(), src.end(), std::back_inserter(dst),
1208  [](char c) { return c != 'o'; });
1209  CPPUNIT_ASSERT_EQUAL(SBuf("The quick brwn fx jumped ver the lazy dg"), dst);
1210  }
1211 }
1212 
1213 int
1214 main(int argc, char *argv[])
1215 {
1216  return TestProgram().run(argc, argv);
1217 }
1218 
void testAutoFind()
Definition: testSBuf.cc:1116
size_type find(char c, size_type startPos=0) const
Definition: SBuf.cc:584
static void testComparisonStdFull(const char *left, const char *right)
Definition: testSBuf.cc:352
void testSBufConstructDestruct()
Definition: testSBuf.cc:136
size_type idealSpace
if allocating anyway, provide this much space
Definition: SBuf.h:710
SBuf & assign(const SBuf &S)
Definition: SBuf.cc:83
void testCopy()
Definition: testSBuf.cc:858
void eventAdd(const char *, EVH *, void *, double, int, bool)
Definition: testSBuf.cc:117
void testAppendStdString()
Definition: testSBuf.cc:279
void testFindFirstOf()
Definition: testSBuf.cc:1070
void testReserve()
Definition: testSBuf.cc:901
void testRFindChar()
Definition: testSBuf.cc:796
void run()
generates and executes cases using configuration params
const_reverse_iterator rbegin() const
Definition: SBuf.h:595
void testSBufStream()
Definition: testSBuf.cc:1052
@ s1
Definition: cf_gen.cc:55
IcmpPinger control
pinger helper contains one of these as a global object.
Definition: pinger.cc:90
void testStringOps()
Definition: testSBuf.cc:872
void testComparisons()
Definition: testSBuf.cc:409
void reserveSpace(size_type minSpace)
Definition: SBuf.h:444
default hash functor to support std::unordered_map<SBuf,*>
Definition: Algorithms.h:109
size_type maxCapacity
do not allocate more than this
Definition: SBuf.h:712
implements test program's main() function while enabling customization
Definition: unitTestMain.h:25
int compare(const SBuf &S, const SBufCaseSensitive isCaseSensitive, const size_type n) const
Definition: SBuf.cc:352
Definition: SBuf.h:93
#define xstrdup
Named SBuf::reserve() parameters. Defaults ask for and restrict nothing.
Definition: SBuf.h:700
void testStdStringOps()
Definition: testSBuf.cc:1123
void testAppendf()
Definition: testSBuf.cc:304
void rawAppendFinish(const char *start, size_type actualSize)
Definition: SBuf.cc:144
size_type spaceSize() const
Definition: SBuf.h:397
bool startsWith(const SBuf &S, const SBufCaseSensitive isCaseSensitive=caseSensitive) const
Definition: SBuf.cc:442
void testPrintf()
Definition: testSBuf.cc:262
int64_t endOffset() const
Definition: MemObject.cc:214
bool allowShared
whether sharing our storage with others is OK
Definition: SBuf.h:713
SBuf empty_sbuf
Definition: testSBuf.cc:132
void testRawSpace()
Definition: testSBuf.cc:506
SBuf substr(size_type pos, size_type n=npos) const
Definition: SBuf.cc:576
void clear()
Definition: SBuf.cc:175
void testGrow()
Definition: testSBuf.cc:886
void testIterators()
Definition: testSBuf.cc:1132
size_type reserve(const SBufReservationRequirements &requirements)
Definition: SBuf.cc:112
SBuf & chop(size_type pos, size_type n=npos)
Definition: SBuf.cc:530
char * rawAppendStart(size_type anticipatedSize)
Definition: SBuf.cc:136
int run(int argc, char *argv[])
Definition: unitTestMain.h:44
std::string str
Definition: testSBuf.cc:600
CPPUNIT_TEST_SUITE(TestSBuf)
void testChop()
Definition: testSBuf.cc:517
size_type rfind(char c, size_type endPos=npos) const
Definition: SBuf.cc:692
const_reverse_iterator rend() const
Definition: SBuf.h:599
void testStartsWith()
Definition: testSBuf.cc:1035
static const char fox1[]
Definition: testSBuf.cc:126
static const char fox[]
Definition: testSBuf.cc:125
static const char fox2[]
Definition: testSBuf.cc:127
const char * rawContent() const
Definition: SBuf.cc:509
SBuf consume(size_type n=npos)
Definition: SBuf.cc:481
CPPUNIT_TEST(testSBufConstructDestruct)
static void testComparisonStd(const char *s1, const char *s2)
Definition: testSBuf.cc:402
@ caseInsensitive
Definition: SBuf.h:38
const_iterator end() const
Definition: SBuf.h:591
MemBlob::size_type size_type
Definition: SBuf.h:96
std::ostream & dump(std::ostream &os) const
dumps class-wide statistics
Definition: MemBlob.cc:33
void testFindSBuf()
Definition: testSBuf.cc:687
void testRawContent()
Definition: testSBuf.cc:493
char at(size_type pos) const
Definition: SBuf.h:253
SBuf text("GET http://resource.com/path HTTP/1.1\r\n" "Host: resource.com\r\n" "Cookie: laijkpk3422r j1noin \r\n" "\r\n")
void testRFindSBuf()
Definition: testSBuf.cc:806
SBuf literal("The quick brown fox jumped over the lazy dog")
static void testComparisonStdN(const char *left, const char *right, const size_t n)
Definition: testSBuf.cc:372
SBuf ToUpper(SBuf buf)
Returns a lower-cased copy of its parameter.
Definition: SBuf.h:725
const CharacterSet alpha("alpha","abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
const_iterator begin() const
Definition: SBuf.h:587
void testConsume()
Definition: testSBuf.cc:480
void testAppendCString()
Definition: testSBuf.cc:271
std::string toStdString() const
std::string export function
Definition: SBuf.h:585
void performEqualityTest()
Definition: testSBuf.cc:602
SBuf buf()
bytes written so far
Definition: Stream.h:41
static void testComparisonStdOneWay(const char *left, const char *right)
Definition: testSBuf.cc:392
static const MemBlobStats & GetStats()
obtain a const view of class-wide statistics
Definition: MemBlob.cc:53
void testStdAlgorithm()
Definition: testSBuf.cc:1197
void testSBufConstructDestructAfterMemInit()
Definition: testSBuf.cc:216
SBuf & trim(const SBuf &toRemove, bool atBeginning=true, bool atEnd=true)
Definition: SBuf.cc:551
std::string fullReference
Definition: testSBuf.cc:600
const char * c_str()
Definition: SBuf.cc:516
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:419
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
SBufStream & clearBuf()
Clear the stream's backing store.
Definition: Stream.h:47
#define xfree
void testEqualityTest()
Definition: testSBuf.cc:223
void testSubscriptOp()
Definition: testSBuf.cc:322
void commonInit()
static const size_type npos
Definition: SBuf.h:100
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
Definition: SBuf.cc:746
void EVH(void *)
Definition: event.h:18
size_type minSpace
allocate [at least this much] if spaceSize() is smaller
Definition: SBuf.h:711
void setAt(size_type pos, char toset)
Definition: SBuf.cc:328
CPPUNIT_TEST_EXCEPTION(testSubscriptOpFail, TextException)
void testSubscriptOpFail()
Definition: testSBuf.cc:334
void testAppendSBuf()
Definition: testSBuf.cc:241
CPPUNIT_TEST_SUITE_END()
CPPUNIT_TEST_SUITE_REGISTRATION(TestSBuf)
void reserveCapacity(size_type minCapacity)
Definition: SBuf.cc:105
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition: SBuf.h:279
an std::runtime_error with thrower location info
Definition: TextException.h:20
static const SBufStats & GetStats()
gets global statistic information
Definition: SBuf.cc:494
void Init()
Definition: old_api.cc:281
void testFindFirstNotOf()
Definition: testSBuf.cc:1093
SBuf ToLower(SBuf buf)
Returns an upper-cased copy of its parameter.
Definition: SBuf.h:733
void testSBufLength()
Definition: testSBuf.cc:851
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:17
int caseCmp(const SBuf &S, const size_type n) const
shorthand version for case-insensitive compare()
Definition: SBuf.h:287
int main(int argc, char *argv[])
Definition: testSBuf.cc:1214
void testSBufHash()
Definition: testSBuf.cc:1169
void testSubstr()
Definition: testSBuf.cc:618
static int sign(int v)
Definition: testSBuf.cc:342
void testTailCopy()
void testDumpStats()
Definition: testSBuf.cc:313
std::ostream & dump(std::ostream &os) const
Dump statistics to an ostream.
Definition: Stats.cc:65
size_type findFirstOf(const CharacterSet &set, size_type startPos=0) const
Definition: SBuf.cc:723
const A & min(A const &lhs, A const &rhs)
void testFindChar()
Definition: testSBuf.cc:630
void testSearchFail()
void testChomp()
Definition: testSBuf.cc:581

 

Introduction

Documentation

Support

Miscellaneous