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