NeoMutt  2023-03-22
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 <stdint.h>
#include <stdio.h>
#include <string.h>
#include "buffer.h"
#include "exit.h"
#include "logging.h"
#include "memory.h"
#include "message.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...
 
size_t mutt_buffer_insert (struct Buffer *buf, size_t offset, const char *s)
 Add a string in the middle of 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 52 of file buffer.c.

53{
54 if (!buf)
55 return NULL;
56 memset(buf, 0, sizeof(struct Buffer));
57 return buf;
58}
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 67 of file buffer.c.

68{
69 struct Buffer buf = { 0 };
70 if (size != 0)
71 {
72 buf.dptr = buf.data = mutt_mem_calloc(1, size);
73 buf.dsize = size;
74 }
75 return buf;
76}
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
+ Here is the call graph for this function:

◆ 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 85 of file buffer.c.

86{
87 if (!buf || !buf->data || (buf->dsize == 0))
88 return;
89 memset(buf->data, 0, buf->dsize);
90 mutt_buffer_seek(buf, 0);
91}
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
Definition: buffer.c:521
+ 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 105 of file buffer.c.

106{
107 if (!buf || !s)
108 return 0;
109
110 if (len > (SIZE_MAX - BufferStepSize))
111 {
112 mutt_error(_("Out of memory"));
113 mutt_exit(1);
114 }
115
116 if (!buf->data || !buf->dptr || ((buf->dptr + len + 1) > (buf->data + buf->dsize)))
117 mutt_buffer_alloc(buf, buf->dsize + MAX(BufferStepSize, len + 1));
118
119 memcpy(buf->dptr, s, len);
120 buf->dptr += len;
121 *(buf->dptr) = '\0';
122 return len;
123}
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:313
static const int BufferStepSize
Definition: buffer.c:43
#define mutt_error(...)
Definition: logging.h:87
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:243
#define MAX(a, b)
Definition: memory.h:30
#define _(a)
Definition: message.h:28
+ 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 133 of file buffer.c.

134{
135 if (!buf || !fmt)
136 return 0; /* LCOV_EXCL_LINE */
137
138 mutt_buffer_alloc(buf, 128);
139
140 int doff = buf->dptr - buf->data;
141 int blen = buf->dsize - doff;
142
143 va_list ap_retry;
144 va_copy(ap_retry, ap);
145
146 int len = vsnprintf(buf->dptr, blen, fmt, ap);
147 if (len >= blen)
148 {
149 mutt_buffer_alloc(buf, buf->dsize + len - blen + 1);
150 len = vsnprintf(buf->dptr, len + 1, fmt, ap_retry);
151 }
152 if (len > 0)
153 buf->dptr += len;
154
155 va_end(ap_retry);
156
157 return len;
158}
+ 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 168 of file buffer.c.

169{
170 if (!buf || !fmt)
171 return -1;
172
173 va_list ap;
174
175 va_start(ap, fmt);
177 int len = buffer_printf(buf, fmt, ap);
178 va_end(ap);
179
180 return len;
181}
static int buffer_printf(struct Buffer *buf, const char *fmt, va_list ap)
Format a string into a Buffer.
Definition: buffer.c:133
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
+ 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 189 of file buffer.c.

190{
191 if (!buf)
192 return;
193
194 mutt_buffer_seek(buf, 0);
195
196 if (buf->data && (buf->dsize > 0))
197 {
198 buf->data[buf->dsize - 1] = '\0';
199 buf->dptr = strchr(buf->data, '\0');
200 }
201}
+ 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 211 of file buffer.c.

212{
213 if (!buf || !fmt)
214 return -1;
215
216 va_list ap;
217
218 va_start(ap, fmt);
219 int len = buffer_printf(buf, fmt, ap);
220 va_end(ap);
221
222 return len;
223}
+ 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 233 of file buffer.c.

234{
235 if (!buf || !s)
236 return 0;
237 return mutt_buffer_addstr_n(buf, s, mutt_str_len(s));
238}
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:105
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
+ 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 248 of file buffer.c.

249{
250 if (!buf)
251 return 0;
252 return mutt_buffer_addstr_n(buf, &c, 1);
253}
+ Here is the call graph for this function:

◆ mutt_buffer_insert()

size_t mutt_buffer_insert ( struct Buffer buf,
size_t  offset,
const char *  s 
)

Add a string in the middle of a buffer.

Parameters
bufBuffer
offsetPosition for the insertion
sString to insert
Return values
numCharacters written
-1Error

Definition at line 263 of file buffer.c.

