]> git.ipfire.org Git - thirdparty/squid.git/blame - src/String.cc
Remove deprecated string memory pools API (#1590)
[thirdparty/squid.git] / src / String.cc
CommitLineData
ad80164a 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
ad80164a 3 *
bbc27441
AJ
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.
ad80164a 7 */
8
582c2af2 9#include "squid.h"
8ee00d73
AR
10#include "mem/forward.h"
11#include "SquidString.h"
696a257c 12
074d6a40 13#include <climits>
582c2af2 14
26ac0430 15// low-level buffer allocation,
e7e1bf60 16// does not free old buffer and does not adjust or look at len_
ad80164a 17void
a7a42b14 18String::allocBuffer(String::size_type sz)
ad80164a 19{
cb3b44fc 20 assert (undefined());
460f7f5e 21 auto *newBuffer = static_cast<char*>(memAllocBuf(sz, &sz));
e7e1bf60 22 setBuffer(newBuffer, sz);
ad80164a 23}
24
e7e1bf60 25// low-level buffer assignment
26// does not free old buffer and does not adjust or look at len_
ad80164a 27void
a7a42b14 28String::setBuffer(char *aBuf, String::size_type aSize)
ad80164a 29{
cb3b44fc 30 assert(undefined());
70df76e3 31 assert(aSize <= SizeMax_);
e7e1bf60 32 buf_ = aBuf;
33 size_ = aSize;
ad80164a 34}
35
f63c4b05 36String::String(char const *aString)
ad80164a 37{
e7e1bf60 38 if (aString)
39 allocAndFill(aString, strlen(aString));
ad80164a 40}
41
30abd221 42String &
43String::operator =(char const *aString)
ad80164a 44{
e7e1bf60 45 reset(aString);
ad80164a 46 return *this;
47}
48
30abd221 49String &
9e9ef416 50String::operator =(String const &old)
ad80164a 51{
e7e1bf60 52 clean(); // TODO: optimize to avoid cleaning the buffer we can use
53 if (old.size() > 0)
cb3b44fc 54 allocAndFill(old.rawBuf(), old.size());
ad80164a 55 return *this;
56}
57
58bool
9e9ef416 59String::operator ==(String const &that) const
ad80164a 60{
30abd221 61 if (0 == this->cmp(that))
62 return true;
ad80164a 63
30abd221 64 return false;
ad80164a 65}
66
67bool
9e9ef416 68String::operator !=(String const &that) const
ad80164a 69{
30abd221 70 if (0 == this->cmp(that))
71 return false;
72
73 return true;
ad80164a 74}
75
e7e1bf60 76// public interface, makes sure that we clean the old buffer first
30abd221 77void
2fe0439c 78String::assign(const char *str, int len)
ad80164a 79{
e7e1bf60 80 clean(); // TODO: optimize to avoid cleaning the buffer we can use
81 allocAndFill(str, len);
82}
4fbc2a54 83
e7e1bf60 84// Allocates the buffer to fit the supplied string and fills it.
85// Does not clean.
86void
87String::allocAndFill(const char *str, int len)
88{
328a07ab 89 assert(str);
e7e1bf60 90 allocBuffer(len + 1);
30abd221 91 len_ = len;
41d00cd3 92 memcpy(buf_, str, len);
30abd221 93 buf_[len] = '\0';
ad80164a 94}
95
aee3523a 96String::String(String const &old) : size_(0), len_(0), buf_(nullptr)
ad80164a 97{
dcb1fef8 98 if (old.size() > 0)
cb3b44fc 99 allocAndFill(old.rawBuf(), old.size());
ad80164a 100}
101
30abd221 102void
103String::clean()
ad80164a 104{
8536ad02 105 /* TODO if mempools has already closed this will FAIL!! */
cb3b44fc 106 if (defined())
460f7f5e 107 memFreeBuf(size_, buf_);
30abd221 108
109 len_ = 0;
110
111 size_ = 0;
112
aee3523a 113 buf_ = nullptr;
ad80164a 114}
115
30abd221 116String::~String()
ad80164a 117{
30abd221 118 clean();
ad80164a 119}
120
121void
9e9ef416 122String::reset(char const *str)
30abd221 123{
e7e1bf60 124 clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
125 if (str)
126 allocAndFill(str, strlen(str));
30abd221 127}
128
129void
9e9ef416 130String::append( char const *str, int len)
ad80164a 131{
30abd221 132 assert(str && len >= 0);
ad80164a 133
5358a024
AJ
134 if (len_ + len + 1 /*'\0'*/ < size_) {
135 xstrncpy(buf_+len_, str, len+1);
ad80164a 136 len_ += len;
137 } else {
e7e1bf60 138 // Create a temporary string and absorb it later.
30abd221 139 String snew;
70df76e3 140 assert(canGrowBy(len)); // otherwise snew.len_ may overflow below
30abd221 141 snew.len_ = len_ + len;
e7e1bf60 142 snew.allocBuffer(snew.len_ + 1);
ad80164a 143
e7e1bf60 144 if (len_)
41d00cd3 145 memcpy(snew.buf_, rawBuf(), len_);
ad80164a 146
147 if (len)
41d00cd3 148 memcpy(snew.buf_ + len_, str, len);
ad80164a 149
30abd221 150 snew.buf_[snew.len_] = '\0';
ad80164a 151
30abd221 152 absorb(snew);
ad80164a 153 }
ad80164a 154}
155
156void
30abd221 157String::append(char const *str)
ad80164a 158{
9e9ef416
RP
159 assert(str);
160 append(str, strlen(str));
ad80164a 161}
162
163void
9e9ef416 164String::append(char const chr)
ad80164a 165{
166 char myString[2];
167 myString[0]=chr;
168 myString[1]='\0';
9e9ef416 169 append(myString, 1);
ad80164a 170}
171
172void
30abd221 173String::append(String const &old)
ad80164a 174{
9e9ef416 175 append(old.rawBuf(), old.len_);
ad80164a 176}
177
30abd221 178void
179String::absorb(String &old)
73d41272 180{
30abd221 181 clean();
e7e1bf60 182 setBuffer(old.buf_, old.size_);
30abd221 183 len_ = old.len_;
184 old.size_ = 0;
aee3523a 185 old.buf_ = nullptr;
30abd221 186 old.len_ = 0;
73d41272 187}
188
9b558d8a 189String
a7a42b14 190String::substr(String::size_type from, String::size_type to) const
9b558d8a 191{
1545d2d1
AJ
192// Must(from >= 0 && from < size());
193 Must(from < size());
9b558d8a
FC
194 Must(to > 0 && to <= size());
195 Must(to > from);
196
197 String rv;
2fe0439c 198 rv.assign(rawBuf()+from, to-from);
9b558d8a
FC
199 return rv;
200}
201
f63c4b05
AJ
202void
203String::cut(String::size_type newLength)
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
217/// compare NULL and empty strings because str*cmp() may fail on NULL strings
218/// and because we need to return consistent results for strncmp(count == 0).
219static bool
220nilCmp(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
235int
236String::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
245int
246String::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
255int
256String::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
265int
266String::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
275int
276String::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
30abd221 285/* TODO: move onto String */
286int
287stringHasWhitespace(const char *s)
288{
aee3523a 289 return strpbrk(s, w_space) != nullptr;
30abd221 290}
291
292/* TODO: move onto String */
293int
294stringHasCntl(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
ad80164a 309/*
310 * Similar to strtok, but has some rudimentary knowledge
311 * of quoting
312 */
313char *
314strwordtok(char *buf, char **t)
315{
aee3523a 316 unsigned char *word = nullptr;
ad80164a 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))
5db6bf73 329 ++p;
ad80164a 330
331 if (!*p)
332 goto error;
333
334 word = d = p;
335
336 while ((ch = *p)) {
337 switch (ch) {
338
339 case '\\':
b48a944e
AJ
340 if (quoted)
341 ++p;
ad80164a 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
5db6bf73
FC
362 *d = ch;
363 ++d;
ad80164a 364
365 if (ch)
5db6bf73 366 ++p;
ad80164a 367
368 break;
369
370 case '"':
371 quoted = !quoted;
372
5db6bf73 373 ++p;
ad80164a 374
375 break;
376
377 default:
378 if (!quoted && xisspace(*p)) {
5db6bf73 379 ++p;
ad80164a 380 goto done;
381 }
382
aec55359
FC
383 *d = *p;
384 ++d;
385 ++p;
ad80164a 386 break;
387 }
388 }
389
390done:
5db6bf73 391 *d = '\0';
ad80164a 392
393error:
394 *t = (char *) p;
395 return (char *) word;
396}
397
30abd221 398const char *
399checkNullString(const char *p)
400{
401 return p ? p : "(NULL)";
402}
403
826a1fed
FC
404const char *
405String::pos(char const *aString) const
406{
4f4611bf 407 if (undefined())
aee3523a 408 return nullptr;
826a1fed
FC
409 return strstr(termedBuf(), aString);
410}
411
412const char *
413String::pos(char const ch) const
414{
4f4611bf 415 if (undefined())
aee3523a 416 return nullptr;
826a1fed
FC
417 return strchr(termedBuf(), ch);
418}
419
420const char *
421String::rpos(char const ch) const
422{
4f4611bf 423 if (undefined())
aee3523a 424 return nullptr;
826a1fed
FC
425 return strrchr(termedBuf(), (ch));
426}
427
428String::size_type
429String::find(char const ch) const
430{
431 const char *c;
432 c=pos(ch);
aee3523a 433 if (c==nullptr)
826a1fed
FC
434 return npos;
435 return c-rawBuf();
436}
437
438String::size_type
439String::find(char const *aString) const
440{
441 const char *c;
442 c=pos(aString);
aee3523a 443 if (c==nullptr)
826a1fed
FC
444 return npos;
445 return c-rawBuf();
446}
447
448String::size_type
449String::rfind(char const ch) const
450{
451 const char *c;
452 c=rpos(ch);
aee3523a 453 if (c==nullptr)
826a1fed
FC
454 return npos;
455 return c-rawBuf();
456}
457