NeoMutt  2022-04-29-249-gaae397
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...
 
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:483
+ 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:275
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:248
#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:
+ 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 260 of file buffer.c.

261{
262 if (!buf || !buf->data)
263 return true;
264
265 return (buf->data[0] == '\0');
266}

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

276{
277 if (!buf)
278 return;
279
280 if (buf->data && (new_size <= buf->dsize))
281 return;
282
283 if (new_size > (SIZE_MAX - BufferStepSize))
284 {
285 mutt_error(_("Out of memory"));
286 mutt_exit(1);
287 }
288
289 const bool was_empty = (buf->dptr == NULL);
290 const size_t offset = (buf->dptr && buf->data) ? (buf->dptr - buf->data) : 0;
291
292 buf->dsize = ROUND_UP(new_size + 1, BufferStepSize);
293
294 mutt_mem_realloc(&buf->data, buf->dsize);
295 mutt_buffer_seek(buf, offset);
296
297 // Ensures that initially NULL buf->data is properly terminated
298 if (was_empty)
299 {
300 buf->dptr = buf->data;
301 *buf->dptr = '\0';
302 }
303}
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 309 of file buffer.c.

310{
311 if (!buf || !buf->data)
312 return;
313
314 buf->dptr = NULL;
315 buf->dsize = 0;
316 FREE(&buf->data);
317}
#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 327 of file buffer.c.

328{
330 return mutt_buffer_addstr(buf, s);
331}
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:

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

343{
345 return mutt_buffer_addstr_n(buf, s, len);
346}
+ 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 357 of file buffer.c.

358{
360 if (end <= beg)
361 return 0;
362
363 return mutt_buffer_strcpy_n(buf, beg, end - beg);
364}
size_t mutt_buffer_strcpy_n(struct Buffer *buf, const char *s, size_t len)
Copy a string into a Buffer.
Definition: buffer.c:342
+ 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 371 of file buffer.c.

372{
373 if (!buf || !buf->data || !buf->dptr)
374 return 0;
375
376 return buf->dptr - buf->data;
377}
+ 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 389 of file buffer.c.

390{
391 if (!buf)
392 return 0;
393
394 if (!dir)
395 dir = "";
396 if (!fname)
397 fname = "";
398
399 const bool d_set = (dir[0] != '\0');
400 const bool f_set = (fname[0] != '\0');
401 if (!d_set && !f_set)
402 return 0;
403
404 const int d_len = strlen(dir);
405 const bool slash = d_set && (dir[d_len - 1] == '/');
406
407 const char *fmt = "%s/%s";
408 if (!f_set || !d_set || slash)
409 fmt = "%s%s";
410
411 return mutt_buffer_printf(buf, fmt, dir, fname);
412}
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 426 of file buffer.c.

428{
429 size_t len = 0;
431 if (dirlen != 0)
432 len += mutt_buffer_addstr_n(buf, dir, dirlen);
433 if ((dirlen != 0) && (fnamelen != 0))
434 len += mutt_buffer_addch(buf, '/');
435 if (fnamelen != 0)
436 len += mutt_buffer_addstr_n(buf, fname, fnamelen);
437 return len;
438}
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
+ 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 447 of file buffer.c.

448{
449 if (!buf)
450 return NULL;
451
452 return mutt_str_dup(buf->data);
453}
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 462 of file buffer.c.

463{
464 if (!dst)
465 return 0;
466
468 if (!src || !src->data)
469 return 0;
470
471 return mutt_buffer_addstr_n(dst, src->data, mutt_buffer_len(src));
472}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:371
+ 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 483 of file buffer.c.

484{
485 if (buf)
486 {
487 buf->dptr = buf->data ? buf->data + offset : NULL;
488 }
489}
+ Here is the caller graph for this function:

Variable Documentation

◆ BufferStepSize

const int BufferStepSize = 128
static

Definition at line 43 of file buffer.c.