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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors