MemBuf.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 
72 #include "squid.h"
73 #include "mem/forward.h"
74 #include "MemBuf.h"
75 
76 /* local constants */
77 
78 /* default values for buffer sizes, used by memBufDefInit */
79 #define MEM_BUF_INIT_SIZE (2*1024)
80 #define MEM_BUF_MAX_SIZE (2*1000*1024*1024)
81 
83 
85 void
87 {
89 }
90 
92 void
94 {
95  assert(szInit > 0 && szMax > 0);
96  buf = nullptr;
97  size = 0;
98  max_capacity = szMax;
99  capacity = 0;
100  stolen = 0;
101  grow(szInit);
102  terminate();
103 }
104 
109 void
111 {
112  if (isNull()) {
113  // nothing to do
114  } else {
115  assert(buf);
116  assert(!stolen); /* not frozen */
117 
119  buf = nullptr;
120  size = capacity = max_capacity = 0;
121  }
122 }
123 
128 void
130 {
131  if (isNull()) {
132  init();
133  } else {
134  assert(!stolen); /* not frozen */
135  /* reset */
136  memset(buf, 0, capacity);
137  size = 0;
138  }
139 }
140 
144 int
146 {
147  if (!buf && !max_capacity && !capacity && !size)
148  return 1; /* is null (not initialized) */
149 
150  assert(buf && max_capacity && capacity); /* paranoid */
151 
152  return 0;
153 }
154 
156 {
157  const mb_size_t terminatedSize = size + 1;
158  return (terminatedSize < capacity) ? capacity - terminatedSize : 0;
159 }
160 
162 {
163  const mb_size_t terminatedSize = size + 1;
164  return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0;
165 }
166 
168 void MemBuf::consume(mb_size_t shiftSize)
169 {
170  const mb_size_t cSize = contentSize();
171  assert(0 <= shiftSize && shiftSize <= cSize);
172  assert(!stolen); /* not frozen */
173 
174  if (shiftSize > 0) {
175  if (shiftSize < cSize)
176  memmove(buf, buf + shiftSize, cSize - shiftSize);
177 
178  size -= shiftSize;
179 
180  terminate();
181  }
182 }
183 
186 {
187  if (contentSize() > 0) {
188  const char *end = buf + contentSize();
189  const char *p = buf;
190  for (; p<end && xisspace(*p); ++p);
191  if (p-buf > 0)
192  consume(p-buf);
193  }
194 }
195 
196 // removes last tailSize bytes
198 {
199  const mb_size_t cSize = contentSize();
200  assert(0 <= tailSize && tailSize <= cSize);
201  assert(!stolen); /* not frozen */
202  size -= tailSize;
203 }
204 
209 void MemBuf::append(const char *newContent, int sz)
210 {
211  assert(sz >= 0);
212  assert(buf || (0==capacity && 0==size));
213  assert(!stolen); /* not frozen */
214 
215  if (sz > 0) {
216  if (size + sz + 1 > capacity)
217  grow(size + sz + 1);
218 
219  assert(size + sz <= capacity); /* paranoid */
220  memcpy(space(), newContent, sz);
221  appended(sz);
222  }
223 }
224 
227 {
228  assert(size + sz <= capacity);
229  size += sz;
230  terminate();
231 }
232 
242 {
243  assert(size < capacity);
244  *space() = '\0';
245 }
246 
250 void
251 MemBuf::vappendf(const char *fmt, va_list vargs)
252 {
253  int sz = 0;
254  assert(fmt);
255  assert(buf);
256  assert(!stolen); /* not frozen */
257  /* assert in Grow should quit first, but we do not want to have a scary infinite loop */
258 
259  while (capacity <= max_capacity) {
260  mb_size_t free_space = capacity - size;
261  /* put as much as we can */
262 
263  /* Fix of bug 753r. The value of vargs is undefined
264  * after vsnprintf() returns. Make a copy of vargs
265  * in case we loop around and call vsnprintf() again.
266  */
267  va_list ap;
268  va_copy(ap,vargs);
269  sz = vsnprintf(buf + size, free_space, fmt, ap);
270  va_end(ap);
271 
272  /* check for possible overflow */
273  /* snprintf on Linuz returns -1 on overflows */
274  /* snprintf on FreeBSD returns at least free_space on overflows */
275 
276  if (sz < 0 || sz >= free_space)
277  grow(capacity + 1);
278  else
279  break;
280  }
281 
282  size += sz;
283  /* on Linux and FreeBSD, '\0' is not counted in return value */
284  /* on XXX it might be counted */
285  /* check that '\0' is appended and not counted */
286 
287  if (!size || buf[size - 1]) {
288  assert(!buf[size]);
289  } else {
290  --size;
291  }
292 }
293 
302 FREE *
304 {
305  FREE *ff;
306  assert(buf);
307  assert(!stolen); /* not frozen */
308 
309  ff = memFreeBufFunc((size_t) capacity);
310  stolen = 1; /* freeze */
311  return ff;
312 }
313 
317 void
319 {
320  size_t new_cap;
321  size_t buf_cap;
322 
323  assert(!stolen);
324  assert(capacity < min_cap);
325 
326  /* determine next capacity */
327 
328  if (min_cap > 64 * 1024) {
329  new_cap = 64 * 1024;
330 
331  while (new_cap < (size_t) min_cap)
332  new_cap += 64 * 1024; /* increase in reasonable steps */
333  } else {
334  new_cap = (size_t) min_cap;
335  }
336 
337  /* last chance to fit before we assert(!overflow) */
338  if (new_cap > (size_t) max_capacity)
339  new_cap = (size_t) max_capacity;
340 
341  assert(new_cap <= (size_t) max_capacity); /* no overflow */
342 
343  assert(new_cap > (size_t) capacity); /* progress */
344 
345  buf_cap = (size_t) capacity;
346 
347  buf = (char *)memReallocBuf(buf, new_cap, &buf_cap);
348 
349  /* done */
350  capacity = (mb_size_t) buf_cap;
351 }
352 
353 /* Reports */
354 
358 void
360 {
361  assert(mb);
362  mb->appendf("memBufReport is not yet implemented @?@\n");
363 }
364 
char * buf
Definition: MemBuf.h:134
void terminate()
Definition: MemBuf.cc:241
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
FREE * freeFunc()
Definition: MemBuf.cc:303
void memBufReport(MemBuf *mb)
Definition: MemBuf.cc:359
void consumeWhitespacePrefix()
removes all prefix whitespace, moving content left
Definition: MemBuf.cc:185
void FREE(void *)
Definition: forward.h:37
mb_size_t size
Definition: MemBuf.h:135
FREE * memFreeBufFunc(size_t size)
Definition: minimal.cc:79
int const char size_t
Definition: stub_liblog.cc:83
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:145
void append(const char *c, int sz) override
Definition: MemBuf.cc:209
mb_size_t capacity
Definition: MemBuf.h:149
#define MEM_BUF_INIT_SIZE
Definition: MemBuf.cc:79
Definition: MemBuf.h:23
void clean()
Definition: MemBuf.cc:110
#define MEM_BUF_MAX_SIZE
Definition: MemBuf.cc:80
unsigned stolen
Definition: MemBuf.h:151
#define assert(EX)
Definition: assert.h:17
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:325
void appended(mb_size_t sz)
updates content size after external append
Definition: MemBuf.cc:226
void vappendf(const char *fmt, va_list ap) override
Definition: MemBuf.cc:251
void * memReallocBuf(void *buf, size_t net_size, size_t *gross_size)
Definition: minimal.cc:54
void init()
Definition: MemBuf.cc:86
mb_size_t potentialSpaceSize() const
Definition: MemBuf.cc:161
void truncate(mb_size_t sz)
Definition: MemBuf.cc:197
mb_size_t spaceSize() const
Definition: MemBuf.cc:155
void reset()
Definition: MemBuf.cc:129
ssize_t mb_size_t
Definition: MemBuf.h:17
#define xisspace(x)
Definition: xis.h:15
void consume(mb_size_t sz)
removes sz bytes and "packs" by moving content left
Definition: MemBuf.cc:168
void grow(mb_size_t min_cap)
Definition: MemBuf.cc:318
void memFreeBuf(size_t size, void *)
Definition: minimal.cc:67
char * space(mb_size_t required)
Definition: MemBuf.h:63

 

Introduction

Documentation

Support

Miscellaneous