]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/String.cc
2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 67 String */
12 #include "base/TextException.h"
13 #include "mgr/Registration.h"
14 #include "profiler/Profiler.h"
19 // low-level buffer allocation,
20 // does not free old buffer and does not adjust or look at len_
22 String::allocBuffer(String::size_type sz
)
24 PROF_start(StringInitBuf
);
26 char *newBuffer
= (char*)memAllocString(sz
, &sz
);
27 setBuffer(newBuffer
, sz
);
28 PROF_stop(StringInitBuf
);
31 // low-level buffer assignment
32 // does not free old buffer and does not adjust or look at len_
34 String::setBuffer(char *aBuf
, String::size_type aSize
)
37 assert(aSize
<= SizeMax_
);
45 StringRegistry::Instance().add(this);
49 String::String(char const *aString
)
52 allocAndFill(aString
, strlen(aString
));
54 StringRegistry::Instance().add(this);
59 String::operator =(char const *aString
)
66 String::operator =(String
const &old
)
68 clean(); // TODO: optimize to avoid cleaning the buffer we can use
70 allocAndFill(old
.rawBuf(), old
.size());
75 String::operator ==(String
const &that
) const
77 if (0 == this->cmp(that
))
84 String::operator !=(String
const &that
) const
86 if (0 == this->cmp(that
))
92 // public interface, makes sure that we clean the old buffer first
94 String::assign(const char *str
, int len
)
96 clean(); // TODO: optimize to avoid cleaning the buffer we can use
97 allocAndFill(str
, len
);
100 // Allocates the buffer to fit the supplied string and fills it.
103 String::allocAndFill(const char *str
, int len
)
105 PROF_start(StringAllocAndFill
);
107 allocBuffer(len
+ 1);
109 memcpy(buf_
, str
, len
);
111 PROF_stop(StringAllocAndFill
);
114 String::String(String
const &old
) : size_(0), len_(0), buf_(NULL
)
117 allocAndFill(old
.rawBuf(), old
.size());
120 StringRegistry::Instance().add(this);
127 PROF_start(StringClean
);
129 /* TODO if mempools has already closed this will FAIL!! */
131 memFreeString(size_
, buf_
);
138 PROF_stop(StringClean
);
146 StringRegistry::Instance().remove(this);
151 String::reset(char const *str
)
153 PROF_start(StringReset
);
154 clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
156 allocAndFill(str
, strlen(str
));
157 PROF_stop(StringReset
);
161 String::append( char const *str
, int len
)
163 assert(str
&& len
>= 0);
165 PROF_start(StringAppend
);
166 if (len_
+ len
+ 1 /*'\0'*/ < size_
) {
167 xstrncpy(buf_
+len_
, str
, len
+1);
170 // Create a temporary string and absorb it later.
172 assert(canGrowBy(len
)); // otherwise snew.len_ may overflow below
173 snew
.len_
= len_
+ len
;
174 snew
.allocBuffer(snew
.len_
+ 1);
177 memcpy(snew
.buf_
, rawBuf(), len_
);
180 memcpy(snew
.buf_
+ len_
, str
, len
);
182 snew
.buf_
[snew
.len_
] = '\0';
186 PROF_stop(StringAppend
);
190 String::append(char const *str
)
193 append(str
, strlen(str
));
197 String::append(char const chr
)
206 String::append(String
const &old
)
208 append(old
.rawBuf(), old
.len_
);
212 String::absorb(String
&old
)
215 setBuffer(old
.buf_
, old
.size_
);
223 String::substr(String::size_type from
, String::size_type to
) const
225 // Must(from >= 0 && from < size());
227 Must(to
> 0 && to
<= size());
231 rv
.assign(rawBuf()+from
, to
-from
);
236 String::cut(String::size_type newLength
)
238 // size_type is size_t, unsigned. No need to check for newLength <0
239 if (newLength
> len_
) return;
243 // buf_ may be nullptr on zero-length strings.
244 if (len_
== 0 && !buf_
)
247 buf_
[newLength
] = '\0';
250 /// compare NULL and empty strings because str*cmp() may fail on NULL strings
251 /// and because we need to return consistent results for strncmp(count == 0).
253 nilCmp(const bool thisIsNilOrEmpty
, const bool otherIsNilOrEmpty
, int &result
)
255 if (!thisIsNilOrEmpty
&& !otherIsNilOrEmpty
)
256 return false; // result does not matter
258 if (thisIsNilOrEmpty
&& otherIsNilOrEmpty
)
260 else if (thisIsNilOrEmpty
)
262 else // otherIsNilOrEmpty
269 String::cmp(char const *aString
) const
272 if (nilCmp(!size(), (!aString
|| !*aString
), result
))
275 return strcmp(termedBuf(), aString
);
279 String::cmp(char const *aString
, String::size_type count
) const
282 if (nilCmp((!size() || !count
), (!aString
|| !*aString
|| !count
), result
))
285 return strncmp(termedBuf(), aString
, count
);
289 String::cmp(String
const &aString
) const
292 if (nilCmp(!size(), !aString
.size(), result
))
295 return strcmp(termedBuf(), aString
.termedBuf());
299 String::caseCmp(char const *aString
) const
302 if (nilCmp(!size(), (!aString
|| !*aString
), result
))
305 return strcasecmp(termedBuf(), aString
);
309 String::caseCmp(char const *aString
, String::size_type count
) const
312 if (nilCmp((!size() || !count
), (!aString
|| !*aString
|| !count
), result
))
315 return strncasecmp(termedBuf(), aString
, count
);
320 String::stat(StoreEntry
*entry
) const
322 storeAppendPrintf(entry
, "%p : %d/%d \"%.*s\"\n",this,len_
, size_
, size(), rawBuf());
326 StringRegistry::Instance()
333 ptrcmp(C
const &lhs
, C
const &rhs
)
338 StringRegistry::StringRegistry()
341 Mgr::RegisterAction("strings",
342 "Strings in use in squid", Stat
, 0, 1);
347 StringRegistry::add(String
const *entry
)
349 entries
.insert(entry
, ptrcmp
);
353 StringRegistry::remove(String
const *entry
)
355 entries
.remove(entry
, ptrcmp
);
358 StringRegistry
StringRegistry::Instance_
;
360 String::size_type
memStringCount();
363 StringRegistry::Stat(StoreEntry
*entry
)
365 storeAppendPrintf(entry
, "%lu entries, %lu reported from MemPool\n", (unsigned long) Instance().entries
.elements
, (unsigned long) memStringCount());
366 Instance().entries
.head
->walk(Stater
, entry
);
370 StringRegistry::Stater(String
const * const & nodedata
, void *state
)
372 StoreEntry
*entry
= (StoreEntry
*) state
;
373 nodedata
->stat(entry
);
378 /* TODO: move onto String */
380 stringHasWhitespace(const char *s
)
382 return strpbrk(s
, w_space
) != NULL
;
385 /* TODO: move onto String */
387 stringHasCntl(const char *s
)
391 while ((c
= (unsigned char) *s
++) != '\0') {
395 if (c
>= 0x7f && c
<= 0x9f)
403 * Similar to strtok, but has some rudimentary knowledge
407 strwordtok(char *buf
, char **t
)
409 unsigned char *word
= NULL
;
410 unsigned char *p
= (unsigned char *) buf
;
416 p
= (unsigned char *) *t
;
421 while (*p
&& xisspace(*p
))
471 if (!quoted
&& xisspace(*p
)) {
488 return (char *) word
;
492 checkNullString(const char *p
)
494 return p
? p
: "(NULL)";
498 String::pos(char const *aString
) const
502 return strstr(termedBuf(), aString
);
506 String::pos(char const ch
) const
510 return strchr(termedBuf(), ch
);
514 String::rpos(char const ch
) const
518 return strrchr(termedBuf(), (ch
));
522 String::find(char const ch
) const
532 String::find(char const *aString
) const
542 String::rfind(char const ch
) const