From ffb900d872a456cc5e7cc1762b1846c0c4df08cd Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Mon, 26 Jun 2023 16:06:26 +0200 Subject: [PATCH] String functions that return str8/16/32 allocated on an arena implicitly zero-terminate strings, so we can avoid one copy when passing to C stdlib APIs --- src/platform/osx_path.m | 3 ++- src/platform/platform_path.h | 6 ++++++ src/platform/win32_path.c | 6 ++++-- src/util/strings.c | 35 ++++++++++++++++++----------------- src/util/strings.h | 12 +++++++++++- 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/platform/osx_path.m b/src/platform/osx_path.m index 575f6c8..28c7eb4 100644 --- a/src/platform/osx_path.m +++ b/src/platform/osx_path.m @@ -23,8 +23,9 @@ str8 path_executable(mem_arena* arena) u32 size = 0; _NSGetExecutablePath(0, &size); result.len = size; - result.ptr = mem_arena_alloc_array(arena, char, result.len); + result.ptr = mem_arena_alloc_array(arena, char, result.len+1); _NSGetExecutablePath(result.ptr, &size); + result.ptr[result.len] = '\0'; return(result); }} diff --git a/src/platform/platform_path.h b/src/platform/platform_path.h index 7665204..da1c23f 100644 --- a/src/platform/platform_path.h +++ b/src/platform/platform_path.h @@ -10,6 +10,12 @@ #include"util/strings.h" +/*NOTE: + by convention, functions that take an arena and return a path + allocated on that arena allocate 1 more character and null-terminate + the string. +*/ + MP_API str8 path_slice_directory(str8 path); MP_API str8 path_slice_filename(str8 path); diff --git a/src/platform/win32_path.c b/src/platform/win32_path.c index a3d8bad..9f39f12 100644 --- a/src/platform/win32_path.c +++ b/src/platform/win32_path.c @@ -22,8 +22,11 @@ bool path_is_absolute(str8 path) str8 path_executable(mem_arena* arena) { + /////////////////////////////////////////////////////////////////// //TODO use wide chars - char* buffer = mem_arena_alloc_array(arena, char, MAX_PATH+1); + /////////////////////////////////////////////////////////////////// + + char* buffer = mem_arena_alloc_array(arena, char, MAX_PATH+2); int size = GetModuleFileName(NULL, buffer, MAX_PATH+1); //TODO: check for errors... for(int i=0; istring.len; } memcpy(dst, postfix.ptr, postfix.len); + str.ptr[str.len] = '\0'; return(str); } @@ -239,8 +236,9 @@ str16 str16_push_buffer(mem_arena* arena, u64 len, u16* buffer) { str16 str = {0}; str.len = len; - str.ptr = mem_arena_alloc_array(arena, u16, len); + str.ptr = mem_arena_alloc_array(arena, u16, len+1); memcpy(str.ptr, buffer, len*sizeof(u16)); + str.ptr[str.len] = (u16)0; return(str); } @@ -275,7 +273,7 @@ str16 str16_list_collate(mem_arena* arena, str16_list list, str16 prefix, str16 { str16 str = {0}; str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len; - str.ptr = mem_arena_alloc_array(arena, u16, str.len); + str.ptr = mem_arena_alloc_array(arena, u16, str.len + 1); char* dst = (char*)str.ptr; memcpy(dst, prefix.ptr, prefix.len*sizeof(u16)); dst += prefix.len*sizeof(u16); @@ -296,6 +294,7 @@ str16 str16_list_collate(mem_arena* arena, str16_list list, str16 prefix, str16 dst += elt->string.len*sizeof(u16); } memcpy(dst, postfix.ptr, postfix.len*sizeof(u16)); + str.ptr[str.len] = (u16)0; return(str); } @@ -323,8 +322,9 @@ str32 str32_push_buffer(mem_arena* arena, u64 len, u32* buffer) { str32 str = {0}; str.len = len; - str.ptr = mem_arena_alloc_array(arena, u32, len); + str.ptr = mem_arena_alloc_array(arena, u32, len+1); memcpy(str.ptr, buffer, len*sizeof(u32)); + str.ptr[str.len] = 0; return(str); } @@ -359,7 +359,7 @@ str32 str32_list_collate(mem_arena* arena, str32_list list, str32 prefix, str32 { str32 str = {0}; str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len; - str.ptr = mem_arena_alloc_array(arena, u32, str.len); + str.ptr = mem_arena_alloc_array(arena, u32, str.len+1); char* dst = (char*)str.ptr; memcpy(dst, prefix.ptr, prefix.len*sizeof(u32)); dst += prefix.len*sizeof(u32); @@ -380,6 +380,7 @@ str32 str32_list_collate(mem_arena* arena, str32_list list, str32 prefix, str32 dst += elt->string.len*sizeof(u32); } memcpy(dst, postfix.ptr, postfix.len*sizeof(u32)); + str.ptr[str.len] = 0; return(str); } diff --git a/src/util/strings.h b/src/util/strings.h index fdc0876..6507ed0 100644 --- a/src/util/strings.h +++ b/src/util/strings.h @@ -19,8 +19,18 @@ extern "C" { #endif +/*NOTE: + By convention, functions that take an arena and return a string slice allocated on + this arena, always allocate one more element and null-terminate the string. This is + done so we can pass those strings directly to C APIs that requires C strings without + having to do a copy with str8_to_cstring(). + + This does _not_ applies to the string returned by str8_split(). Those are slices + into the original string. Only the _list nodes_ are allocated on the arena. +*/ + //---------------------------------------------------------------------------------- -// string slices as values +// u8 strings //---------------------------------------------------------------------------------- typedef struct str8 {