264{
265 if (!buf || !s || (*s == '\0'))
266 {
267 return -1;
268 }
269
270 const size_t slen = mutt_str_len(s);
271 const size_t curlen = mutt_buffer_len(buf);
272 mutt_buffer_alloc(buf, curlen + slen + 1);
273
274 if (offset > curlen)
275 {
276 for (size_t i = curlen; i < offset; ++i)
277 {
278 mutt_buffer_addch(buf, ' ');
279 }
280 mutt_buffer_addstr(buf, s);
281 }
282 else
283 {
284 memmove(buf->data + offset + slen, buf->data + offset, curlen - offset);
285 memcpy(buf->data + offset, s, slen);
286 buf->data[curlen + slen] = '\0';
287 buf->dptr = buf->data + curlen + slen;
288 }
289
290 return mutt_buffer_len(buf) - curlen;
291}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:409
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
+ 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 298 of file buffer.c.

299{
300 if (!buf || !buf->data)
301 return true;
302
303 return (buf->data[0] == '\0');
304}

◆ 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 313 of file buffer.c.

314{
315 if (!buf)
316 return;
317
318 if (buf->data && (new_size <= buf->dsize))
319 return;
320
321 if (new_size > (SIZE_MAX - BufferStepSize))
322 {
323 mutt_error(_("Out of memory"));
324 mutt_exit(1);
325 }
326
327 const bool was_empty = (buf->dptr == NULL);
328 const size_t offset = (buf->dptr && buf->data) ? (buf->dptr - buf->data) : 0;
329
330 buf->dsize = ROUND_UP(new_size + 1, BufferStepSize);
331
332 mutt_mem_realloc(&buf->data, buf->dsize);
333 mutt_buffer_seek(buf, offset);
334
335 // Ensures that initially NULL buf->data is properly terminated
336 if (was_empty)
337 {
338 buf->dptr = buf->data;
339 *buf->dptr = '\0';
340 }
341}
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 347 of file buffer.c.

348{
349 if (!buf || !buf->data)
350 return;
351
352 buf->dptr = NULL;
353 buf->dsize = 0;
354 FREE(&buf->data);
355}
#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 365 of file buffer.c.

366{
368 return mutt_buffer_addstr(buf, s);
369}
+ 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 380 of file buffer.c.

381{
383 return mutt_buffer_addstr_n(buf, s, len);
384}
+ 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 395 of file buffer.c.

396{
398 if (end <= beg)
399 return 0;
400
401 return mutt_buffer_strcpy_n(buf, beg, end - beg);
402}
size_t mutt_buffer_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:380
+ 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 409 of file buffer.c.

410{
411 if (!buf || !buf->data || !buf->dptr)
412 return 0;
413
414 return buf->dptr - buf->data;
415}
+ 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 427 of file buffer.c.

428{
429 if (!buf)
430 return 0;
431
432 if (!dir)
433 dir = "";
434 if (!fname)
435 fname = "";
436
437 const bool d_set = (dir[0] != '\0');
438 const bool f_set = (fname[0] != '\0');
439 if (!d_set && !f_set)
440 return 0;
441
442 const int d_len = strlen(dir);
443 const bool slash = d_set && (dir[d_len - 1] == '/');
444
445 const char *fmt = "%s/%s";
446 if (!f_set || !d_set || slash)
447 fmt = "%s%s";
448
449 return mutt_buffer_printf(buf, fmt, dir, fname);
450}
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
+ 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 464 of file buffer.c.

466{
467 size_t len = 0;
469 if (dirlen != 0)
470 len += mutt_buffer_addstr_n(buf, dir, dirlen);
471 if ((dirlen != 0) && (fnamelen != 0))
472 len += mutt_buffer_addch(buf, '/');
473 if (fnamelen != 0)
474 len += mutt_buffer_addstr_n(buf, fname, fnamelen);
475 return len;
476}
+ 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 485 of file buffer.c.

486{
487 if (!buf)
488 return NULL;
489
490 return mutt_str_dup(buf->data);
491}
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 500 of file buffer.c.

501{
502 if (!dst)
503 return 0;
504
506 if (!src || !src->data)
507 return 0;
508
509 return mutt_buffer_addstr_n(dst, src->data, mutt_buffer_len(src));
510}
+ 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 521 of file buffer.c.

522{
523 if (buf)
524 {
525 buf->dptr = buf->data ? buf->data + offset : NULL;
526 }
527}
+ Here is the caller graph for this function:

Variable Documentation

◆ BufferStepSize

const int BufferStepSize = 128
static

Definition at line 43 of file buffer.c.