MemBuf.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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 #include "profiler/Profiler.h"
78 
79 /* local constants */
80 
81 /* default values for buffer sizes, used by memBufDefInit */
82 #define MEM_BUF_INIT_SIZE (2*1024)
83 #define MEM_BUF_MAX_SIZE (2*1000*1024*1024)
84 
86 
88 void
90 {
92 }
93 
95 void
97 {
98  assert(szInit > 0 && szMax > 0);
99  buf = NULL;
100  size = 0;
101  max_capacity = szMax;
102  capacity = 0;
103  stolen = 0;
104  grow(szInit);
105  terminate();
106 }
107 
112 void
114 {
115  if (isNull()) {
116  // nothing to do
117  } else {
118  assert(buf);
119  assert(!stolen); /* not frozen */
120 
122  buf = NULL;
123  size = capacity = max_capacity = 0;
124  }
125 }
126 
131 void
133 {
134  if (isNull()) {
135  init();
136  } else {
137  assert(!stolen); /* not frozen */
138  /* reset */
139  memset(buf, 0, capacity);
140  size = 0;
141  }
142 }
143 
147 int
149 {
150  if (!buf && !max_capacity && !capacity && !size)
151  return 1; /* is null (not initialized) */
152 
153  assert(buf && max_capacity && capacity); /* paranoid */
154 
155  return 0;
156 }
157 
159 {
160  const mb_size_t terminatedSize = size + 1;
161  return (terminatedSize < capacity) ? capacity - terminatedSize : 0;
162 }
163 
165 {
166  const mb_size_t terminatedSize = size + 1;
167  return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0;
168 }
169 
171 void MemBuf::consume(mb_size_t shiftSize)
172 {
173  const mb_size_t cSize = contentSize();
174  assert(0 <= shiftSize && shiftSize <= cSize);
175  assert(!stolen); /* not frozen */
176 
177  PROF_start(MemBuf_consume);
178  if (shiftSize > 0) {
179  if (shiftSize < cSize)
180  memmove(buf, buf + shiftSize, cSize - shiftSize);
181 
182  size -= shiftSize;
183 
184  terminate();
185  }
186  PROF_stop(MemBuf_consume);
187 }
188 
191 {
192  PROF_start(MemBuf_consumeWhitespace);
193  if (contentSize() > 0) {
194  const char *end = buf + contentSize();
195  const char *p = buf;
196  for (; p<end && xisspace(*p); ++p);
197  if (p-buf > 0)
198  consume(p-buf);
199  }
200  PROF_stop(MemBuf_consumeWhitespace);
201 }
202 
203 // removes last tailSize bytes
205 {
206  const mb_size_t cSize = contentSize();
207  assert(0 <= tailSize && tailSize <= cSize);
208  assert(!stolen); /* not frozen */
209  size -= tailSize;
210 }
211 
216 void MemBuf::append(const char *newContent, int sz)
217 {
218  assert(sz >= 0);
219  assert(buf || (0==capacity && 0==size));
220  assert(!stolen); /* not frozen */
221 
222  PROF_start(MemBuf_append);
223  if (sz > 0) {
224  if (size + sz + 1 > capacity)
225  grow(size + sz + 1);
226 
227  assert(size + sz <= capacity); /* paranoid */
228  memcpy(space(), newContent, sz);
229  appended(sz);
230  }
231  PROF_stop(MemBuf_append);
232 }
233 
236 {
237  assert(size + sz <= capacity);
238  size += sz;
239  terminate();
240 }
241 
251 {
252  assert(size < capacity);
253  *space() = '\0';
254 }
255 
259 void
260 MemBuf::vappendf(const char *fmt, va_list vargs)
261 {
262  int sz = 0;
263  assert(fmt);
264  assert(buf);
265  assert(!stolen); /* not frozen */
266  /* assert in Grow should quit first, but we do not want to have a scary infinite loop */
267 
268  while (capacity <= max_capacity) {
269  mb_size_t free_space = capacity - size;
270  /* put as much as we can */
271 
272  /* Fix of bug 753r. The value of vargs is undefined
273  * after vsnprintf() returns. Make a copy of vargs
274  * incase we loop around and call vsnprintf() again.
275  */
276  va_list ap;
277  va_copy(ap,vargs);
278  sz = vsnprintf(buf + size, free_space, fmt, ap);
279  va_end(ap);
280 
281  /* check for possible overflow */
282  /* snprintf on Linuz returns -1 on overflows */
283  /* snprintf on FreeBSD returns at least free_space on overflows */
284 
285  if (sz < 0 || sz >= free_space)
286  grow(capacity + 1);
287  else
288  break;
289  }
290 
291  size += sz;
292  /* on Linux and FreeBSD, '\0' is not counted in return value */
293  /* on XXX it might be counted */
294  /* check that '\0' is appended and not counted */
295 
296  if (!size || buf[size - 1]) {
297  assert(!buf[size]);
298  } else {
299  --size;
300  }
301 }
302 
311 FREE *
313 {
314  FREE *ff;
315  assert(buf);
316  assert(!stolen); /* not frozen */
317 
318  ff = memFreeBufFunc((size_t) capacity);
319  stolen = 1; /* freeze */
320  return ff;
321 }
322 
326 void
328 {
329  size_t new_cap;
330  size_t buf_cap;
331 
332  assert(!stolen);
333  assert(capacity < min_cap);
334 
335  PROF_start(MemBuf_grow);
336 
337  /* determine next capacity */
338 
339  if (min_cap > 64 * 1024) {
340  new_cap = 64 * 1024;
341 
342  while (new_cap < (size_t) min_cap)
343  new_cap += 64 * 1024; /* increase in reasonable steps */
344  } else {
345  new_cap = (size_t) min_cap;
346  }
347 
348  /* last chance to fit before we assert(!overflow) */
349  if (new_cap > (size_t) max_capacity)
350  new_cap = (size_t) max_capacity;
351 
352  assert(new_cap <= (size_t) max_capacity); /* no overflow */
353 
354  assert(new_cap > (size_t) capacity); /* progress */
355 
356  buf_cap = (size_t) capacity;
357 
358  buf = (char *)memReallocBuf(buf, new_cap, &buf_cap);
359 
360  /* done */
361  capacity = (mb_size_t) buf_cap;
362  PROF_stop(MemBuf_grow);
363 }
364 
365 /* Reports */
366 
370 void
372 {
373  assert(mb);
374  mb->appendf("memBufReport is not yet implemented @?@\n");
375 }
376 
FREE * freeFunc()
Definition: MemBuf.cc:312
void grow(mb_size_t min_cap)
Definition: MemBuf.cc:327
#define MEM_BUF_INIT_SIZE
Definition: MemBuf.cc:82
#define assert(EX)
Definition: assert.h:17
mb_size_t spaceSize() const
Definition: MemBuf.cc:158
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:216
void consumeWhitespacePrefix()
removes all prefix whitespace, moving content left
Definition: MemBuf.cc:190
mb_size_t potentialSpaceSize() const
Definition: MemBuf.cc:164
void consume(mb_size_t sz)
removes sz bytes and "packs" by moving content left
Definition: MemBuf.cc:171
#define xisspace(x)
Definition: xis.h:17
char * p
Definition: membanger.c:43
void FREE(void *)
Definition: forward.h:36
mb_size_t capacity
Definition: MemBuf.h:149
void * memReallocBuf(void *buf, size_t net_size, size_t *gross_size)
Definition: old_api.cc:335
virtual void vappendf(const char *fmt, va_list ap)
Definition: MemBuf.cc:260
char * space()
returns buffer after data; does not check space existence
Definition: MemBuf.h:57
void reset()
Definition: MemBuf.cc:132
mb_size_t size
Definition: MemBuf.h:135
void memBufReport(MemBuf *mb)
Definition: MemBuf.cc:371
void appended(mb_size_t sz)
updates content size after external append
Definition: MemBuf.cc:235
mb_size_t contentSize() const
available data size
Definition: MemBuf.h:47
void memFreeBuf(size_t size, void *)
Definition: old_api.cc:359
void clean()
Definition: MemBuf.cc:113
unsigned stolen
Definition: MemBuf.h:151
char * buf
Definition: MemBuf.h:134
int isNull() const
Definition: MemBuf.cc:148
mb_size_t max_capacity
Definition: MemBuf.h:142
#define PROF_start(probename)
Definition: Profiler.h:62
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
ssize_t mb_size_t
Definition: MemBuf.h:17
int const char size_t
Definition: stub_liblog.cc:86
Definition: MemBuf.h:23
void init()
Definition: MemBuf.cc:89
void truncate(mb_size_t sz)
Definition: MemBuf.cc:204
#define PROF_stop(probename)
Definition: Profiler.h:63
FREE * memFreeBufFunc(size_t size)
Definition: old_api.cc:552
#define MEM_BUF_MAX_SIZE
Definition: MemBuf.cc:83
#define NULL
Definition: types.h:166
void terminate()
Definition: MemBuf.cc:250

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors