diff options
| author | 3gg <3gg@shellblade.net> | 2021-12-04 16:01:12 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2021-12-04 16:01:12 -0800 |
| commit | f8217d240d598f39f70047f7a623dd46312542c6 (patch) | |
| tree | 4e40843d665e388416c1226f739c2b8c0b8da736 /cstring | |
| parent | 5f6ea503cdb6ad4a95b679672a1ad324d96c89a5 (diff) | |
Initial commit.
Diffstat (limited to 'cstring')
| -rw-r--r-- | cstring/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | cstring/include/cstring.h | 64 |
2 files changed, 75 insertions, 0 deletions
diff --git a/cstring/CMakeLists.txt b/cstring/CMakeLists.txt new file mode 100644 index 0000000..67fb366 --- /dev/null +++ b/cstring/CMakeLists.txt | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | cmake_minimum_required(VERSION 3.16) | ||
| 2 | |||
| 3 | project(cstring) | ||
| 4 | |||
| 5 | add_library(cstring INTERFACE) | ||
| 6 | |||
| 7 | target_include_directories(cstring INTERFACE | ||
| 8 | include) | ||
| 9 | |||
| 10 | target_link_libraries(cstring INTERFACE | ||
| 11 | -lbsd) | ||
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 | |||
| 61 | DEF_STRING(sstring, 32) // Small. | ||
| 62 | DEF_STRING(mstring, 256) // Medium. | ||
| 63 | DEF_STRING(lstring, 1024) // Large. | ||
| 64 | DEF_STRING(xlstring, 4096) // Extra large. | ||
