MemBuf.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 #ifdef VA_COPY
80 #undef VA_COPY
81 #endif
82 #if defined HAVE_VA_COPY
83 #define VA_COPY va_copy
84 #elif defined HAVE___VA_COPY
85 #define VA_COPY __va_copy
86 #endif
87 
88 /* local constants */
89 
90 /* default values for buffer sizes, used by memBufDefInit */
91 #define MEM_BUF_INIT_SIZE (2*1024)
92 #define MEM_BUF_MAX_SIZE (2*1000*1024*1024)
93 
95 
97 void
99 {
101 }
102 
104 void
106 {
107  assert(szInit > 0 && szMax > 0);
108  buf = NULL;
109  size = 0;
110  max_capacity = szMax;
111  capacity = 0;
112  stolen = 0;
113  grow(szInit);
114  terminate();
115 }
116 
121 void
123 {
124  if (isNull()) {
125  // nothing to do
126  } else {
127  assert(buf);
128  assert(!stolen); /* not frozen */
129 
131  buf = NULL;
132  size = capacity = max_capacity = 0;
133  }
134 }
135 
140 void
142 {
143  if (isNull()) {
144  init();
145  } else {
146  assert(!stolen); /* not frozen */
147  /* reset */
148  memset(buf, 0, capacity);
149  size = 0;
150  }
151 }
152 
156 int
158 {
159  if (!buf && !max_capacity && !capacity && !size)
160  return 1; /* is null (not initialized) */
161 
162  assert(buf && max_capacity && capacity); /* paranoid */
163 
164  return 0;
165 }
166 
168 {
169  const mb_size_t terminatedSize = size + 1;
170  return (terminatedSize < capacity) ? capacity - terminatedSize : 0;
171 }
172 
174 {
175  const mb_size_t terminatedSize = size + 1;
176  return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0;
177 }
178 
180 void MemBuf::consume(mb_size_t shiftSize)
181 {
182  const mb_size_t cSize = contentSize();
183  assert(0 <= shiftSize && shiftSize <= cSize);
184  assert(!stolen); /* not frozen */
185 
186  PROF_start(MemBuf_consume);
187  if (shiftSize > 0) {
188  if (shiftSize < cSize)
189  memmove(buf, buf + shiftSize, cSize - shiftSize);
190 
191  size -= shiftSize;
192 
193  terminate();
194  }
195  PROF_stop(MemBuf_consume);
196 }
197 
200 {
201  PROF_start(MemBuf_consumeWhitespace);
202  if (contentSize() > 0) {
203  const char *end = buf + contentSize();
204  const char *p = buf;
205  for (; p<end && xisspace(*p); ++p);
206  if (p-buf > 0)
207  consume(p-buf);
208  }
209  PROF_stop(MemBuf_consumeWhitespace);
210 }
211 
212 // removes last tailSize bytes
214 {
215  const mb_size_t cSize = contentSize();
216  assert(0 <= tailSize && tailSize <= cSize);
217  assert(!stolen); /* not frozen */
218  size -= tailSize;
219 }
220 
225 void MemBuf::append(const char *newContent, int sz)
226 {
227  assert(sz >= 0);
228  assert(buf || (0==capacity && 0==size));
229  assert(!stolen); /* not frozen */
230 
231  PROF_start(MemBuf_append);
232  if (sz > 0) {
233  if (size + sz + 1 > capacity)
234  grow(size + sz + 1);
235 
236  assert(size + sz <= capacity); /* paranoid */
237  memcpy(space(), newContent, sz);
238  appended(sz);
239  }
240  PROF_stop(MemBuf_append);
241 }
242 
245 {
246  assert(size + sz <= capacity);
247  size += sz;
248  terminate();
249 }
250 
260 {
261  assert(size < capacity);
262  *space() = '\0';
263 }
264 
268 void
269 MemBuf::vappendf(const char *fmt, va_list vargs)
270 {
271 #ifdef VA_COPY
272  va_list ap;
273 #endif
274 
275  int sz = 0;
276  assert(fmt);
277  assert(buf);
278  assert(!stolen); /* not frozen */
279  /* assert in Grow should quit first, but we do not want to have a scary infinite loop */
280 
281  while (capacity <= max_capacity) {
282  mb_size_t free_space = capacity - size;
283  /* put as much as we can */
284 
285 #ifdef VA_COPY
286  /* Fix of bug 753r. The value of vargs is undefined
287  * after vsnprintf() returns. Make a copy of vargs
288  * incase we loop around and call vsnprintf() again.
289  */
290  VA_COPY(ap,vargs);
291  sz = vsnprintf(buf + size, free_space, fmt, ap);
292  va_end(ap);
293 #else /* VA_COPY */
294 
295  sz = vsnprintf(buf + size, free_space, fmt, vargs);
296 #endif /*VA_COPY*/
297  /* check for possible overflow */
298  /* snprintf on Linuz returns -1 on overflows */
299  /* snprintf on FreeBSD returns at least free_space on overflows */
300 
301  if (sz < 0 || sz >= free_space)
302  grow(capacity + 1);
303  else
304  break;
305  }
306 
307  size += sz;
308  /* on Linux and FreeBSD, '\0' is not counted in return value */
309  /* on XXX it might be counted */
310  /* check that '\0' is appended and not counted */
311 
312  if (!size || buf[size - 1]) {
313  assert(!buf[size]);
314  } else {
315  --size;
316  }
317 }
318 
327 FREE *
329 {
330  FREE *ff;
331  assert(buf);
332  assert(!stolen); /* not frozen */
333 
334  ff = memFreeBufFunc((size_t) capacity);
335  stolen = 1; /* freeze */
336  return ff;
337 }
338 
342 void
344 {
345  size_t new_cap;
346  size_t buf_cap;
347 
348  assert(!stolen);
349  assert(capacity < min_cap);
350 
351  PROF_start(MemBuf_grow);
352 
353  /* determine next capacity */
354 
355  if (min_cap > 64 * 1024) {
356  new_cap = 64 * 1024;
357 
358  while (new_cap < (size_t) min_cap)
359  new_cap += 64 * 1024; /* increase in reasonable steps */
360  } else {
361  new_cap = (size_t) min_cap;
362  }
363 
364  /* last chance to fit before we assert(!overflow) */
365  if (new_cap > (size_t) max_capacity)
366  new_cap = (size_t) max_capacity;
367 
368  assert(new_cap <= (size_t) max_capacity); /* no overflow */
369 
370  assert(new_cap > (size_t) capacity); /* progress */
371 
372  buf_cap = (size_t) capacity;
373 
374  buf = (char *)memReallocBuf(buf, new_cap, &buf_cap);
375 
376  /* done */
377  capacity = (mb_size_t) buf_cap;
378  PROF_stop(MemBuf_grow);
379 }
380 
381 /* Reports */
382 
386 void
388 {
389  assert(mb);
390  mb->appendf("memBufReport is not yet implemented @?@\n");
391 }
392 
FREE * freeFunc()
Definition: MemBuf.cc:328
void grow(mb_size_t min_cap)
Definition: MemBuf.cc:343
#define MEM_BUF_INIT_SIZE
Definition: MemBuf.cc:91
#define assert(EX)
Definition: assert.h:17
mb_size_t spaceSize() const
Definition: MemBuf.cc:167
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:225
void consumeWhitespacePrefix()
removes all prefix whitespace, moving content left
Definition: MemBuf.cc:199
mb_size_t potentialSpaceSize() const
Definition: MemBuf.cc:173
void consume(mb_size_t sz)
removes sz bytes and "packs" by moving content left
Definition: MemBuf.cc:180
#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:269
char * space()
returns buffer after data; does not check space existence
Definition: MemBuf.h:57
void reset()
Definition: MemBuf.cc:141
mb_size_t size
Definition: MemBuf.h:135
void memBufReport(MemBuf *mb)
Definition: MemBuf.cc:387
void appended(mb_size_t sz)
updates content size after external append
Definition: MemBuf.cc:244
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:122
unsigned stolen
Definition: MemBuf.h:151
char * buf
Definition: MemBuf.h:134
int isNull() const
Definition: MemBuf.cc:157
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:84
Definition: MemBuf.h:23
void init()
Definition: MemBuf.cc:98
void truncate(mb_size_t sz)
Definition: MemBuf.cc:213
#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:92
#define NULL
Definition: types.h:166
void terminate()
Definition: MemBuf.cc:259

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors