mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
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:
parent
343918dee0
commit
0573f16693
12 changed files with 122 additions and 90 deletions
|
|
@ -2,14 +2,15 @@
|
|||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "common/buf.h"
|
||||
#include "common/macros.h"
|
||||
#include "common/mem.h"
|
||||
|
||||
void
|
||||
buf_expand_tilde(struct buf *s)
|
||||
{
|
||||
struct buf new;
|
||||
buf_init(&new);
|
||||
struct buf new = BUF_INIT;
|
||||
for (int i = 0 ; i < s->len ; i++) {
|
||||
if (s->buf[i] == '~') {
|
||||
buf_add(&new, getenv("HOME"));
|
||||
|
|
@ -17,10 +18,7 @@ buf_expand_tilde(struct buf *s)
|
|||
buf_add_char(&new, s->buf[i]);
|
||||
}
|
||||
}
|
||||
free(s->buf);
|
||||
s->buf = new.buf;
|
||||
s->len = new.len;
|
||||
s->alloc = new.alloc;
|
||||
buf_move(s, &new);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -44,10 +42,8 @@ isvalid(char p)
|
|||
void
|
||||
buf_expand_shell_variables(struct buf *s)
|
||||
{
|
||||
struct buf new;
|
||||
struct buf environment_variable;
|
||||
buf_init(&new);
|
||||
buf_init(&environment_variable);
|
||||
struct buf new = BUF_INIT;
|
||||
struct buf environment_variable = BUF_INIT;
|
||||
|
||||
for (int i = 0 ; i < s->len ; i++) {
|
||||
if (s->buf[i] == '$' && isvalid(s->buf[i+1])) {
|
||||
|
|
@ -69,37 +65,43 @@ buf_expand_shell_variables(struct buf *s)
|
|||
buf_add_char(&new, s->buf[i]);
|
||||
}
|
||||
}
|
||||
free(environment_variable.buf);
|
||||
free(s->buf);
|
||||
s->buf = new.buf;
|
||||
s->len = new.len;
|
||||
s->alloc = new.alloc;
|
||||
buf_reset(&environment_variable);
|
||||
buf_move(s, &new);
|
||||
}
|
||||
|
||||
void
|
||||
buf_init(struct buf *s)
|
||||
static void
|
||||
buf_expand(struct buf *s, int new_alloc)
|
||||
{
|
||||
/* we can't assert(!s->buf) here because struct may be uninitialized */
|
||||
|
||||
s->alloc = 256;
|
||||
s->buf = xmalloc(s->alloc);
|
||||
s->buf[0] = '\0';
|
||||
s->len = 0;
|
||||
/*
|
||||
* "s->alloc &&" ensures that s->data is always allocated after
|
||||
* returning (even if new_alloc == 0). The extra check is not
|
||||
* really necessary but makes it easier for analyzers to see
|
||||
* that we never overwrite a string literal.
|
||||
*/
|
||||
if (s->alloc && new_alloc <= s->alloc) {
|
||||
return;
|
||||
}
|
||||
new_alloc = MAX(new_alloc, 256);
|
||||
new_alloc = MAX(new_alloc, s->alloc * 3 / 2);
|
||||
if (s->alloc) {
|
||||
assert(s->buf);
|
||||
s->buf = xrealloc(s->buf, new_alloc);
|
||||
} else {
|
||||
assert(!s->len);
|
||||
s->buf = xmalloc(new_alloc);
|
||||
s->buf[0] = '\0';
|
||||
}
|
||||
s->alloc = new_alloc;
|
||||
}
|
||||
|
||||
void
|
||||
buf_add(struct buf *s, const char *data)
|
||||
{
|
||||
assert(s->buf);
|
||||
|
||||
if (!data || data[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
int len = strlen(data);
|
||||
if (s->alloc <= s->len + len + 1) {
|
||||
s->alloc = s->alloc + len;
|
||||
s->buf = xrealloc(s->buf, s->alloc);
|
||||
}
|
||||
buf_expand(s, s->len + len + 1);
|
||||
memcpy(s->buf + s->len, data, len);
|
||||
s->len += len;
|
||||
s->buf[s->len] = 0;
|
||||
|
|
@ -108,12 +110,7 @@ buf_add(struct buf *s, const char *data)
|
|||
void
|
||||
buf_add_char(struct buf *s, char ch)
|
||||
{
|
||||
assert(s->buf);
|
||||
|
||||
if (s->alloc <= s->len + 1) {
|
||||
s->alloc = s->alloc * 3 / 2 + 16;
|
||||
s->buf = xrealloc(s->buf, s->alloc);
|
||||
}
|
||||
buf_expand(s, s->len + 1);
|
||||
s->buf[s->len++] = ch;
|
||||
s->buf[s->len] = '\0';
|
||||
}
|
||||
|
|
@ -121,15 +118,30 @@ buf_add_char(struct buf *s, char ch)
|
|||
void
|
||||
buf_clear(struct buf *s)
|
||||
{
|
||||
assert(s->buf);
|
||||
|
||||
s->len = 0;
|
||||
s->buf[0] = '\0';
|
||||
if (s->alloc) {
|
||||
assert(s->buf);
|
||||
s->len = 0;
|
||||
s->buf[0] = '\0';
|
||||
} else {
|
||||
*s = BUF_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
buf_reset(struct buf *s)
|
||||
{
|
||||
zfree(s->buf);
|
||||
buf_init(s);
|
||||
if (s->alloc) {
|
||||
free(s->buf);
|
||||
}
|
||||
*s = BUF_INIT;
|
||||
}
|
||||
|
||||
void
|
||||
buf_move(struct buf *dst, struct buf *src)
|
||||
{
|
||||
if (dst->alloc) {
|
||||
free(dst->buf);
|
||||
}
|
||||
*dst = *src;
|
||||
*src = BUF_INIT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,10 +87,10 @@ find_dir(struct ctx *ctx)
|
|||
{
|
||||
char *debug = getenv("LABWC_DEBUG_DIR_CONFIG_AND_THEME");
|
||||
|
||||
struct buf prefix = BUF_INIT;
|
||||
for (int i = 0; ctx->dirs[i].path; i++) {
|
||||
struct dir d = ctx->dirs[i];
|
||||
struct buf prefix;
|
||||
buf_init(&prefix);
|
||||
buf_clear(&prefix);
|
||||
|
||||
/*
|
||||
* Replace (rather than augment) $HOME/.config with
|
||||
|
|
@ -100,7 +100,6 @@ find_dir(struct ctx *ctx)
|
|||
char *pfxenv = getenv(d.prefix);
|
||||
buf_add(&prefix, pfxenv ? pfxenv : d.default_prefix);
|
||||
if (!prefix.len) {
|
||||
free(prefix.buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -130,8 +129,8 @@ find_dir(struct ctx *ctx)
|
|||
wl_list_append(ctx->list, &path->link);
|
||||
}
|
||||
g_strfreev(prefixes);
|
||||
free(prefix.buf);
|
||||
}
|
||||
buf_reset(&prefix);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -10,18 +10,19 @@
|
|||
#include "common/buf.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char *
|
||||
struct buf
|
||||
grab_file(const char *filename)
|
||||
{
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
FILE *stream = fopen(filename, "r");
|
||||
if (!stream) {
|
||||
return NULL;
|
||||
return BUF_INIT;
|
||||
}
|
||||
struct buf buffer;
|
||||
buf_init(&buffer);
|
||||
struct buf buffer = BUF_INIT;
|
||||
while ((getline(&line, &len, stream) != -1)) {
|
||||
char *p = strrchr(line, '\n');
|
||||
if (p) {
|
||||
|
|
@ -31,5 +32,5 @@ grab_file(const char *filename)
|
|||
}
|
||||
free(line);
|
||||
fclose(stream);
|
||||
return buffer.buf;
|
||||
return buffer;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue