String.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 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 /* DEBUG: section 67 String */
10 
11 #include "squid.h"
12 #include "base/TextException.h"
13 #include "mgr/Registration.h"
14 #include "Store.h"
15 
16 #include <climits>
17 
18 // low-level buffer allocation,
19 // does not free old buffer and does not adjust or look at len_
20 void
22 {
23  assert (undefined());
24  char *newBuffer = (char*)memAllocString(sz, &sz);
25  setBuffer(newBuffer, sz);
26 }
27 
28 // low-level buffer assignment
29 // does not free old buffer and does not adjust or look at len_
30 void
32 {
33  assert(undefined());
34  assert(aSize <= SizeMax_);
35  buf_ = aBuf;
36  size_ = aSize;
37 }
38 
40 {
41 #if DEBUGSTRINGS
42  StringRegistry::Instance().add(this);
43 #endif
44 }
45 
46 String::String(char const *aString)
47 {
48  if (aString)
49  allocAndFill(aString, strlen(aString));
50 #if DEBUGSTRINGS
51  StringRegistry::Instance().add(this);
52 #endif
53 }
54 
55 String &
56 String::operator =(char const *aString)
57 {
58  reset(aString);
59  return *this;
60 }
61 
62 String &
64 {
65  clean(); // TODO: optimize to avoid cleaning the buffer we can use
66  if (old.size() > 0)
67  allocAndFill(old.rawBuf(), old.size());
68  return *this;
69 }
70 
71 bool
72 String::operator ==(String const &that) const
73 {
74  if (0 == this->cmp(that))
75  return true;
76 
77  return false;
78 }
79 
80 bool
81 String::operator !=(String const &that) const
82 {
83  if (0 == this->cmp(that))
84  return false;
85 
86  return true;
87 }
88 
89 // public interface, makes sure that we clean the old buffer first
90 void
91 String::assign(const char *str, int len)
92 {
93  clean(); // TODO: optimize to avoid cleaning the buffer we can use
94  allocAndFill(str, len);
95 }
96 
97 // Allocates the buffer to fit the supplied string and fills it.
98 // Does not clean.
99 void
100 String::allocAndFill(const char *str, int len)
101 {
102  assert(str);
103  allocBuffer(len + 1);
104  len_ = len;
105  memcpy(buf_, str, len);
106  buf_[len] = '\0';
107 }
108 
109 String::String(String const &old) : size_(0), len_(0), buf_(NULL)
110 {
111  if (old.size() > 0)
112  allocAndFill(old.rawBuf(), old.size());
113 #if DEBUGSTRINGS
114 
115  StringRegistry::Instance().add(this);
116 #endif
117 }
118 
119 void
121 {
122  /* TODO if mempools has already closed this will FAIL!! */
123  if (defined())
125 
126  len_ = 0;
127 
128  size_ = 0;
129 
130  buf_ = NULL;
131 }
132 
134 {
135  clean();
136 #if DEBUGSTRINGS
137 
138  StringRegistry::Instance().remove(this);
139 #endif
140 }
141 
142 void
143 String::reset(char const *str)
144 {
145  clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
146  if (str)
147  allocAndFill(str, strlen(str));
148 }
149 
150 void
151 String::append( char const *str, int len)
152 {
153  assert(str && len >= 0);
154 
155  if (len_ + len + 1 /*'\0'*/ < size_) {
156  xstrncpy(buf_+len_, str, len+1);
157  len_ += len;
158  } else {
159  // Create a temporary string and absorb it later.
160  String snew;
161  assert(canGrowBy(len)); // otherwise snew.len_ may overflow below
162  snew.len_ = len_ + len;
163  snew.allocBuffer(snew.len_ + 1);
164 
165  if (len_)
166  memcpy(snew.buf_, rawBuf(), len_);
167 
168  if (len)
169  memcpy(snew.buf_ + len_, str, len);
170 
171  snew.buf_[snew.len_] = '\0';
172 
173  absorb(snew);
174  }
175 }
176 
177 void
178 String::append(char const *str)
179 {
180  assert(str);
181  append(str, strlen(str));
182 }
183 
184 void
185 String::append(char const chr)
186 {
187  char myString[2];
188  myString[0]=chr;
189  myString[1]='\0';
190  append(myString, 1);
191 }
192 
193 void
195 {
196  append(old.rawBuf(), old.len_);
197 }
198 
199 void
201 {
202  clean();
203  setBuffer(old.buf_, old.size_);
204  len_ = old.len_;
205  old.size_ = 0;
206  old.buf_ = NULL;
207  old.len_ = 0;
208 }
209 
210 String
212 {
213 // Must(from >= 0 && from < size());
214  Must(from < size());
215  Must(to > 0 && to <= size());
216  Must(to > from);
217 
218  String rv;
219  rv.assign(rawBuf()+from, to-from);
220  return rv;
221 }
222 
223 void
225 {
226  // size_type is size_t, unsigned. No need to check for newLength <0
227  if (newLength > len_) return;
228 
229  len_ = newLength;
230 
231  // buf_ may be nullptr on zero-length strings.
232  if (len_ == 0 && !buf_)
233  return;
234 
235  buf_[newLength] = '\0';
236 }
237 
240 static bool
241 nilCmp(const bool thisIsNilOrEmpty, const bool otherIsNilOrEmpty, int &result)
242 {
243  if (!thisIsNilOrEmpty && !otherIsNilOrEmpty)
244  return false; // result does not matter
245 
246  if (thisIsNilOrEmpty && otherIsNilOrEmpty)
247  result = 0;
248  else if (thisIsNilOrEmpty)
249  result = -1;
250  else // otherIsNilOrEmpty
251  result = +1;
252 
253  return true;
254 }
255 
256 int
257 String::cmp(char const *aString) const
258 {
259  int result = 0;
260  if (nilCmp(!size(), (!aString || !*aString), result))
261  return result;
262 
263  return strcmp(termedBuf(), aString);
264 }
265 
266 int
267 String::cmp(char const *aString, String::size_type count) const
268 {
269  int result = 0;
270  if (nilCmp((!size() || !count), (!aString || !*aString || !count), result))
271  return result;
272 
273  return strncmp(termedBuf(), aString, count);
274 }
275 
276 int
277 String::cmp(String const &aString) const
278 {
279  int result = 0;
280  if (nilCmp(!size(), !aString.size(), result))
281  return result;
282 
283  return strcmp(termedBuf(), aString.termedBuf());
284 }
285 
286 int
287 String::caseCmp(char const *aString) const
288 {
289  int result = 0;
290  if (nilCmp(!size(), (!aString || !*aString), result))
291  return result;
292 
293  return strcasecmp(termedBuf(), aString);
294 }
295 
296 int
297 String::caseCmp(char const *aString, String::size_type count) const
298 {
299  int result = 0;
300  if (nilCmp((!size() || !count), (!aString || !*aString || !count), result))
301  return result;
302 
303  return strncasecmp(termedBuf(), aString, count);
304 }
305 
306 #if DEBUGSTRINGS
307 void
308 String::stat(StoreEntry *entry) const
309 {
310  storeAppendPrintf(entry, "%p : %d/%d \"%.*s\"\n",this,len_, size_, size(), rawBuf());
311 }
312 
313 StringRegistry &
315 {
316  return Instance_;
317 }
318 
319 template <class C>
320 int
321 ptrcmp(C const &lhs, C const &rhs)
322 {
323  return lhs - rhs;
324 }
325 
326 StringRegistry::StringRegistry()
327 {
328 #if DEBUGSTRINGS
329  Mgr::RegisterAction("strings",
330  "Strings in use in squid", Stat, 0, 1);
331 #endif
332 }
333 
334 void
335 StringRegistry::add(String const *entry)
336 {
337  entries.insert(entry, ptrcmp);
338 }
339 
340 void
341 StringRegistry::remove(String const *entry)
342 {
343  entries.remove(entry, ptrcmp);
344 }
345 
346 StringRegistry StringRegistry::Instance_;
347 
349 
350 void
351 StringRegistry::Stat(StoreEntry *entry)
352 {
353  storeAppendPrintf(entry, "%lu entries, %lu reported from MemPool\n", (unsigned long) Instance().entries.elements, (unsigned long) memStringCount());
354  Instance().entries.head->walk(Stater, entry);
355 }
356 
357 void
358 StringRegistry::Stater(String const * const & nodedata, void *state)
359 {
360  StoreEntry *entry = (StoreEntry *) state;
361  nodedata->stat(entry);
362 }
363 
364 #endif
365 
366 /* TODO: move onto String */
367 int
368 stringHasWhitespace(const char *s)
369 {
370  return strpbrk(s, w_space) != NULL;
371 }
372 
373 /* TODO: move onto String */
374 int
375 stringHasCntl(const char *s)
376 {
377  unsigned char c;
378 
379  while ((c = (unsigned char) *s++) != '\0') {
380  if (c <= 0x1f)
381  return 1;
382 
383  if (c >= 0x7f && c <= 0x9f)
384  return 1;
385  }
386 
387  return 0;
388 }
389 
390 /*
391  * Similar to strtok, but has some rudimentary knowledge
392  * of quoting
393  */
394 char *
395 strwordtok(char *buf, char **t)
396 {
397  unsigned char *word = NULL;
398  unsigned char *p = (unsigned char *) buf;
399  unsigned char *d;
400  unsigned char ch;
401  int quoted = 0;
402 
403  if (!p)
404  p = (unsigned char *) *t;
405 
406  if (!p)
407  goto error;
408 
409  while (*p && xisspace(*p))
410  ++p;
411 
412  if (!*p)
413  goto error;
414 
415  word = d = p;
416 
417  while ((ch = *p)) {
418  switch (ch) {
419 
420  case '\\':
421  if (quoted)
422  ++p;
423 
424  switch (*p) {
425 
426  case 'n':
427  ch = '\n';
428 
429  break;
430 
431  case 'r':
432  ch = '\r';
433 
434  break;
435 
436  default:
437  ch = *p;
438 
439  break;
440 
441  }
442 
443  *d = ch;
444  ++d;
445 
446  if (ch)
447  ++p;
448 
449  break;
450 
451  case '"':
452  quoted = !quoted;
453 
454  ++p;
455 
456  break;
457 
458  default:
459  if (!quoted && xisspace(*p)) {
460  ++p;
461  goto done;
462  }
463 
464  *d = *p;
465  ++d;
466  ++p;
467  break;
468  }
469  }
470 
471 done:
472  *d = '\0';
473 
474 error:
475  *t = (char *) p;
476  return (char *) word;
477 }
478 
479 const char *
480 checkNullString(const char *p)
481 {
482  return p ? p : "(NULL)";
483 }
484 
485 const char *
486 String::pos(char const *aString) const
487 {
488  if (undefined())
489  return NULL;
490  return strstr(termedBuf(), aString);
491 }
492 
493 const char *
494 String::pos(char const ch) const
495 {
496  if (undefined())
497  return NULL;
498  return strchr(termedBuf(), ch);
499 }
500 
501 const char *
502 String::rpos(char const ch) const
503 {
504  if (undefined())
505  return NULL;
506  return strrchr(termedBuf(), (ch));
507 }
508 
510 String::find(char const ch) const
511 {
512  const char *c;
513  c=pos(ch);
514  if (c==NULL)
515  return npos;
516  return c-rawBuf();
517 }
518 
520 String::find(char const *aString) const
521 {
522  const char *c;
523  c=pos(aString);
524  if (c==NULL)
525  return npos;
526  return c-rawBuf();
527 }
528 
530 String::rfind(char const ch) const
531 {
532  const char *c;
533  c=rpos(ch);
534  if (c==NULL)
535  return npos;
536  return c-rawBuf();
537 }
538 
bool undefined() const
Definition: SquidString.h:136
int caseCmp(char const *) const
Definition: String.cc:287
static CodeContext::Pointer & Instance()
guarantees the forever existence of the pointer, starting from the first use
Definition: CodeContext.cc:26
size_type len_
Definition: SquidString.h:141
bool operator!=(String const &) const
Definition: String.cc:81
size_type rfind(char const ch) const
Definition: String.cc:530
String()
Definition: String.cc:39
String & operator=(char const *)
Definition: String.cc:56
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:869
void error(char *format,...)
size_type size_
Definition: SquidString.h:139
void setBuffer(char *buf, size_type sz)
Definition: String.cc:31
int stringHasCntl(const char *s)
Definition: String.cc:375
int cmp(char const *) const
Definition: String.cc:257
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
static const size_type npos
Definition: SquidString.h:39
#define w_space
bool operator==(String const &) const
Definition: String.cc:72
bool canGrowBy(const size_type growthLen) const
whether appending growthLen characters is safe (i.e., unlikely to assert)
Definition: SquidString.h:124
char * buf_
Definition: SquidString.h:147
#define NULL
Definition: types.h:166
void append(char const *buf, int len)
Definition: String.cc:151
const char * rpos(char const ch) const
Definition: String.cc:502
char * strwordtok(char *buf, char **t)
Definition: String.cc:395
const char * checkNullString(const char *p)
Definition: String.cc:480
void memFreeString(size_t size, void *)
Definition: old_api.cc:277
bool defined() const
Definition: SquidString.h:135
int stringHasWhitespace(const char *s)
Definition: String.cc:368
void allocAndFill(const char *str, int len)
Definition: String.cc:100
#define assert(EX)
Definition: assert.h:19
static bool nilCmp(const bool thisIsNilOrEmpty, const bool otherIsNilOrEmpty, int &result)
Definition: String.cc:241
char const * termedBuf() const
Definition: SquidString.h:92
static uint32 C
Definition: md4.c:43
void absorb(String &old)
Definition: String.cc:200
void const char int sz
Definition: stub_cbdata.cc:16
const char * pos(char const *aString) const
Definition: String.cc:486
~String()
Definition: String.cc:133
size_t size_type
Definition: SquidString.h:38
static const size_type SizeMax_
Definition: SquidString.h:143
void cut(size_type newLength)
Definition: String.cc:224
size_type size() const
Definition: SquidString.h:73
void allocBuffer(size_type sz)
Definition: String.cc:21
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:73
void reset(char const *str)
Definition: String.cc:143
void assign(const char *str, int len)
Definition: String.cc:91
size_type find(char const ch) const
Definition: String.cc:510
void * memAllocString(size_t net_size, size_t *gross_size)
Definition: old_api.cc:230
String substr(size_type from, size_type to) const
Definition: String.cc:211
#define xisspace(x)
Definition: xis.h:17
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
static StatHist s
char const * rawBuf() const
Definition: SquidString.h:86
size_t memStringCount()
Definition: old_api.cc:265
void clean()
Definition: String.cc:120

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors