NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
buffer.c File Reference

General purpose object for storing and parsing strings. More...

#include "config.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "buffer.h"
#include "memory.h"
#include "string2.h"
+ Include dependency graph for buffer.c:

Go to the source code of this file.

Functions

struct Buffermutt_buffer_init (struct Buffer *buf)
 Initialise a new Buffer. More...
 
struct Buffer mutt_buffer_make (size_t size)
 Make a new buffer on the stack. More...
 
void mutt_buffer_reset (struct Buffer *buf)
 Reset an existing Buffer. More...
 
size_t mutt_buffer_addstr_n (struct Buffer *buf, const char *s, size_t len)
 Add a string to a Buffer, expanding it if necessary. More...
 
static int buffer_printf (struct Buffer *buf, const char *fmt, va_list ap)
 Format a string into a Buffer. More...
 
int mutt_buffer_printf (struct Buffer *buf, const char *fmt,...)
 Format a string overwriting a Buffer. More...
 
void mutt_buffer_fix_dptr (struct Buffer *buf)
 Move the dptr to end of the Buffer. More...
 
int mutt_buffer_add_printf (struct Buffer *buf, const char *fmt,...)
 Format a string appending a Buffer. More...
 
size_t mutt_buffer_addstr (struct Buffer *buf, const char *s)
 Add a string to a Buffer. More...
 
size_t mutt_buffer_addch (struct Buffer *buf, char c)
 Add a single character to a Buffer. More...
 
bool mutt_buffer_is_empty (const struct Buffer *buf)
 Is the Buffer empty? More...
 
void mutt_buffer_alloc (struct Buffer *buf, size_t new_size)
 Make sure a buffer can store at least new_size bytes. More...
 
void mutt_buffer_dealloc (struct Buffer *buf)
 Release the memory allocated by a buffer. More...
 
size_t mutt_buffer_strcpy (struct Buffer *buf, const char *s)
 Copy a string into a Buffer. More...
 
size_t mutt_buffer_strcpy_n (struct Buffer *buf, const char *s, size_t len)
 Copy a string into a Buffer. More...
 
size_t mutt_buffer_substrcpy (struct Buffer *buf, const char *beg, const char *end)
 Copy a partial string into a Buffer. More...
 
size_t mutt_buffer_len (const struct Buffer *buf)
 Calculate the length of a Buffer. More...
 
size_t mutt_buffer_concat_path (struct Buffer *buf, const char *dir, const char *fname)
 Join a directory name and a filename. More...
 
size_t mutt_buffer_concatn_path (struct Buffer *buf, const char *dir, size_t dirlen, const char *fname, size_t fnamelen)
 Join a directory name and a filename. More...
 
char * mutt_buffer_strdup (const struct Buffer *buf)
 Copy a Buffer's string. More...
 
size_t mutt_buffer_copy (struct Buffer *dst, const struct Buffer *src)
 Copy a Buffer's contents to another Buffer. More...
 
void mutt_buffer_seek (struct Buffer *buf, size_t offset)
 Set current read/write position to offset from beginning. More...
 

Variables

static const int BufferStepSize = 128
 

Detailed Description

General purpose object for storing and parsing strings.

Authors
  • Ian Zimmerman
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file buffer.c.

Function Documentation

◆ mutt_buffer_init()

struct Buffer* mutt_buffer_init ( struct Buffer buf)

Initialise a new Buffer.

Parameters
bufBuffer to initialise
Return values
ptrInitialised Buffer

This must not be called on a Buffer that already contains data.

Definition at line 48 of file buffer.c.

49 {
50  if (!buf)
51  return NULL;
52  memset(buf, 0, sizeof(struct Buffer));
53  return buf;
54 }
String manipulation buffer.
Definition: buffer.h:34
+ Here is the caller graph for this function:

◆ mutt_buffer_make()

struct Buffer mutt_buffer_make ( size_t  size)

Make a new buffer on the stack.

Parameters
sizeInitial size
Return values
bufInitialized buffer

The buffer must be released using mutt_buffer_dealloc

Definition at line 48 of file buffer.c.

64 {
65  struct Buffer buf = { 0 };
66  if (size != 0)
67  {
68  buf.dptr = buf.data = mutt_mem_calloc(1, size);
69  buf.dsize = size;
70  }
71  return buf;
72 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char * dptr
Current read/write position.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35

◆ mutt_buffer_reset()

void mutt_buffer_reset ( struct Buffer buf)

Reset an existing Buffer.

Parameters
bufBuffer to reset

This can be called on a Buffer to reset the pointers, effectively emptying it.

Definition at line 81 of file buffer.c.

82 {
83  if (!buf || !buf->data || (buf->dsize == 0))
84  return;
85  memset(buf->data, 0, buf->dsize);
86  mutt_buffer_seek(buf, 0);
87 }
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:466
+ Here is the call graph for this function:

◆ mutt_buffer_addstr_n()

size_t mutt_buffer_addstr_n ( struct Buffer buf,
const char *  s,
size_t  len 
)

Add a string to a Buffer, expanding it if necessary.

Parameters
bufBuffer to add to
sString to add
lenLength of the string
Return values
numBytes written to Buffer
0Error

Dynamically grow a Buffer to accommodate s, in increments of 128 bytes. Always one byte bigger than necessary for the null terminator, and the buffer is always NUL-terminated

Definition at line 101 of file buffer.c.

102 {
103  if (!buf || !s)
104  return 0;
105 
106  if (!buf->data || !buf->dptr || ((buf->dptr + len + 1) > (buf->data + buf->dsize)))
107  mutt_buffer_alloc(buf, buf->dsize + MAX(BufferStepSize, len + 1));
108 
109  memcpy(buf->dptr, s, len);
110  buf->dptr += len;
111  *(buf->dptr) = '\0';
112  return len;
113 }
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
static const int BufferStepSize
Definition: buffer.c:39
#define MAX(a, b)
Definition: memory.h:30
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buffer_printf()

static int buffer_printf ( struct Buffer buf,
const char *  fmt,
va_list  ap 
)
static

Format a string into a Buffer.

Parameters
bufBuffer
fmtprintf-style format string
apArguments to be formatted
Return values
numCharacters written
0Error

Definition at line 123 of file buffer.c.

124 {
125  if (!buf || !fmt)
126  return 0; /* LCOV_EXCL_LINE */
127 
128  mutt_buffer_alloc(buf, 128);
129 
130  int doff = buf->dptr - buf->data;
131  int blen = buf->dsize - doff;
132 
133  va_list ap_retry;
134  va_copy(ap_retry, ap);
135 
136  int len = vsnprintf(buf->dptr, blen, fmt, ap);
137  if (len >= blen)
138  {
139  mutt_buffer_alloc(buf, buf->dsize + len - blen + 1);
140  len = vsnprintf(buf->dptr, len + 1, fmt, ap_retry);
141  }
142  if (len > 0)
143  buf->dptr += len;
144 
145  va_end(ap_retry);
146 
147  return len;
148 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_printf()

int mutt_buffer_printf ( struct Buffer buf,
const char *  fmt,
  ... 
)

Format a string overwriting a Buffer.

Parameters
bufBuffer
fmtprintf-style format string
...Arguments to be formatted
Return values
numCharacters written
-1Error

Definition at line 158 of file buffer.c.

159 {
160  if (!buf || !fmt)
161  return -1;
162 
163  va_list ap;
164 
165  va_start(ap, fmt);
166  mutt_buffer_reset(buf);
167  int len = buffer_printf(buf, fmt, ap);
168  va_end(ap);
169 
170  return len;
171 }
static int buffer_printf(struct Buffer *buf, const char *fmt, va_list ap)
Format a string into a Buffer.
Definition: buffer.c:123
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:81
+ Here is the call graph for this function:

◆ mutt_buffer_fix_dptr()

void mutt_buffer_fix_dptr ( struct Buffer buf)

Move the dptr to end of the Buffer.

Parameters
bufBuffer to alter

Ensure buffer->dptr points to the end of the buffer.

Definition at line 179 of file buffer.c.

180 {
181  if (!buf)
182  return;
183 
184  mutt_buffer_seek(buf, 0);
185 
186  if (buf->data && (buf->dsize > 0))
187  {
188  buf->data[buf->dsize - 1] = '\0';
189  buf->dptr = strchr(buf->data, '\0');
190  }
191 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_add_printf()

int mutt_buffer_add_printf ( struct Buffer buf,
const char *  fmt,
  ... 
)

Format a string appending a Buffer.

Parameters
bufBuffer
fmtprintf-style format string
...Arguments to be formatted
Return values
numCharacters written
-1Error

Definition at line 201 of file buffer.c.

202 {
203  if (!buf || !fmt)
204  return -1;
205 
206  va_list ap;
207 
208  va_start(ap, fmt);
209  int len = buffer_printf(buf, fmt, ap);
210  va_end(ap);
211 
212  return len;
213 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_addstr()

size_t mutt_buffer_addstr ( struct Buffer buf,
const char *  s 
)

Add a string to a Buffer.

Parameters
bufBuffer to add to
sString to add
Return values
numBytes written to Buffer

If necessary, the Buffer will be expanded.

Definition at line 223 of file buffer.c.

224 {
225  if (!buf || !s)
226  return 0;
227  return mutt_buffer_addstr_n(buf, s, mutt_str_len(s));
228 }
size_t mutt_buffer_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition: buffer.c:101
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
+ Here is the call graph for this function:

◆ mutt_buffer_addch()

size_t mutt_buffer_addch ( struct Buffer buf,
char  c 
)

Add a single character to a Buffer.

Parameters
bufBuffer to add to
cCharacter to add
Return values
numBytes written to Buffer

If necessary, the Buffer will be expanded.

Definition at line 238 of file buffer.c.

239 {
240  if (!buf)
241  return 0;
242  return mutt_buffer_addstr_n(buf, &c, 1);
243 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_is_empty()

bool mutt_buffer_is_empty ( const struct Buffer buf)

Is the Buffer empty?

Parameters
bufBuffer to inspect
Return values
trueBuffer is empty

Definition at line 250 of file buffer.c.

251 {
252  if (!buf || !buf->data)
253  return true;
254 
255  return (buf->data[0] == '\0');
256 }

◆ mutt_buffer_alloc()

void mutt_buffer_alloc ( struct Buffer buf,
size_t  new_size 
)

Make sure a buffer can store at least new_size bytes.

Parameters
bufBuffer to change
new_sizeNew size
Note
new_size will be rounded up to BufferStepSize

Definition at line 265 of file buffer.c.

266 {
267  if (!buf)
268  return;
269 
270  if (buf->data && (new_size > 0) && (new_size <= buf->dsize))
271  return;
272 
273  const bool was_empty = (buf->dptr == NULL);
274  const size_t offset = (buf->dptr && buf->data) ? (buf->dptr - buf->data) : 0;
275 
276  buf->dsize = ROUND_UP(new_size + 1, BufferStepSize);
277  mutt_mem_realloc(&buf->data, buf->dsize);
278  mutt_buffer_seek(buf, offset);
279 
280  // Ensures that initially NULL buf->data is properly terminated
281  if (was_empty)
282  {
283  buf->dptr = buf->data;
284  *buf->dptr = '\0';
285  }
286 }
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define ROUND_UP(NUM, STEP)
Definition: memory.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_dealloc()

void mutt_buffer_dealloc ( struct Buffer buf)

Release the memory allocated by a buffer.

Parameters
bufBuffer to change

Definition at line 292 of file buffer.c.

293 {
294  if (!buf || !buf->data)
295  return;
296 
297  buf->dptr = NULL;
298  buf->dsize = 0;
299  FREE(&buf->data);
300 }
#define FREE(x)
Definition: memory.h:43

◆ mutt_buffer_strcpy()

size_t mutt_buffer_strcpy ( struct Buffer buf,
const char *  s 
)

Copy a string into a Buffer.

Parameters
bufBuffer to overwrite
sString to copy
Return values
numBytes written to Buffer

Overwrites any existing content.

Definition at line 310 of file buffer.c.

311 {
312  mutt_buffer_reset(buf);
313  return mutt_buffer_addstr(buf, s);
314 }
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:223
+ Here is the call graph for this function:

◆ mutt_buffer_strcpy_n()

size_t mutt_buffer_strcpy_n ( struct Buffer buf,
const char *  s,
size_t  len 
)

Copy a string into a Buffer.

Parameters
bufBuffer to overwrite
sString to copy
lenLength of string to copy
Return values
numBytes written to Buffer

Overwrites any existing content.

Definition at line 325 of file buffer.c.

326 {
327  mutt_buffer_reset(buf);
328  return mutt_buffer_addstr_n(buf, s, len);
329 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_substrcpy()

size_t mutt_buffer_substrcpy ( struct Buffer buf,
const char *  beg,
const char *  end 
)

Copy a partial string into a Buffer.

Parameters
bufBuffer to overwrite
begStart of string to copy
endEnd of string to copy
Return values
numBytes written to Buffer

Overwrites any existing content.

Definition at line 340 of file buffer.c.

341 {
342  mutt_buffer_reset(buf);
343  if (end <= beg)
344  return 0;
345 
346  return mutt_buffer_strcpy_n(buf, beg, end - beg);
347 }
size_t mutt_buffer_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:325
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_len()

size_t mutt_buffer_len ( const struct Buffer buf)

Calculate the length of a Buffer.

Parameters
bufBuffer
Return values
numSize of buffer

Definition at line 354 of file buffer.c.

355 {
356  if (!buf || !buf->data || !buf->dptr)
357  return 0;
358 
359  return buf->dptr - buf->data;
360 }
+ Here is the caller graph for this function:

◆ mutt_buffer_concat_path()

size_t mutt_buffer_concat_path ( struct Buffer buf,
const char *  dir,
const char *  fname 
)

Join a directory name and a filename.

Parameters
bufBuffer to add to
dirDirectory name
fnameFile name
Return values
numBytes written to Buffer

If both dir and fname are supplied, they are separated with '/'. If either is missing, then the other will be copied exactly.

Definition at line 372 of file buffer.c.

373 {
374  if (!buf)
375  return 0;
376 
377  if (!dir)
378  dir = "";
379  if (!fname)
380  fname = "";
381 
382  const bool d_set = (dir[0] != '\0');
383  const bool f_set = (fname[0] != '\0');
384  if (!d_set && !f_set)
385  return 0;
386 
387  const int d_len = strlen(dir);
388  const bool slash = d_set && (dir[d_len - 1] == '/');
389 
390  const char *fmt = "%s/%s";
391  if (!f_set || !d_set || slash)
392  fmt = "%s%s";
393 
394  return mutt_buffer_printf(buf, fmt, dir, fname);
395 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:158
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_concatn_path()

size_t mutt_buffer_concatn_path ( struct Buffer buf,
const char *  dir,
size_t  dirlen,
const char *  fname,
size_t  fnamelen 
)

Join a directory name and a filename.

Parameters
bufBuffer for the result
dirDirectory name
dirlenDirectory name
fnameFile name
fnamelenFile name
Return values
numSize of buffer

If both dir and fname are supplied, they are separated with '/'. If either is missing, then the other will be copied exactly.

Definition at line 409 of file buffer.c.

411 {
412  size_t len = 0;
413  mutt_buffer_reset(buf);
414  if (dirlen != 0)
415  len += mutt_buffer_addstr_n(buf, dir, dirlen);
416  if ((dirlen != 0) && (fnamelen != 0))
417  len += mutt_buffer_addch(buf, '/');
418  if (fnamelen != 0)
419  len += mutt_buffer_addstr_n(buf, fname, fnamelen);
420  return len;
421 }
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:238
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_strdup()

char* mutt_buffer_strdup ( const struct Buffer buf)

Copy a Buffer's string.

Parameters
bufBuffer to copy
Return values
ptrCopy of string
Note
Caller must free the returned string

Definition at line 430 of file buffer.c.

431 {
432  if (!buf)
433  return NULL;
434 
435  return mutt_str_dup(buf->data);
436 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_copy()

size_t mutt_buffer_copy ( struct Buffer dst,
const struct Buffer src 
)

Copy a Buffer's contents to another Buffer.

Parameters
dstBuffer for result
srcBuffer to copy
Return values
numBytes written to Buffer
0Error

Definition at line 445 of file buffer.c.

446 {
447  if (!dst)
448  return 0;
449 
450  mutt_buffer_reset(dst);
451  if (!src || !src->data)
452  return 0;
453 
454  return mutt_buffer_addstr_n(dst, src->data, mutt_buffer_len(src));
455 }
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:354
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_seek()

void mutt_buffer_seek ( struct Buffer buf,
size_t  offset 
)

Set current read/write position to offset from beginning.

Parameters
bufBuffer to use
offsetDistance from the beginning

This is used for cases where the buffer is read from A value is placed in the buffer, and then b->dptr is set back to the beginning as a read marker instead of write marker.

Definition at line 466 of file buffer.c.

467 {
468  if (buf)
469  buf->dptr = buf->data + offset;
470 }
+ Here is the caller graph for this function:

Variable Documentation

◆ BufferStepSize

const int BufferStepSize = 128
static

Definition at line 39 of file buffer.c.