From 158b6e1fd42c744b9a7210db316af3de292f8b1c Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 15 Jul 2021 14:58:29 +0100 Subject: [PATCH] Added `_str_raw_to_cstrsa()`: Convert raw buffer to nul-terminated string that is dynamically allocated and statically held. (i.e. do not `free()`) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for naka's current commit: Blessing − 吉 --- src/str.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/str.c b/src/str.c index 89381ba..c0cea03 100644 --- a/src/str.c +++ b/src/str.c @@ -31,7 +31,50 @@ struct string { //TODO: We can use offsetof() to reverse the result of `str_new()` from char* (str field) to str_t*. +inline static isize _str_wrap_index(usize _max, isize wr) +{ + isize max = (isize)_max; + ifU(max<0) FATAL("max too large, must be <= isize::max (%lu)", SIZE_MAX>>1); + else if(!max) return 0; + + while(wr<0) wr = max + wr; + wr = wr >=max ? wr % max : wr; + debug_assert(wr>0); + return wr; +} + +// Create a cstring (nul-terminated) from `from`. This string is statically allocated and should not be modified. +// `sl` - Max size of `from` buffer. If 0, then just free the allocated buffer and return empty string; +// `from` - Non-nul-terminated string buffer to copy from. +// `len` - A pointer to a wrappable index for `from`. If `len` is negative, then offset from `sl`, if it's positive, offset from 0; if it's NULL, use `sl` itself. It is wrapped around `sl` in the case that the computed offset is >= sl. +// +// # Notes +// Don't `free()` this returned pointer, this function handles that on call and on program exit. +static const char* _str_raw_to_cstrsa(usize sl, const char from[restrict sl], isize*pINOUT len) +{ + static _Thread_local char* _ma_buf = NULL; + + if(!sl) { + free(_ma_buf); //free(NULL) is allowed. + _ma_buf=NULL; + return ""; + } + _callcv(exit) void _cleanup() { free(_ma_buf); _ma_buf = NULL; } + + isize fp = (isize) (sl & (SIZE_MAX >> 1)); + if(!len) len = &fp; + TRACE("copying wrapped %ld bytes from buffer %p[%lu]", *len, from, sl); + + + usize rl = (usize) (*len = _str_wrap_index(sl, *len)); + + if(_ma_buf) _ma_buf = realloc(_ma_buf, rl+1); + else _ma_buf = malloc(rl+1); + memmove(_ma_buf, from, rl); + _ma_buf[rl] = 0; + return (const char*)_ma_buf; +} inline static bool _str_meta_is_owned(enum str_ownership owned) {