From f8217d240d598f39f70047f7a623dd46312542c6 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 4 Dec 2021 16:01:12 -0800 Subject: Initial commit. --- cstring/CMakeLists.txt | 11 ++++++++ cstring/include/cstring.h | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 cstring/CMakeLists.txt create mode 100644 cstring/include/cstring.h (limited to 'cstring') 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 @@ +cmake_minimum_required(VERSION 3.16) + +project(cstring) + +add_library(cstring INTERFACE) + +target_include_directories(cstring INTERFACE + include) + +target_link_libraries(cstring INTERFACE + -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 @@ +/// Fixed-size strings with value semantics. +#pragma once + +#include +#include + +/// A fixed-size string. +/// The string is null-terminated so that it can be used with the usual C APIs. +#define DEF_STRING(STRING, SIZE) \ + typedef struct STRING { \ + int length; \ + char str[SIZE]; \ + } STRING; \ + \ + static const size_t STRING##_size = SIZE; \ + \ + static inline const char* STRING##_cstring(const STRING* str) { \ + return str->str; \ + } \ + \ + static inline STRING STRING##_make(const char* cstr) { \ + if (!cstr) { \ + return (STRING){0}; \ + } else { \ + STRING str = (STRING){0}; \ + str.length = strlcpy(str.str, cstr, SIZE); \ + return str; \ + } \ + } \ + \ + static inline STRING STRING##_dirname(STRING path) { \ + STRING str = path; \ + for (int i = str.length - 1; i >= 0; --i) { \ + if (str.str[i] == '/' || str.str[i] == '\\') { \ + str.str[i] = 0; \ + str.length = i; \ + return str; \ + } else { \ + str.str[i] = 0; \ + } \ + } \ + str = (STRING){0}; \ + str.str[0] = '.'; \ + str.length = 1; \ + return str; \ + } \ + \ + static inline STRING STRING##_concat(STRING a, STRING b) { \ + assert(a.length + b.length + 1 < SIZE); \ + STRING str = {0}; \ + strlcpy(str.str, a.str, SIZE); \ + strlcpy(str.str + a.length, b.str, SIZE); \ + str.length = a.length + b.length; \ + return str; \ + } \ + \ + static inline STRING STRING##_concat_path(STRING a, STRING b) { \ + return STRING##_concat(STRING##_concat(a, STRING##_make("/")), b); \ + } + +DEF_STRING(sstring, 32) // Small. +DEF_STRING(mstring, 256) // Medium. +DEF_STRING(lstring, 1024) // Large. +DEF_STRING(xlstring, 4096) // Extra large. -- cgit v1.2.3