Skip to content

Commit 499becc

Browse files
authored
util, treewide: improve string handling (#33)
* treewide: rename str -> strbuf This makes the type name more in line with what it actually is (a mutable buffer holding a string) and is in preparation for adding a new str type which instead acts similar to Rust's str or C++'s std::string_view in an effort to move away from null terminated strings. * util: make strbuf a struct Using an SDS-style string was interesting but I don't think the benefits are worth the complexity. It also prevents _Generic from disambiguating between strbuf and C strings. * util: add str This is intended to serve a similar purpose to Rust's str or C++'s std::string_view. * test: add tests for str, strbuf * util: add str_clone_cstr, str_from * env_reexec: use str for environment manipulation * config: use str for action parsing * util: add strbuf_clone_cstr * server: use strbuf for X11 window title * util: add ww_strdup ww_strdup wraps strdup with a NULL check to avoid having to spam check_alloc everywhere. * treewide: use ww_strdup * config, subproc, wrap: use strs for subprocesses This removes the 63 argument limit (not that anyone was realistically limited by it.) * util: remove 0 capacity restriction on strbuf
1 parent 2b93980 commit 499becc

27 files changed

+567
-319
lines changed

.clang-format-include

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include/**.h
22
waywall/**.c
3+
test/**.c

doc/02_waywall_exec.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# exec
22

3-
This function asynchronously executes the given command as a subprocess. No
4-
sophisticated argument processing is performed; quoting arguments or performing
5-
shell substitutions will require you to run a shell script. A maximum of 63
6-
space-delimited arguments can be provided in the command string.
3+
This function asynchronously executes the given command as a subprocess.
4+
Arguments are split by spaces and no further processing is performed; quoting
5+
arguments or performing shell substitutions will require you to run a shell
6+
script.
77

88
If the spawned subprocess does not exit before waywall, it will be killed with
99
`SIGKILL` when waywall closes.

include/instance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ struct instance {
3434

3535
struct instance *instance_create(struct server_view *view, struct inotify *inotify);
3636
void instance_destroy(struct instance *instance);
37-
str instance_get_state_path(struct instance *instance);
37+
strbuf instance_get_state_path(struct instance *instance);
3838
void instance_state_update(struct instance *instance);

include/reload.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct reload {
1515
reload_func_t func;
1616
void *data;
1717

18-
str config_path;
18+
strbuf config_path;
1919
int config_dir_wd;
2020
struct list_int config_wd;
2121

include/subproc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "util/list.h"
4+
#include "util/str.h"
45
#include <sys/types.h>
56

67
LIST_DEFINE(struct subproc_entry, list_subproc_entry);
@@ -18,4 +19,4 @@ struct subproc_entry {
1819

1920
struct subproc *subproc_create(struct server *server);
2021
void subproc_destroy(struct subproc *subproc);
21-
void subproc_exec(struct subproc *subproc, char *cmd[static 64]);
22+
void subproc_exec(struct subproc *subproc, struct strs cmd);

include/util/alloc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "util/prelude.h"
44
#include <stddef.h>
55
#include <stdlib.h>
6+
#include <string.h>
67

78
#define check_alloc(data) \
89
do { \
@@ -11,6 +12,15 @@
1112
} \
1213
} while (0)
1314

15+
static inline char *
16+
ww_strdup(const char *str) {
17+
ww_assert(str);
18+
19+
char *dup = strdup(str);
20+
check_alloc(dup);
21+
return dup;
22+
}
23+
1424
static inline void *
1525
zalloc(size_t nmemb, size_t size) {
1626
void *data = calloc(nmemb, size);

include/util/str.h

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,48 @@
11
#pragma once
22

3-
typedef char *str;
3+
#include <sys/types.h>
44

5-
void str_append(str *dst, const char *src);
6-
void str_clear(str str);
7-
void str_free(str str);
8-
str str_new();
5+
#define str_lit(lit) ((str){sizeof(lit) - 1, lit})
6+
7+
typedef struct {
8+
ssize_t len;
9+
const char *data;
10+
} str;
11+
12+
typedef struct {
13+
ssize_t len, cap;
14+
char *data;
15+
} strbuf;
16+
17+
struct strs {
18+
ssize_t len;
19+
str *data;
20+
};
21+
22+
#define strbuf_append(dst, src) \
23+
_Generic((src), \
24+
int: strbuf_append_char, \
25+
strbuf: strbuf_append_buf, \
26+
str: strbuf_append_str, \
27+
default: strbuf_append_cstr)(dst, src)
28+
29+
void strbuf_append_char(strbuf *dst, char src);
30+
void strbuf_append_cstr(strbuf *dst, const char *src);
31+
void strbuf_append_buf(strbuf *dst, strbuf src);
32+
void strbuf_append_str(strbuf *dst, str src);
33+
void strbuf_clear(strbuf *buf);
34+
char *strbuf_clone_cstr(strbuf buf);
35+
void strbuf_free(strbuf *buf);
36+
strbuf strbuf_new();
37+
str strbuf_view(strbuf buf);
38+
39+
strbuf str_clone(str s);
40+
char *str_clone_cstr(str s);
41+
bool str_eq(str a, str b);
42+
str str_from(const char *cstr);
43+
ssize_t str_index(str s, char needle, ssize_t start);
44+
str str_slice(str s, ssize_t start, ssize_t end);
45+
struct strs str_split(str s, char sep);
46+
47+
void strs_free(struct strs strs);
48+
ssize_t strs_index(struct strs strs, str s, ssize_t start);

include/wrap.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "util/box.h"
4+
#include "util/str.h"
45
#include <stdint.h>
56
#include <wayland-server-core.h>
67

@@ -55,7 +56,7 @@ struct wrap *wrap_create(struct server *server, struct inotify *inotify, struct
5556
void wrap_destroy(struct wrap *wrap);
5657
int wrap_set_config(struct wrap *wrap, struct config *cfg);
5758

58-
void wrap_lua_exec(struct wrap *wrap, char *cmd[static 64]);
59+
void wrap_lua_exec(struct wrap *wrap, struct strs cmd);
5960
void wrap_lua_press_key(struct wrap *wrap, uint32_t keycode);
6061
int wrap_lua_set_res(struct wrap *wrap, int32_t width, int32_t height);
6162
void wrap_lua_show_floating(struct wrap *wrap, bool show);

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,4 @@ waywall_deps = [
7575

7676
subdir('protocol')
7777
subdir('waywall')
78+
subdir('test')

test/meson.build

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
waywall_tests = {
2+
'str': ['util/prelude.c', 'util/str.c']
3+
}
4+
5+
foreach name, extra_src : waywall_tests
6+
fixed_extra_src = []
7+
foreach _extra_src : extra_src
8+
fixed_extra_src += meson.global_source_root() + '/waywall/' + _extra_src
9+
endforeach
10+
11+
test(name, executable('test_' + name,
12+
files(name + '.c'),
13+
files(fixed_extra_src),
14+
15+
include_directories: includes,
16+
))
17+
endforeach

0 commit comments

Comments
 (0)