]> git.ipfire.org Git - thirdparty/squid.git/blame - src/String.cc
String 'call duplication' optimization(?) bypassed calling String::init()
[thirdparty/squid.git] / src / String.cc
CommitLineData
ad80164a 1
2/*
dcb1fef8 3 * $Id: String.cc,v 1.28 2008/01/23 19:24:14 rousskov Exp $
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.
24 *
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.
29 *
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
36#include "squid.h"
ad80164a 37#include "Store.h"
38
39void
30abd221 40String::initBuf(size_t sz)
ad80164a 41{
42 PROF_start(StringInitBuf);
5c3b79c8 43 clean();
30abd221 44 buf((char *)memAllocString(sz, &sz));
ad80164a 45 assert(sz < 65536);
30abd221 46 size_ = sz;
ad80164a 47 PROF_stop(StringInitBuf);
48}
49
50void
30abd221 51String::init(char const *str)
ad80164a 52{
53 assert(this);
54
55 PROF_start(StringInit);
ad80164a 56 if (str)
57 limitInit(str, strlen(str));
58 else
30abd221 59 clean();
ad80164a 60 PROF_stop(StringInit);
61}
62
30abd221 63String::String (char const *aString) : size_(0), len_(0), buf_(NULL)
ad80164a 64{
30abd221 65 init (aString);
ad80164a 66#if DEBUGSTRINGS
67
30abd221 68 StringRegistry::Instance().add(this);
ad80164a 69#endif
70}
71
30abd221 72String &
73String::operator =(char const *aString)
ad80164a 74{
5c3b79c8 75 init(aString);
ad80164a 76 return *this;
77}
78
30abd221 79String &
80String::operator = (String const &old)
ad80164a 81{
30abd221 82 clean ();
83
5c3b79c8 84 if(old.size() > 0)
85 limitInit(old.buf(), old.size());
ad80164a 86
87 return *this;
88}
89
90bool
30abd221 91String::operator == (String const &that) const
ad80164a 92{
30abd221 93 if (0 == this->cmp(that))
94 return true;
ad80164a 95
30abd221 96 return false;
ad80164a 97}
98
99bool
30abd221 100String::operator != (String const &that) const
ad80164a 101{
30abd221 102 if (0 == this->cmp(that))
103 return false;
104
105 return true;
ad80164a 106}
107
30abd221 108void
109String::limitInit(const char *str, int len)
ad80164a 110{
30abd221 111 PROF_start(StringLimitInit);
112 assert(this && str);
113 initBuf(len + 1);
114 len_ = len;
115 xmemcpy(buf_, str, len);
116 buf_[len] = '\0';
117 PROF_stop(StringLimitInit);
ad80164a 118}
119
30abd221 120String::String (String const &old) : size_(0), len_(0), buf_(NULL)
ad80164a 121{
dcb1fef8 122 if (old.size() > 0)
123 limitInit(old.buf(), old.size());
30abd221 124#if DEBUGSTRINGS
125
126 StringRegistry::Instance().add(this);
127#endif
ad80164a 128}
129
30abd221 130void
131String::clean()
ad80164a 132{
30abd221 133 PROF_start(StringClean);
134 assert(this);
135
136 if (buf())
137 memFreeString(size_, buf_);
138
139 len_ = 0;
140
141 size_ = 0;
142
143 buf_ = NULL;
144 PROF_stop(StringClean);
ad80164a 145}
146
30abd221 147String::~String()
ad80164a 148{
30abd221 149 clean();
ad80164a 150#if DEBUGSTRINGS
151
30abd221 152 StringRegistry::Instance().remove(this);
ad80164a 153#endif
154}
155
156void
30abd221 157String::reset(const char *str)
158{
159 PROF_start(StringReset);
30abd221 160 init(str);
161 PROF_stop(StringReset);
162}
163
164void
165String::append(const char *str, int len)
ad80164a 166{
167 assert(this);
30abd221 168 assert(str && len >= 0);
ad80164a 169
170 PROF_start(StringAppend);
30abd221 171 if (len_ + len < size_) {
172 strncat(buf_, str, len);
ad80164a 173 len_ += len;
174 } else {
30abd221 175 String snew;
176 snew.len_ = len_ + len;
177 snew.initBuf(snew.len_ + 1);
ad80164a 178
179 if (buf_)
30abd221 180 xmemcpy(snew.buf_, buf(), len_);
ad80164a 181
182 if (len)
30abd221 183 xmemcpy(snew.buf_ + len_, str, len);
ad80164a 184
30abd221 185 snew.buf_[snew.len_] = '\0';
ad80164a 186
30abd221 187 absorb(snew);
ad80164a 188 }
189 PROF_stop(StringAppend);
190}
191
192void
30abd221 193String::append(char const *str)
ad80164a 194{
30abd221 195 assert (str);
ad80164a 196 append (str, strlen(str));
197}
198
199void
30abd221 200String::append (char chr)
ad80164a 201{
202 char myString[2];
203 myString[0]=chr;
204 myString[1]='\0';
205 append (myString, 1);
206}
207
208void
30abd221 209String::append(String const &old)
ad80164a 210{
30abd221 211 append (old.buf(), old.len_);
ad80164a 212}
213
30abd221 214void
215String::absorb(String &old)
73d41272 216{
30abd221 217 clean();
218 size_ = old.size_;
219 buf (old.buf_);
220 len_ = old.len_;
221 old.size_ = 0;
222 old.buf_ = NULL;
223 old.len_ = 0;
73d41272 224}
225
30abd221 226void
227String::buf(char *newBuf)
ad80164a 228{
30abd221 229 assert (buf_ == NULL);
230 buf_ = newBuf;
ad80164a 231}
232
233#if DEBUGSTRINGS
234void
30abd221 235String::stat(StoreEntry *entry) const
ad80164a 236{
30abd221 237 storeAppendPrintf(entry, "%p : %d/%d \"%s\"\n",this,len_, size_, buf());
ad80164a 238}
239
30abd221 240StringRegistry &
241StringRegistry::Instance()
ad80164a 242{
243 return Instance_;
244}
245
246template <class C>
247int
248ptrcmp(C const &lhs, C const &rhs)
249{
250 return lhs - rhs;
251}
252
253void
30abd221 254StringRegistry::registerWithCacheManager(CacheManager & manager)
ad80164a 255{
256 manager.registerAction("strings",
257 "Strings in use in squid", Stat, 0, 1);
258}
259
260void
30abd221 261
262StringRegistry::add
263 (String const *entry)
ad80164a 264{
265 entries.insert(entry, ptrcmp);
266}
267
268void
30abd221 269
270StringRegistry::remove
271 (String const *entry)
ad80164a 272{
273 entries.remove(entry, ptrcmp);
274}
275
30abd221 276StringRegistry StringRegistry::Instance_;
ad80164a 277
278extern size_t memStringCount();
279
280void
30abd221 281StringRegistry::Stat(StoreEntry *entry)
ad80164a 282{
283 storeAppendPrintf(entry, "%lu entries, %lu reported from MemPool\n", (unsigned long) Instance().entries.elements, (unsigned long) memStringCount());
284 Instance().entries.head->walk(Stater, entry);
285}
286
287void
30abd221 288StringRegistry::Stater(String const * const & nodedata, void *state)
ad80164a 289{
290 StoreEntry *entry = (StoreEntry *) state;
291 nodedata->stat(entry);
292}
293
294#endif
295
30abd221 296/* TODO: move onto String */
297int
298stringHasWhitespace(const char *s)
299{
300 return strpbrk(s, w_space) != NULL;
301}
302
303/* TODO: move onto String */
304int
305stringHasCntl(const char *s)
306{
307 unsigned char c;
308
309 while ((c = (unsigned char) *s++) != '\0') {
310 if (c <= 0x1f)
311 return 1;
312
313 if (c >= 0x7f && c <= 0x9f)
314 return 1;
315 }
316
317 return 0;
318}
319
ad80164a 320/*
321 * Similar to strtok, but has some rudimentary knowledge
322 * of quoting
323 */
324char *
325strwordtok(char *buf, char **t)
326{
327 unsigned char *word = NULL;
328 unsigned char *p = (unsigned char *) buf;
329 unsigned char *d;
330 unsigned char ch;
331 int quoted = 0;
332
333 if (!p)
334 p = (unsigned char *) *t;
335
336 if (!p)
337 goto error;
338
339 while (*p && xisspace(*p))
340 p++;
341
342 if (!*p)
343 goto error;
344
345 word = d = p;
346
347 while ((ch = *p)) {
348 switch (ch) {
349
350 case '\\':
351 p++;
352
353 switch (*p) {
354
355 case 'n':
356 ch = '\n';
357
358 break;
359
360 case 'r':
361 ch = '\r';
362
363 break;
364
365 default:
366 ch = *p;
367
368 break;
369
370 }
371
372 *d++ = ch;
373
374 if (ch)
375 p++;
376
377 break;
378
379 case '"':
380 quoted = !quoted;
381
382 p++;
383
384 break;
385
386 default:
387 if (!quoted && xisspace(*p)) {
388 p++;
389 goto done;
390 }
391
392 *d++ = *p++;
393 break;
394 }
395 }
396
397done:
398 *d++ = '\0';
399
400error:
401 *t = (char *) p;
402 return (char *) word;
403}
404
30abd221 405const char *
406checkNullString(const char *p)
407{
408 return p ? p : "(NULL)";
409}
410
ad80164a 411#ifndef _USE_INLINE_
30abd221 412#include "String.cci"
ad80164a 413#endif