aboutsummaryrefslogtreecommitdiff
path: root/cstring/include
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2021-12-04 16:01:12 -0800
committer3gg <3gg@shellblade.net>2021-12-04 16:01:12 -0800
commitf8217d240d598f39f70047f7a623dd46312542c6 (patch)
tree4e40843d665e388416c1226f739c2b8c0b8da736 /cstring/include
parent5f6ea503cdb6ad4a95b679672a1ad324d96c89a5 (diff)
Initial commit.
Diffstat (limited to 'cstring/include')
-rw-r--r--cstring/include/cstring.h64
1 files changed, 64 insertions, 0 deletions
diff --git a/cstring/include/cstring.h b/cstring/include/cstring.h
new file mode 100644
index 0000000..644f1e1
--- /dev/null
+++ b/cstring/include/cstring.h
@@ -0,0 +1,64 @@
1/// Fixed-size strings with value semantics.
2#pragma once
3
4#include <assert.h>
5#include <bsd/string.h>
6
7/// A fixed-size string.
8/// The string is null-terminated so that it can be used with the usual C APIs.
9#define DEF_STRING(STRING, SIZE) \
10 typedef struct STRING { \
11 int length; \
12 char str[SIZE]; \
13 } STRING; \
14 \
15 static const size_t STRING##_size = SIZE; \
16 \
17 static inline const char* STRING##_cstring(const STRING* str) { \
18 return str->str; \
19 } \
20 \
21 static inline STRING STRING##_make(const char* cstr) { \
22 if (!cstr) { \
23 return (STRING){0}; \
24 } else { \
25 STRING str = (STRING){0}; \
26 str.length = strlcpy(str.str, cstr, SIZE); \
27 return str; \
28 } \
29 } \
30 \
31 static inline STRING STRING##_dirname(STRING path) { \
32 STRING str = path; \
33 for (int i = str.length - 1; i >= 0; --i) { \
34 if (str.str[i] == '/' || str.str[i] == '\\') { \
35 str.str[i] = 0; \
36 str.length = i; \
37 return str; \
38 } else { \
39 str.str[i] = 0; \
40 } \
41 } \
42 str = (STRING){0}; \
43 str.str[0] = '.'; \
44 str.length = 1; \
45 return str; \
46 } \
47 \
48 static inline STRING STRING##_concat(STRING a, STRING b) { \
49 assert(a.length + b.length + 1 < SIZE); \
50 STRING str = {0}; \
51 strlcpy(str.str, a.str, SIZE); \
52 strlcpy(str.str + a.length, b.str, SIZE); \
53 str.length = a.length + b.length; \
54 return str; \
55 } \
56 \
57 static inline STRING STRING##_concat_path(STRING a, STRING b) { \
58 return STRING##_concat(STRING##_concat(a, STRING##_make("/")), b); \
59 }
60
61DEF_STRING(sstring, 32) // Small.
62DEF_STRING(mstring, 256) // Medium.
63DEF_STRING(lstring, 1024) // Large.
64DEF_STRING(xlstring, 4096) // Extra large.