]> git.ipfire.org Git - thirdparty/squid.git/blob - src/String.cc
Converted many #ifdefs to #ifs
[thirdparty/squid.git] / src / String.cc
1
2 /*
3 * $Id$
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"
37 #include "Store.h"
38 #include "TextException.h"
39
40 int
41 String::psize() const
42 {
43 Must(size() < INT_MAX);
44 return size();
45 }
46
47
48 // low-level buffer allocation,
49 // does not free old buffer and does not adjust or look at len_
50 void
51 String::allocBuffer(String::size_type sz)
52 {
53 PROF_start(StringInitBuf);
54 assert (undefined());
55 char *newBuffer = (char*)memAllocString(sz, &sz);
56 setBuffer(newBuffer, sz);
57 PROF_stop(StringInitBuf);
58 }
59
60 // low-level buffer assignment
61 // does not free old buffer and does not adjust or look at len_
62 void
63 String::setBuffer(char *aBuf, String::size_type aSize)
64 {
65 assert(undefined());
66 assert(aSize < 65536);
67 buf_ = aBuf;
68 size_ = aSize;
69 }
70
71 String::String (char const *aString) : size_(0), len_(0), buf_(NULL)
72 {
73 if (aString)
74 allocAndFill(aString, strlen(aString));
75 #if DEBUGSTRINGS
76
77 StringRegistry::Instance().add(this);
78 #endif
79 }
80
81 String &
82 String::operator =(char const *aString)
83 {
84 reset(aString);
85 return *this;
86 }
87
88 String &
89 String::operator = (String const &old)
90 {
91 clean(); // TODO: optimize to avoid cleaning the buffer we can use
92 if (old.size() > 0)
93 allocAndFill(old.rawBuf(), old.size());
94 return *this;
95 }
96
97 bool
98 String::operator == (String const &that) const
99 {
100 if (0 == this->cmp(that))
101 return true;
102
103 return false;
104 }
105
106 bool
107 String::operator != (String const &that) const
108 {
109 if (0 == this->cmp(that))
110 return false;
111
112 return true;
113 }
114
115 // public interface, makes sure that we clean the old buffer first
116 void
117 String::limitInit(const char *str, int len)
118 {
119 clean(); // TODO: optimize to avoid cleaning the buffer we can use
120 allocAndFill(str, len);
121 }
122
123 // Allocates the buffer to fit the supplied string and fills it.
124 // Does not clean.
125 void
126 String::allocAndFill(const char *str, int len)
127 {
128 PROF_start(StringAllocAndFill);
129 assert(this && str);
130 allocBuffer(len + 1);
131 len_ = len;
132 xmemcpy(buf_, str, len);
133 buf_[len] = '\0';
134 PROF_stop(StringAllocAndFill);
135 }
136
137 String::String (String const &old) : size_(0), len_(0), buf_(NULL)
138 {
139 if (old.size() > 0)
140 allocAndFill(old.rawBuf(), old.size());
141 #if DEBUGSTRINGS
142
143 StringRegistry::Instance().add(this);
144 #endif
145 }
146
147 void
148 String::clean()
149 {
150 PROF_start(StringClean);
151 assert(this);
152
153 /* TODO if mempools has already closed this will FAIL!! */
154 if (defined())
155 memFreeString(size_, buf_);
156
157 len_ = 0;
158
159 size_ = 0;
160
161 buf_ = NULL;
162 PROF_stop(StringClean);
163 }
164
165 String::~String()
166 {
167 clean();
168 #if DEBUGSTRINGS
169
170 StringRegistry::Instance().remove(this);
171 #endif
172 }
173
174 void
175 String::reset(const char *str)
176 {
177 PROF_start(StringReset);
178 clean(); // TODO: optimize to avoid cleaning the buffer if we can reuse it
179 if (str)
180 allocAndFill(str, strlen(str));
181 PROF_stop(StringReset);
182 }
183
184 void
185 String::append(const char *str, int len)
186 {
187 assert(this);
188 assert(str && len >= 0);
189
190 PROF_start(StringAppend);
191 if (len_ + len < size_) {
192 strncat(buf_, str, len);
193 len_ += len;
194 } else {
195 // Create a temporary string and absorb it later.
196 String snew;
197 assert(len_ + len < 65536); // otherwise snew.len_ overflows below
198 snew.len_ = len_ + len;
199 snew.allocBuffer(snew.len_ + 1);
200
201 if (len_)
202 xmemcpy(snew.buf_, rawBuf(), len_);
203
204 if (len)
205 xmemcpy(snew.buf_ + len_, str, len);
206
207 snew.buf_[snew.len_] = '\0';
208
209 absorb(snew);
210 }
211 PROF_stop(StringAppend);
212 }
213
214 void
215 String::append(char const *str)
216 {
217 assert (str);
218 append (str, strlen(str));
219 }
220
221 void
222 String::append (char chr)
223 {
224 char myString[2];
225 myString[0]=chr;
226 myString[1]='\0';
227 append (myString, 1);
228 }
229
230 void
231 String::append(String const &old)
232 {
233 append (old.rawBuf(), old.len_);
234 }
235
236 void
237 String::absorb(String &old)
238 {
239 clean();
240 setBuffer(old.buf_, old.size_);
241 len_ = old.len_;
242 old.size_ = 0;
243 old.buf_ = NULL;
244 old.len_ = 0;
245 }
246
247 String
248 String::substr(String::size_type from, String::size_type to) const
249 {
250 Must(from >= 0 && from < size());
251 Must(to > 0 && to <= size());
252 Must(to > from);
253
254 String rv;
255 rv.limitInit(rawBuf()+from,to-from);
256 return rv;
257 }
258
259
260 #if DEBUGSTRINGS
261 void
262 String::stat(StoreEntry *entry) const
263 {
264 storeAppendPrintf(entry, "%p : %d/%d \"%.*s\"\n",this,len_, size_, size(), rawBuf());
265 }
266
267 StringRegistry &
268 StringRegistry::Instance()
269 {
270 return Instance_;
271 }
272
273 template <class C>
274 int
275 ptrcmp(C const &lhs, C const &rhs)
276 {
277 return lhs - rhs;
278 }
279
280 StringRegistry::StringRegistry()
281 {
282 #if DEBUGSTRINGS
283 CacheManager::GetInstance()->registerAction("strings",
284 "Strings in use in squid", Stat, 0, 1);
285 #endif
286 }
287
288 void
289
290 StringRegistry::add
291 (String const *entry)
292 {
293 entries.insert(entry, ptrcmp);
294 }
295
296 void
297
298 StringRegistry::remove
299 (String const *entry)
300 {
301 entries.remove(entry, ptrcmp);
302 }
303
304 StringRegistry StringRegistry::Instance_;
305
306 extern String::size_type memStringCount();
307
308 void
309 StringRegistry::Stat(StoreEntry *entry)
310 {
311 storeAppendPrintf(entry, "%lu entries, %lu reported from MemPool\n", (unsigned long) Instance().entries.elements, (unsigned long) memStringCount());
312 Instance().entries.head->walk(Stater, entry);
313 }
314
315 void
316 StringRegistry::Stater(String const * const & nodedata, void *state)
317 {
318 StoreEntry *entry = (StoreEntry *) state;
319 nodedata->stat(entry);
320 }
321
322 #endif
323
324 /* TODO: move onto String */
325 int
326 stringHasWhitespace(const char *s)
327 {
328 return strpbrk(s, w_space) != NULL;
329 }
330
331 /* TODO: move onto String */
332 int
333 stringHasCntl(const char *s)
334 {
335 unsigned char c;
336
337 while ((c = (unsigned char) *s++) != '\0') {
338 if (c <= 0x1f)
339 return 1;
340
341 if (c >= 0x7f && c <= 0x9f)
342 return 1;
343 }
344
345 return 0;
346 }
347
348 /*
349 * Similar to strtok, but has some rudimentary knowledge
350 * of quoting
351 */
352 char *
353 strwordtok(char *buf, char **t)
354 {
355 unsigned char *word = NULL;
356 unsigned char *p = (unsigned char *) buf;
357 unsigned char *d;
358 unsigned char ch;
359 int quoted = 0;
360
361 if (!p)
362 p = (unsigned char *) *t;
363
364 if (!p)
365 goto error;
366
367 while (*p && xisspace(*p))
368 p++;
369
370 if (!*p)
371 goto error;
372
373 word = d = p;
374
375 while ((ch = *p)) {
376 switch (ch) {
377
378 case '\\':
379 p++;
380
381 switch (*p) {
382
383 case 'n':
384 ch = '\n';
385
386 break;
387
388 case 'r':
389 ch = '\r';
390
391 break;
392
393 default:
394 ch = *p;
395
396 break;
397
398 }
399
400 *d++ = ch;
401
402 if (ch)
403 p++;
404
405 break;
406
407 case '"':
408 quoted = !quoted;
409
410 p++;
411
412 break;
413
414 default:
415 if (!quoted && xisspace(*p)) {
416 p++;
417 goto done;
418 }
419
420 *d++ = *p++;
421 break;
422 }
423 }
424
425 done:
426 *d++ = '\0';
427
428 error:
429 *t = (char *) p;
430 return (char *) word;
431 }
432
433 const char *
434 checkNullString(const char *p)
435 {
436 return p ? p : "(NULL)";
437 }
438
439 const char *
440 String::pos(char const *aString) const
441 {
442 if (undefined())
443 return NULL;
444 return strstr(termedBuf(), aString);
445 }
446
447 const char *
448 String::pos(char const ch) const
449 {
450 if (undefined())
451 return NULL;
452 return strchr(termedBuf(), ch);
453 }
454
455 const char *
456 String::rpos(char const ch) const
457 {
458 if (undefined())
459 return NULL;
460 return strrchr(termedBuf(), (ch));
461 }
462
463 String::size_type
464 String::find(char const ch) const
465 {
466 const char *c;
467 c=pos(ch);
468 if (c==NULL)
469 return npos;
470 return c-rawBuf();
471 }
472
473 String::size_type
474 String::find(char const *aString) const
475 {
476 const char *c;
477 c=pos(aString);
478 if (c==NULL)
479 return npos;
480 return c-rawBuf();
481 }
482
483 String::size_type
484 String::rfind(char const ch) const
485 {
486 const char *c;
487 c=rpos(ch);
488 if (c==NULL)
489 return npos;
490 return c-rawBuf();
491 }
492
493
494
495 #if !_USE_INLINE_
496 #include "String.cci"
497 #endif