]> git.ipfire.org Git - thirdparty/squid.git/blame - src/String.cc
Removed squid-old.h
[thirdparty/squid.git] / src / String.cc
CommitLineData
ad80164a 1
2/*
262a0e14 3 * $Id$
ad80164a 4 *
5 * DEBUG: section 67 String
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
26ac0430 24 *
ad80164a 25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
26ac0430 29 *
ad80164a 30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
582c2af2 36#include "squid.h"
3d93a84d 37#include "base/TextException.h"
8822ebee 38#include "mgr/Registration.h"
582c2af2
FC
39#include "profiler/Profiler.h"
40#include "protos.h"
ad80164a 41#include "Store.h"
696a257c 42
582c2af2
FC
43#if HAVE_LIMITS_H
44#include <limits.h>
45#endif
46
696a257c
FC
47int
48String::psize() const
49{
50 Must(size() < INT_MAX);
51 return size();
52}
53
ad80164a 54
26ac0430 55// low-level buffer allocation,
e7e1bf60 56// does not free old buffer and does not adjust or look at len_
ad80164a 57void
a7a42b14 58String::allocBuffer(String::size_type sz)
ad80164a 59{
60 PROF_start(StringInitBuf);
cb3b44fc 61 assert (undefined());
e7e1bf60 62 char *newBuffer = (char*)memAllocString(sz, &sz);
63 setBuffer(newBuffer, sz);
ad80164a 64 PROF_stop(StringInitBuf);
65}
66
e7e1bf60 67// low-level buffer assignment
68// does not free old buffer and does not adjust or look at len_
ad80164a 69void
a7a42b14 70String::setBuffer(char *aBuf, String::size_type aSize)
ad80164a 71{
cb3b44fc 72 assert(undefined());
e7e1bf60 73 assert(aSize < 65536);
74 buf_ = aBuf;
75 size_ = aSize;
ad80164a 76}
77
30abd221 78String::String (char const *aString) : size_(0), len_(0), buf_(NULL)
ad80164a 79{
e7e1bf60 80 if (aString)
81 allocAndFill(aString, strlen(aString));
ad80164a 82#if DEBUGSTRINGS
83
30abd221 84 StringRegistry::Instance().add(this);
ad80164a 85#endif
86}
87
30abd221 88String &
89String::operator =(char const *aString)
ad80164a 90{
e7e1bf60 91 reset(aString);
ad80164a 92 return *this;
93}
94
30abd221 95String &
96String::operator = (String const &old)
ad80164a 97{
e7e1bf60 98 clean(); // TODO: optimize to avoid cleaning the buffer we can use
99 if (old.size() > 0)
cb3b44fc 100 allocAndFill(old.rawBuf(), old.size());
ad80164a 101 return *this;
102}
103
104bool
30abd221 105String::operator == (String const &that) const
ad80164a 106{
30abd221 107 if (0 == this->cmp(that))
108 return true;
ad80164a 109
30abd221 110 return false;
ad80164a 111}
112
113bool
30abd221 114String::operator != (String const &that) const
ad80164a 115{
30abd221 116 if (0 == this->cmp(that))
117 return false;
118
119 return true;
ad80164a 120}
121
e7e1bf60 122// public interface, makes sure that we clean the old buffer first
30abd221 123void
124String::limitInit(const char *str, int len)
ad80164a 125{
e7e1bf60 126 clean(); // TODO: optimize to avoid cleaning the buffer we can use
127 allocAndFill(str, len);
128}
4fbc2a54 129
e7e1bf60 130// Allocates the buffer to fit the supplied string and fills it.
131// Does not clean.
132void
133String::allocAndFill(const char *str, int len)
134{
135 PROF_start(StringAllocAndFill);
136 assert(this && str);
137 allocBuffer(len + 1);
30abd221 138 len_ = len;
41d00cd3 139 memcpy(buf_, str, len);
30abd221 140 buf_[len] = '\0';
e7e1bf60 141 PROF_stop(StringAllocAndFill);
ad80164a 142}
143
30abd221 144String::String (String const &old) : size_(0), len_(0), buf_(NULL)
ad80164a 145{
dcb1fef8 146 if (old.size() > 0)
cb3b44fc 147 allocAndFill(old.rawBuf(), old.size());
30abd221 148#if DEBUGSTRINGS
149
150 StringRegistry::Instance().add(this);
151#endif
ad80164a 152}
153
30abd221 154void
155String::clean()
ad80164a 156{
30abd221 157 PROF_start(StringClean);
158 assert(this);
159
8536ad02 160 /* TODO if mempools has already closed this will FAIL!! */
cb3b44fc 161 if (defined())
30abd221 162 memFreeString(size_, buf_);
163
164 len_ = 0;
165
166 size_ = 0;
167
168 buf_ = NULL;
169 PROF_stop(StringClean);
ad80164a 170}
171
30abd221 172String::~String()
ad80164a 173{
30abd221 174 clean();
ad80164a 175#if DEBUGSTRINGS
176
30abd221 177 StringRegistry::Instance().remove(this);
ad80164a 178#endif
179}
180
181void
30abd221 182String::reset(const char *str)
183{
184 PROF_start(StringReset);
e7e1bf60 185 clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
186 if (str)
187 allocAndFill(str, strlen(str));
30abd221 188 PROF_stop(StringReset);
189}
190
191void
192String::append(const char *str, int len)
ad80164a 193{
194 assert(this);
30abd221 195 assert(str && len >= 0);
ad80164a 196
197 PROF_start(StringAppend);
30abd221 198 if (len_ + len < size_) {
199 strncat(buf_, str, len);
ad80164a 200 len_ += len;
201 } else {
e7e1bf60 202 // Create a temporary string and absorb it later.
30abd221 203 String snew;
44c26431 204 assert(len_ + len < 65536); // otherwise snew.len_ overflows below
30abd221 205 snew.len_ = len_ + len;
e7e1bf60 206 snew.allocBuffer(snew.len_ + 1);
ad80164a 207
e7e1bf60 208 if (len_)
41d00cd3 209 memcpy(snew.buf_, rawBuf(), len_);
ad80164a 210
211 if (len)
41d00cd3 212 memcpy(snew.buf_ + len_, str, len);
ad80164a 213
30abd221 214 snew.buf_[snew.len_] = '\0';
ad80164a 215
30abd221 216 absorb(snew);
ad80164a 217 }
218 PROF_stop(StringAppend);
219}
220
221void
30abd221 222String::append(char const *str)
ad80164a 223{
30abd221 224 assert (str);
ad80164a 225 append (str, strlen(str));
226}
227
228void
30abd221 229String::append (char chr)
ad80164a 230{
231 char myString[2];
232 myString[0]=chr;
233 myString[1]='\0';
234 append (myString, 1);
235}
236
237void
30abd221 238String::append(String const &old)
ad80164a 239{
cb3b44fc 240 append (old.rawBuf(), old.len_);
ad80164a 241}
242
30abd221 243void
244String::absorb(String &old)
73d41272 245{
30abd221 246 clean();
e7e1bf60 247 setBuffer(old.buf_, old.size_);
30abd221 248 len_ = old.len_;
249 old.size_ = 0;
250 old.buf_ = NULL;
251 old.len_ = 0;
73d41272 252}
253
9b558d8a 254String
a7a42b14 255String::substr(String::size_type from, String::size_type to) const
9b558d8a 256{
1545d2d1
AJ
257// Must(from >= 0 && from < size());
258 Must(from < size());
9b558d8a
FC
259 Must(to > 0 && to <= size());
260 Must(to > from);
261
262 String rv;
263 rv.limitInit(rawBuf()+from,to-from);
264 return rv;
265}
266
267
ad80164a 268#if DEBUGSTRINGS
269void
30abd221 270String::stat(StoreEntry *entry) const
ad80164a 271{
cb3b44fc 272 storeAppendPrintf(entry, "%p : %d/%d \"%.*s\"\n",this,len_, size_, size(), rawBuf());
ad80164a 273}
274
30abd221 275StringRegistry &
276StringRegistry::Instance()
ad80164a 277{
278 return Instance_;
279}
280
281template <class C>
282int
283ptrcmp(C const &lhs, C const &rhs)
284{
285 return lhs - rhs;
286}
287
6852be71 288StringRegistry::StringRegistry()
ad80164a 289{
6852be71 290#if DEBUGSTRINGS
8822ebee 291 Mgr::RegisterAction("strings",
d9fc6862 292 "Strings in use in squid", Stat, 0, 1);
6852be71 293#endif
ad80164a 294}
295
296void
6ca34f6f 297StringRegistry::add(String const *entry)
ad80164a 298{
299 entries.insert(entry, ptrcmp);
300}
301
302void
6ca34f6f 303StringRegistry::remove(String const *entry)
ad80164a 304{
305 entries.remove(entry, ptrcmp);
306}
307
30abd221 308StringRegistry StringRegistry::Instance_;
ad80164a 309
a7a42b14 310extern String::size_type memStringCount();
ad80164a 311
312void
30abd221 313StringRegistry::Stat(StoreEntry *entry)
ad80164a 314{
315 storeAppendPrintf(entry, "%lu entries, %lu reported from MemPool\n", (unsigned long) Instance().entries.elements, (unsigned long) memStringCount());
316 Instance().entries.head->walk(Stater, entry);
317}
318
319void
30abd221 320StringRegistry::Stater(String const * const & nodedata, void *state)
ad80164a 321{
322 StoreEntry *entry = (StoreEntry *) state;
323 nodedata->stat(entry);
324}
325
326#endif
327
30abd221 328/* TODO: move onto String */
329int
330stringHasWhitespace(const char *s)
331{
332 return strpbrk(s, w_space) != NULL;
333}
334
335/* TODO: move onto String */
336int
337stringHasCntl(const char *s)
338{
339 unsigned char c;
340
341 while ((c = (unsigned char) *s++) != '\0') {
342 if (c <= 0x1f)
343 return 1;
344
345 if (c >= 0x7f && c <= 0x9f)
346 return 1;
347 }
348
349 return 0;
350}
351
ad80164a 352/*
353 * Similar to strtok, but has some rudimentary knowledge
354 * of quoting
355 */
356char *
357strwordtok(char *buf, char **t)
358{
359 unsigned char *word = NULL;
360 unsigned char *p = (unsigned char *) buf;
361 unsigned char *d;
362 unsigned char ch;
363 int quoted = 0;
364
365 if (!p)
366 p = (unsigned char *) *t;
367
368 if (!p)
369 goto error;
370
371 while (*p && xisspace(*p))
5db6bf73 372 ++p;
ad80164a 373
374 if (!*p)
375 goto error;
376
377 word = d = p;
378
379 while ((ch = *p)) {
380 switch (ch) {
381
382 case '\\':
5db6bf73 383 ++p;
ad80164a 384
385 switch (*p) {
386
387 case 'n':
388 ch = '\n';
389
390 break;
391
392 case 'r':
393 ch = '\r';
394
395 break;
396
397 default:
398 ch = *p;
399
400 break;
401
402 }
403
5db6bf73
FC
404 *d = ch;
405 ++d;
ad80164a 406
407 if (ch)
5db6bf73 408 ++p;
ad80164a 409
410 break;
411
412 case '"':
413 quoted = !quoted;
414
5db6bf73 415 ++p;
ad80164a 416
417 break;
418
419 default:
420 if (!quoted && xisspace(*p)) {
5db6bf73 421 ++p;
ad80164a 422 goto done;
423 }
424
aec55359
FC
425 *d = *p;
426 ++d;
427 ++p;
ad80164a 428 break;
429 }
430 }
431
432done:
5db6bf73 433 *d = '\0';
ad80164a 434
435error:
436 *t = (char *) p;
437 return (char *) word;
438}
439
30abd221 440const char *
441checkNullString(const char *p)
442{
443 return p ? p : "(NULL)";
444}
445
826a1fed
FC
446const char *
447String::pos(char const *aString) const
448{
4f4611bf
FC
449 if (undefined())
450 return NULL;
826a1fed
FC
451 return strstr(termedBuf(), aString);
452}
453
454const char *
455String::pos(char const ch) const
456{
4f4611bf
FC
457 if (undefined())
458 return NULL;
826a1fed
FC
459 return strchr(termedBuf(), ch);
460}
461
462const char *
463String::rpos(char const ch) const
464{
4f4611bf
FC
465 if (undefined())
466 return NULL;
826a1fed
FC
467 return strrchr(termedBuf(), (ch));
468}
469
470String::size_type
471String::find(char const ch) const
472{
473 const char *c;
474 c=pos(ch);
475 if (c==NULL)
476 return npos;
477 return c-rawBuf();
478}
479
480String::size_type
481String::find(char const *aString) const
482{
483 const char *c;
484 c=pos(aString);
485 if (c==NULL)
486 return npos;
487 return c-rawBuf();
488}
489
490String::size_type
491String::rfind(char const ch) const
492{
493 const char *c;
494 c=rpos(ch);
495 if (c==NULL)
496 return npos;
497 return c-rawBuf();
498}
499
500
9b558d8a 501
32d002cb 502#if !_USE_INLINE_
30abd221 503#include "String.cci"
ad80164a 504#endif