MemBuf.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 59 auto-growing Memory Buffer with printf */
10 
74 #include "squid.h"
75 #include "mem/forward.h"
76 #include "MemBuf.h"
77 
78 /* local constants */
79 
80 /* default values for buffer sizes, used by memBufDefInit */
81 #define MEM_BUF_INIT_SIZE (2*1024)
82 #define MEM_BUF_MAX_SIZE (2*1000*1024*1024)
83 
85 
87 void
89 {
91 }
92 
94 void
96 {
97  assert(szInit > 0 && szMax > 0);
98  buf = NULL;
99  size = 0;
100  max_capacity = szMax;
101  capacity = 0;
102  stolen = 0;
103  grow(szInit);
104  terminate();
105 }
106 
111 void
113 {
114  if (isNull()) {
115  // nothing to do
116  } else {
117  assert(buf);
118  assert(!stolen); /* not frozen */
119 
121  buf = NULL;
122  size = capacity = max_capacity = 0;
123  }
124 }
125 
130 void
132 {
133  if (isNull()) {
134  init();
135  } else {
136  assert(!stolen); /* not frozen */
137  /* reset */
138  memset(buf, 0, capacity);
139  size = 0;
140  }
141 }
142 
146 int
148 {
149  if (!buf && !max_capacity && !capacity && !size)
150  return 1; /* is null (not initialized) */
151 
152  assert(buf && max_capacity && capacity); /* paranoid */
153 
154  return 0;
155 }
156 
158 {
159  const mb_size_t terminatedSize = size + 1;
160  return (terminatedSize < capacity) ? capacity - terminatedSize : 0;
161 }
162 
164 {
165  const mb_size_t terminatedSize = size + 1;
166  return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0;
167 }
168 
170 void MemBuf::consume(mb_size_t shiftSize)
171 {
172  const mb_size_t cSize = contentSize();
173  assert(0 <= shiftSize && shiftSize <= cSize);
174  assert(!stolen); /* not frozen */
175 
176  if (shiftSize > 0) {
177  if (shiftSize < cSize)
178  memmove(buf, buf + shiftSize, cSize - shiftSize);
179 
180  size -= shiftSize;
181 
182  terminate();
183  }
184 }
185 
188 {
189  if (contentSize() > 0) {
190  const char *end = buf + contentSize();
191  const char *p = buf;
192  for (; p<end && xisspace(*p); ++p);
193  if (p-buf > 0)
194  consume(p-buf);
195  }
196 }
197 
198 // removes last tailSize bytes
200 {
201  const mb_size_t cSize = contentSize();
202  assert(0 <= tailSize && tailSize <= cSize);
203  assert(!stolen); /* not frozen */
204  size -= tailSize;
205 }
206 
211 void MemBuf::append(const char *newContent, int sz)
212 {
213  assert(sz >= 0);
214  assert(buf || (0==capacity && 0==size));
215  assert(!stolen); /* not frozen */
216 
217  if (sz > 0) {
218  if (size + sz + 1 > capacity)
219  grow(size + sz + 1);
220 
221  assert(size + sz <= capacity); /* paranoid */
222  memcpy(space(), newContent, sz);
223  appended(sz);
224  }
225 }
226 
229 {
230  assert(size + sz <= capacity);
231  size += sz;
232  terminate();
233 }
234 
244 {
245  assert(size < capacity);
246  *space() = '\0';
247 }
248 
252 void
253 MemBuf::vappendf(const char *fmt, va_list vargs)
254 {
255  int sz = 0;
256  assert(fmt);
257  assert(buf);
258  assert(!stolen); /* not frozen */
259  /* assert in Grow should quit first, but we do not want to have a scary infinite loop */
260 
261  while (capacity <= max_capacity) {
262  mb_size_t free_space = capacity - size;
263  /* put as much as we can */
264 
265  /* Fix of bug 753r. The value of vargs is undefined
266  * after vsnprintf() returns. Make a copy of vargs
267  * in case we loop around and call vsnprintf() again.
268  */
269  va_list ap;
270  va_copy(ap,vargs);
271  sz = vsnprintf(buf + size, free_space, fmt, ap);
272  va_end(ap);
273 
274  /* check for possible overflow */
275  /* snprintf on Linuz returns -1 on overflows */
276  /* snprintf on FreeBSD returns at least free_space on overflows */
277 
278  if (sz < 0 || sz >= free_space)
279  grow(capacity + 1);
280  else
281  break;
282  }
283 
284  size += sz;
285  /* on Linux and FreeBSD, '\0' is not counted in return value */
286  /* on XXX it might be counted */
287  /* check that '\0' is appended and not counted */
288 
289  if (!size || buf[size - 1]) {
290  assert(!buf[size]);
291  } else {
292  --size;
293  }
294 }
295 
304 FREE *
306 {
307  FREE *ff;
308  assert(buf);
309  assert(!stolen); /* not frozen */
310 
311  ff = memFreeBufFunc((size_t) capacity);
312  stolen = 1; /* freeze */
313  return ff;
314 }
315 
319 void
321 {
322  size_t new_cap;
323  size_t buf_cap;
324 
325  assert(!stolen);
326  assert(capacity < min_cap);
327 
328  /* determine next capacity */
329 
330  if (min_cap > 64 * 1024) {
331  new_cap = 64 * 1024;
332 
333  while (new_cap < (size_t) min_cap)
334  new_cap += 64 * 1024; /* increase in reasonable steps */
335  } else {
336  new_cap = (size_t) min_cap;
337  }
338 
339  /* last chance to fit before we assert(!overflow) */
340  if (new_cap > (size_t) max_capacity)
341  new_cap = (size_t) max_capacity;
342 
343  assert(new_cap <= (size_t) max_capacity); /* no overflow */
344 
345  assert(new_cap > (size_t) capacity); /* progress */
346 
347  buf_cap = (size_t) capacity;
348 
349  buf = (char *)memReallocBuf(buf, new_cap, &buf_cap);
350 
351  /* done */
352  capacity = (mb_size_t) buf_cap;
353 }
354 
355 /* Reports */
356 
360 void
362 {
363  assert(mb);
364  mb->appendf("memBufReport is not yet implemented @?@\n");
365 }
366 
char * buf
Definition: MemBuf.h:134
void terminate()
Definition: MemBuf.cc:243
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
FREE * freeFunc()
Definition: MemBuf.cc:305
void memBufReport(MemBuf *mb)
Definition: MemBuf.cc:361
void consumeWhitespacePrefix()
removes all prefix whitespace, moving content left
Definition: MemBuf.cc:187
void FREE(void *)
Definition: forward.h:36
mb_size_t size
Definition: MemBuf.h:135
FREE * memFreeBufFunc(size_t size)
Definition: old_api.cc:567
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:211
int const char size_t
Definition: stub_liblog.cc:86
mb_size_t max_capacity
Definition: MemBuf.h:142
mb_size_t contentSize() const
available data size
Definition: MemBuf.h:47
int isNull() const
Definition: MemBuf.cc:147
#define NULL
Definition: types.h:166
mb_size_t capacity
Definition: MemBuf.h:149
#define MEM_BUF_INIT_SIZE
Definition: MemBuf.cc:81
Definition: MemBuf.h:24
void clean()
Definition: MemBuf.cc:112
#define MEM_BUF_MAX_SIZE
Definition: MemBuf.cc:82
unsigned stolen
Definition: MemBuf.h:151
#define assert(EX)
Definition: assert.h:19
char * space()
returns buffer after data; does not check space existence
Definition: MemBuf.h:57
void const char int sz
Definition: stub_cbdata.cc:16
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
virtual void vappendf(const char *fmt, va_list ap)
Definition: MemBuf.cc:253
void appended(mb_size_t sz)
updates content size after external append
Definition: MemBuf.cc:228
void * memReallocBuf(void *buf, size_t net_size, size_t *gross_size)
Definition: old_api.cc:360
void init()
Definition: MemBuf.cc:88
mb_size_t potentialSpaceSize() const
Definition: MemBuf.cc:163
void truncate(mb_size_t sz)
Definition: MemBuf.cc:199
mb_size_t spaceSize() const
Definition: MemBuf.cc:157
void reset()
Definition: MemBuf.cc:131
ssize_t mb_size_t
Definition: MemBuf.h:17
#define xisspace(x)
Definition: xis.h:17
void consume(mb_size_t sz)
removes sz bytes and "packs" by moving content left
Definition: MemBuf.cc:170
void grow(mb_size_t min_cap)
Definition: MemBuf.cc:320
void memFreeBuf(size_t size, void *)
Definition: old_api.cc:384

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors