]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/String.cc
45e24c94828b90130d427a161622b6f7f6214bcf
2 * Copyright (C) 1996-2025 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.
10 #include "mem/forward.h"
11 #include "sbuf/SBuf.h"
12 #include "SquidString.h"
16 // low-level buffer allocation,
17 // does not free old buffer and does not adjust or look at len_
19 String::allocBuffer(String::size_type sz
)
22 auto *newBuffer
= static_cast<char*>(memAllocBuf(sz
, &sz
));
23 setBuffer(newBuffer
, sz
);
26 // low-level buffer assignment
27 // does not free old buffer and does not adjust or look at len_
29 String::setBuffer(char *aBuf
, String::size_type aSize
)
32 assert(aSize
<= SizeMax_
);
37 String::String(char const *aString
)
40 allocAndFill(aString
, strlen(aString
));
44 String::operator =(char const *aString
)
51 String::operator =(String
const &old
)
53 clean(); // TODO: optimize to avoid cleaning the buffer we can use
55 allocAndFill(old
.rawBuf(), old
.size());
60 String::operator ==(String
const &that
) const
62 if (0 == this->cmp(that
))
69 String::operator !=(String
const &that
) const
71 if (0 == this->cmp(that
))
77 // public interface, makes sure that we clean the old buffer first
79 String::assign(const char *str
, int len
)
81 clean(); // TODO: optimize to avoid cleaning the buffer we can use
82 allocAndFill(str
, len
);
85 // Allocates the buffer to fit the supplied string and fills it.
88 String::allocAndFill(const char *str
, int len
)
93 memcpy(buf_
, str
, len
);
97 String::String(String
const &old
) : size_(0), len_(0), buf_(nullptr)
100 allocAndFill(old
.rawBuf(), old
.size());
106 /* TODO if mempools has already closed this will FAIL!! */
108 memFreeBuf(size_
, buf_
);
123 String::reset(char const *str
)
125 clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
127 allocAndFill(str
, strlen(str
));
131 String::append( char const *str
, int len
)
133 assert(str
&& len
>= 0);
135 if (len_
+ len
+ 1 /*'\0'*/ < size_
) {
136 xstrncpy(buf_
+len_
, str
, len
+1);
139 // Create a temporary string and absorb it later.
141 assert(canGrowBy(len
)); // otherwise snew.len_ may overflow below
142 snew
.len_
= len_
+ len
;
143 snew
.allocBuffer(snew
.len_
+ 1);
146 memcpy(snew
.buf_
, rawBuf(), len_
);
149 memcpy(snew
.buf_
+ len_
, str
, len
);
151 snew
.buf_
[snew
.len_
] = '\0';
158 String::append(char const *str
)
161 append(str
, strlen(str
));
165 String::append(char const chr
)
174 String::append(String
const &old
)
176 append(old
.rawBuf(), old
.len_
);
180 String::append(const SBuf
&buf
)
182 append(buf
.rawContent(), buf
.length());
186 String::absorb(String
&old
)
189 setBuffer(old
.buf_
, old
.size_
);
197 String::substr(String::size_type from
, String::size_type to
) const
199 // Must(from >= 0 && from < size());
201 Must(to
> 0 && to
<= size());
205 rv
.assign(rawBuf()+from
, to
-from
);
210 String::cut(String::size_type newLength
)
212 // size_type is size_t, unsigned. No need to check for newLength <0
213 if (newLength
> len_
) return;
217 // buf_ may be nullptr on zero-length strings.
218 if (len_
== 0 && !buf_
)
221 buf_
[newLength
] = '\0';
224 /// compare NULL and empty strings because str*cmp() may fail on NULL strings
225 /// and because we need to return consistent results for strncmp(count == 0).
227 nilCmp(const bool thisIsNilOrEmpty
, const bool otherIsNilOrEmpty
, int &result
)
229 if (!thisIsNilOrEmpty
&& !otherIsNilOrEmpty
)
230 return false; // result does not matter
232 if (thisIsNilOrEmpty
&& otherIsNilOrEmpty
)
234 else if (thisIsNilOrEmpty
)
236 else // otherIsNilOrEmpty
243 String::cmp(char const *aString
) const
246 if (nilCmp(!size(), (!aString
|| !*aString
), result
))
249 return strcmp(termedBuf(), aString
);
253 String::cmp(char const *aString
, String::size_type count
) const
256 if (nilCmp((!size() || !count
), (!aString
|| !*aString
|| !count
), result
))
259 return strncmp(termedBuf(), aString
, count
);
263 String::cmp(String
const &aString
) const
266 if (nilCmp(!size(), !aString
.size(), result
))
269 return strcmp(termedBuf(), aString
.termedBuf());
273 String::caseCmp(char const *aString
) const
276 if (nilCmp(!size(), (!aString
|| !*aString
), result
))
279 return strcasecmp(termedBuf(), aString
);
283 String::caseCmp(char const *aString
, String::size_type count
) const
286 if (nilCmp((!size() || !count
), (!aString
|| !*aString
|| !count
), result
))
289 return strncasecmp(termedBuf(), aString
, count
);
292 /* TODO: move onto String */
294 stringHasWhitespace(const char *s
)
296 return strpbrk(s
, w_space
) != nullptr;
299 /* TODO: move onto String */
301 stringHasCntl(const char *s
)
305 while ((c
= (unsigned char) *s
++) != '\0') {
309 if (c
>= 0x7f && c
<= 0x9f)
317 * Similar to strtok, but has some rudimentary knowledge
321 strwordtok(char *buf
, char **t
)
323 unsigned char *word
= nullptr;
324 unsigned char *p
= (unsigned char *) buf
;
330 p
= (unsigned char *) *t
;
335 while (*p
&& xisspace(*p
))
385 if (!quoted
&& xisspace(*p
)) {
402 return (char *) word
;
406 checkNullString(const char *p
)
408 return p
? p
: "(NULL)";
412 String::pos(char const *aString
) const
416 return strstr(termedBuf(), aString
);
420 String::pos(char const ch
) const
424 return strchr(termedBuf(), ch
);
428 String::rpos(char const ch
) const
432 return strrchr(termedBuf(), (ch
));
436 String::find(char const ch
) const
446 String::find(char const *aString
) const
456 String::rfind(char const ch
) const