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