String.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 "mem/forward.h"
11 #include "SquidString.h"
12 
13 #include <climits>
14 
15 // low-level buffer allocation,
16 // does not free old buffer and does not adjust or look at len_
17 void
19 {
20  assert (undefined());
21  auto *newBuffer = static_cast<char*>(memAllocBuf(sz, &sz));
22  setBuffer(newBuffer, sz);
23 }
24 
25 // low-level buffer assignment
26 // does not free old buffer and does not adjust or look at len_
27 void
29 {
30  assert(undefined());
31  assert(aSize <= SizeMax_);
32  buf_ = aBuf;
33  size_ = aSize;
34 }
35 
36 String::String(char const *aString)
37 {
38  if (aString)
39  allocAndFill(aString, strlen(aString));
40 }
41 
42 String &
43 String::operator =(char const *aString)
44 {
45  reset(aString);
46  return *this;
47 }
48 
49 String &
51 {
52  clean(); // TODO: optimize to avoid cleaning the buffer we can use
53  if (old.size() > 0)
54  allocAndFill(old.rawBuf(), old.size());
55  return *this;
56 }
57 
58 bool
59 String::operator ==(String const &that) const
60 {
61  if (0 == this->cmp(that))
62  return true;
63 
64  return false;
65 }
66 
67 bool
68 String::operator !=(String const &that) const
69 {
70  if (0 == this->cmp(that))
71  return false;
72 
73  return true;
74 }
75 
76 // public interface, makes sure that we clean the old buffer first
77 void
78 String::assign(const char *str, int len)
79 {
80  clean(); // TODO: optimize to avoid cleaning the buffer we can use
81  allocAndFill(str, len);
82 }
83 
84 // Allocates the buffer to fit the supplied string and fills it.
85 // Does not clean.
86 void
87 String::allocAndFill(const char *str, int len)
88 {
89  assert(str);
90  allocBuffer(len + 1);
91  len_ = len;
92  memcpy(buf_, str, len);
93  buf_[len] = '\0';
94 }
95 
96 String::String(String const &old) : size_(0), len_(0), buf_(nullptr)
97 {
98  if (old.size() > 0)
99  allocAndFill(old.rawBuf(), old.size());
100 }
101 
102 void
104 {
105  /* TODO if mempools has already closed this will FAIL!! */
106  if (defined())
108 
109  len_ = 0;
110 
111  size_ = 0;
112 
113  buf_ = nullptr;
114 }
115 
117 {
118  clean();
119 }
120 
121 void
122 String::reset(char const *str)
123 {
124  clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
125  if (str)
126  allocAndFill(str, strlen(str));
127 }
128 
129 void
130 String::append( char const *str, int len)
131 {
132  assert(str && len >= 0);
133 
134  if (len_ + len + 1 /*'\0'*/ < size_) {
135  xstrncpy(buf_+len_, str, len+1);
136  len_ += len;
137  } else {
138  // Create a temporary string and absorb it later.
139  String snew;
140  assert(canGrowBy(len)); // otherwise snew.len_ may overflow below
141  snew.len_ = len_ + len;
142  snew.allocBuffer(snew.len_ + 1);
143 
144  if (len_)
145  memcpy(snew.buf_, rawBuf(), len_);
146 
147  if (len)
148  memcpy(snew.buf_ + len_, str, len);
149 
150  snew.buf_[snew.len_] = '\0';
151 
152  absorb(snew);
153  }
154 }
155 
156 void
157 String::append(char const *str)
158 {
159  assert(str);
160  append(str, strlen(str));
161 }
162 
163 void
164 String::append(char const chr)
165 {
166  char myString[2];
167  myString[0]=chr;
168  myString[1]='\0';
169  append(myString, 1);
170 }
171 
172 void
174 {
175  append(old.rawBuf(), old.len_);
176 }
177 
178 void
180 {
181  clean();
182  setBuffer(old.buf_, old.size_);
183  len_ = old.len_;
184  old.size_ = 0;
185  old.buf_ = nullptr;
186  old.len_ = 0;
187 }
188 
189 String
191 {
192 // Must(from >= 0 && from < size());
193  Must(from < size());
194  Must(to > 0 && to <= size());
195  Must(to > from);
196 
197  String rv;
198  rv.assign(rawBuf()+from, to-from);
199  return rv;
200 }
201 
202 void
204 {
205  // size_type is size_t, unsigned. No need to check for newLength <0
206  if (newLength > len_) return;
207 
208  len_ = newLength;
209 
210  // buf_ may be nullptr on zero-length strings.
211  if (len_ == 0 && !buf_)
212  return;
213 
214  buf_[newLength] = '\0';
215 }
216 
219 static bool
220 nilCmp(const bool thisIsNilOrEmpty, const bool otherIsNilOrEmpty, int &result)
221 {
222  if (!thisIsNilOrEmpty && !otherIsNilOrEmpty)
223  return false; // result does not matter
224 
225  if (thisIsNilOrEmpty && otherIsNilOrEmpty)
226  result = 0;
227  else if (thisIsNilOrEmpty)
228  result = -1;
229  else // otherIsNilOrEmpty
230  result = +1;
231 
232  return true;
233 }
234 
235 int
236 String::cmp(char const *aString) const
237 {
238  int result = 0;
239  if (nilCmp(!size(), (!aString || !*aString), result))
240  return result;
241 
242  return strcmp(termedBuf(), aString);
243 }
244 
245 int
246 String::cmp(char const *aString, String::size_type count) const
247 {
248  int result = 0;
249  if (nilCmp((!size() || !count), (!aString || !*aString || !count), result))
250  return result;
251 
252  return strncmp(termedBuf(), aString, count);
253 }
254 
255 int
256 String::cmp(String const &aString) const
257 {
258  int result = 0;
259  if (nilCmp(!size(), !aString.size(), result))
260  return result;
261 
262  return strcmp(termedBuf(), aString.termedBuf());
263 }
264 
265 int
266 String::caseCmp(char const *aString) const
267 {
268  int result = 0;
269  if (nilCmp(!size(), (!aString || !*aString), result))
270  return result;
271 
272  return strcasecmp(termedBuf(), aString);
273 }
274 
275 int
276 String::caseCmp(char const *aString, String::size_type count) const
277 {
278  int result = 0;
279  if (nilCmp((!size() || !count), (!aString || !*aString || !count), result))
280  return result;
281 
282  return strncasecmp(termedBuf(), aString, count);
283 }
284 
285 /* TODO: move onto String */
286 int
287 stringHasWhitespace(const char *s)
288 {
289  return strpbrk(s, w_space) != nullptr;
290 }
291 
292 /* TODO: move onto String */
293 int
294 stringHasCntl(const char *s)
295 {
296  unsigned char c;
297 
298  while ((c = (unsigned char) *s++) != '\0') {
299  if (c <= 0x1f)
300  return 1;
301 
302  if (c >= 0x7f && c <= 0x9f)
303  return 1;
304  }
305 
306  return 0;
307 }
308 
309 /*
310  * Similar to strtok, but has some rudimentary knowledge
311  * of quoting
312  */
313 char *
314 strwordtok(char *buf, char **t)
315 {
316  unsigned char *word = nullptr;
317  unsigned char *p = (unsigned char *) buf;
318  unsigned char *d;
319  unsigned char ch;
320  int quoted = 0;
321 
322  if (!p)
323  p = (unsigned char *) *t;
324 
325  if (!p)
326  goto error;
327 
328  while (*p && xisspace(*p))
329  ++p;
330 
331  if (!*p)
332  goto error;
333 
334  word = d = p;
335 
336  while ((ch = *p)) {
337  switch (ch) {
338 
339  case '\\':
340  if (quoted)
341  ++p;
342 
343  switch (*p) {
344 
345  case 'n':
346  ch = '\n';
347 
348  break;
349 
350  case 'r':
351  ch = '\r';
352 
353  break;
354 
355  default:
356  ch = *p;
357 
358  break;
359 
360  }
361 
362  *d = ch;
363  ++d;
364 
365  if (ch)
366  ++p;
367 
368  break;
369 
370  case '"':
371  quoted = !quoted;
372 
373  ++p;
374 
375  break;
376 
377  default:
378  if (!quoted && xisspace(*p)) {
379  ++p;
380  goto done;
381  }
382 
383  *d = *p;
384  ++d;
385  ++p;
386  break;
387  }
388  }
389 
390 done:
391  *d = '\0';
392 
393 error:
394  *t = (char *) p;
395  return (char *) word;
396 }
397 
398 const char *
399 checkNullString(const char *p)
400 {
401  return p ? p : "(NULL)";
402 }
403 
404 const char *
405 String::pos(char const *aString) const
406 {
407  if (undefined())
408  return nullptr;
409  return strstr(termedBuf(), aString);
410 }
411 
412 const char *
413 String::pos(char const ch) const
414 {
415  if (undefined())
416  return nullptr;
417  return strchr(termedBuf(), ch);
418 }
419 
420 const char *
421 String::rpos(char const ch) const
422 {
423  if (undefined())
424  return nullptr;
425  return strrchr(termedBuf(), (ch));
426 }
427 
429 String::find(char const ch) const
430 {
431  const char *c;
432  c=pos(ch);
433  if (c==nullptr)
434  return npos;
435  return c-rawBuf();
436 }
437 
439 String::find(char const *aString) const
440 {
441  const char *c;
442  c=pos(aString);
443  if (c==nullptr)
444  return npos;
445  return c-rawBuf();
446 }
447 
449 String::rfind(char const ch) const
450 {
451  const char *c;
452  c=rpos(ch);
453  if (c==nullptr)
454  return npos;
455  return c-rawBuf();
456 }
457 
bool undefined() const
Definition: SquidString.h:136
int caseCmp(char const *) const
Definition: String.cc:266
size_type len_
Definition: SquidString.h:141
bool operator!=(String const &) const
Definition: String.cc:68
const char * rawBuf() const
Definition: SquidString.h:86
size_type rfind(char const ch) const
Definition: String.cc:449
String & operator=(char const *)
Definition: String.cc:43
void * memAllocBuf(size_t net_size, size_t *gross_size)
Definition: minimal.cc:46
void error(char *format,...)
size_type size_
Definition: SquidString.h:139
void setBuffer(char *buf, size_type sz)
Definition: String.cc:28
int stringHasCntl(const char *s)
Definition: String.cc:294
int cmp(char const *) const
Definition: String.cc:236
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
String()=default
#define w_space
const static size_type npos
Definition: SquidString.h:39
bool operator==(String const &) const
Definition: String.cc:59
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:156
void append(char const *buf, int len)
Definition: String.cc:130
const char * rpos(char const ch) const
Definition: String.cc:421
char * strwordtok(char *buf, char **t)
Definition: String.cc:314
const char * checkNullString(const char *p)
Definition: String.cc:399
bool defined() const
Definition: SquidString.h:135
int stringHasWhitespace(const char *s)
Definition: String.cc:287
void allocAndFill(const char *str, int len)
Definition: String.cc:87
#define assert(EX)
Definition: assert.h:17
static bool nilCmp(const bool thisIsNilOrEmpty, const bool otherIsNilOrEmpty, int &result)
Definition: String.cc:220
void absorb(String &old)
Definition: String.cc:179
const char * pos(char const *aString) const
Definition: String.cc:405
~String()
Definition: String.cc:116
size_t size_type
Definition: SquidString.h:38
static const size_type SizeMax_
Definition: SquidString.h:151
const char * termedBuf() const
Definition: SquidString.h:92
void cut(size_type newLength)
Definition: String.cc:203
size_type size() const
Definition: SquidString.h:73
void allocBuffer(size_type sz)
Definition: String.cc:18
#define Must(condition)
Definition: TextException.h:75
void reset(char const *str)
Definition: String.cc:122
void assign(const char *str, int len)
Definition: String.cc:78
size_type find(char const ch) const
Definition: String.cc:429
String substr(size_type from, size_type to) const
Definition: String.cc:190
#define xisspace(x)
Definition: xis.h:15
void memFreeBuf(size_t size, void *)
Definition: minimal.cc:67
void clean()
Definition: String.cc:103

 

Introduction

Documentation

Support

Miscellaneous