common: remove buf_init(), add BUF_INIT and buf_move()

Add a BUF_INIT macro, which makes it easier to initialize a struct buf
to an empty string (without a heap allocation).

Add buf_move() to move the contents of one struct buf to another (the
source is reset to BUF_INIT, analogous to C++ move-assignment).

Use buf_reset() instead of directly calling `free(s->buf)` since the
internal buf may not always be allocated by malloc() now.
This commit is contained in:
John Lindgren 2024-04-14 14:20:57 -04:00 committed by Johan Malm
parent 343918dee0
commit 0573f16693
12 changed files with 122 additions and 90 deletions

View file

@ -8,16 +8,28 @@
#ifndef LABWC_BUF_H
#define LABWC_BUF_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct buf {
/**
* Pointer to underlying string buffer. If alloc != 0, then
* this was allocated via malloc().
*/
char *buf;
/**
* Allocated length of buf. If zero, buf was not allocated
* (either NULL or literal empty string).
*/
int alloc;
/**
* Length of string contents (not including terminating NUL).
* Currently this must be zero if alloc is zero (i.e. non-empty
* literal strings are not allowed).
*/
int len;
};
/** Value used to initialize a struct buf to an empty string */
#define BUF_INIT ((struct buf){.buf = ""})
/**
* buf_expand_tilde - expand ~ in buffer
* @s: buffer
@ -31,13 +43,6 @@ void buf_expand_tilde(struct buf *s);
*/
void buf_expand_shell_variables(struct buf *s);
/**
* buf_init - allocate NULL-terminated C string buffer
* @s: buffer
* Note: use free(s->buf) to free it
*/
void buf_init(struct buf *s);
/**
* buf_add - add data to C string buffer
* @s: buffer
@ -55,13 +60,35 @@ void buf_add_char(struct buf *s, char data);
/**
* buf_clear - clear the buffer, internal allocations are preserved
* @s: buffer
*
* The buffer will be set to a NUL-terminated empty string.
*
* This is the appropriate function to call to re-use the buffer
* in a loop or similar situations as it reuses the existing heap
* allocation.
*/
void buf_clear(struct buf *s);
/**
* buf_reset - reset the buffer, internal allocations are free'd
* @s: buffer
*
* The buffer will be re-initialized to BUF_INIT (empty string).
*
* Inside a loop, consider using buf_clear() instead, as it allows
* reusing the existing heap allocation. buf_reset() should still be
* called after exiting the loop.
*/
void buf_reset(struct buf *s);
/**
* buf_move - move the contents of src to dst, freeing any previous
* allocation of dst and resetting src to BUF_INIT.
*
* dst must either have been initialized with BUF_INIT
* or zeroed out (e.g. created by znew() or on the stack
* with something like struct buf foo = {0}).
*/
void buf_move(struct buf *dst, struct buf *src);
#endif /* LABWC_BUF_H */