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
This commit is contained in:
parent
4b491ee94a
commit
ffb900d872
|
@ -23,8 +23,9 @@ str8 path_executable(mem_arena* arena)
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
_NSGetExecutablePath(0, &size);
|
_NSGetExecutablePath(0, &size);
|
||||||
result.len = 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);
|
_NSGetExecutablePath(result.ptr, &size);
|
||||||
|
result.ptr[result.len] = '\0';
|
||||||
return(result);
|
return(result);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,12 @@
|
||||||
|
|
||||||
#include"util/strings.h"
|
#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_directory(str8 path);
|
||||||
MP_API str8 path_slice_filename(str8 path);
|
MP_API str8 path_slice_filename(str8 path);
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,11 @@ bool path_is_absolute(str8 path)
|
||||||
|
|
||||||
str8 path_executable(mem_arena* arena)
|
str8 path_executable(mem_arena* arena)
|
||||||
{
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////
|
||||||
//TODO use wide chars
|
//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);
|
int size = GetModuleFileName(NULL, buffer, MAX_PATH+1);
|
||||||
//TODO: check for errors...
|
//TODO: check for errors...
|
||||||
for(int i=0; i<size; i++)
|
for(int i=0; i<size; i++)
|
||||||
|
@ -33,7 +36,6 @@ str8 path_executable(mem_arena* arena)
|
||||||
buffer[i] = '/';
|
buffer[i] = '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(str8_from_buffer(size, buffer));
|
return(str8_from_buffer(size, buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,21 +28,20 @@ str8 str8_push_buffer(mem_arena* arena, u64 len, char* buffer)
|
||||||
{
|
{
|
||||||
str8 str = {0};
|
str8 str = {0};
|
||||||
str.len = len;
|
str.len = len;
|
||||||
str.ptr = mem_arena_alloc_array(arena, char, len);
|
str.ptr = mem_arena_alloc_array(arena, char, len+1);
|
||||||
memcpy(str.ptr, buffer, len);
|
memcpy(str.ptr, buffer, len);
|
||||||
|
str.ptr[str.len] = '\0';
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
str8 str8_push_cstring(mem_arena* arena, const char* str)
|
str8 str8_push_cstring(mem_arena* arena, const char* str)
|
||||||
{
|
{
|
||||||
if(!str)
|
int len = 0;
|
||||||
|
if(str)
|
||||||
{
|
{
|
||||||
return((str8){0});
|
len = strlen(str);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return(str8_push_buffer(arena, strlen(str), (char*)str));
|
|
||||||
}
|
}
|
||||||
|
return(str8_push_buffer(arena, strlen(str), (char*)str));
|
||||||
}
|
}
|
||||||
|
|
||||||
str8 str8_push_copy(mem_arena* arena, str8 s)
|
str8 str8_push_copy(mem_arena* arena, str8 s)
|
||||||
|
@ -60,11 +59,8 @@ str8 str8_pushfv(mem_arena* arena, const char* format, va_list args)
|
||||||
{
|
{
|
||||||
//NOTE(martin):
|
//NOTE(martin):
|
||||||
// We first compute the number of characters to write passing a size of 0.
|
// We first compute the number of characters to write passing a size of 0.
|
||||||
// then we allocate len+1 (since vsnprint always terminates with a '\0').
|
// then we allocate len+1 (since vsnprint always terminates with a '\0').
|
||||||
// We could call vsprintf since we know the size, but I'm not sure there's a hard
|
|
||||||
// guarantee that vsprintf and vsnprintf write the same number of characters in all
|
|
||||||
// and every case, and that would be a difficult bug to spot, so it seems better to
|
|
||||||
// waste one byte and be safe.
|
|
||||||
char dummy;
|
char dummy;
|
||||||
str8 str = {0};
|
str8 str = {0};
|
||||||
va_list argCopy;
|
va_list argCopy;
|
||||||
|
@ -137,7 +133,7 @@ str8 str8_list_collate(mem_arena* arena, str8_list list, str8 prefix, str8 separ
|
||||||
{
|
{
|
||||||
str8 str = {0};
|
str8 str = {0};
|
||||||
str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len;
|
str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len;
|
||||||
str.ptr = mem_arena_alloc_array(arena, char, str.len);
|
str.ptr = mem_arena_alloc_array(arena, char, str.len + 1);
|
||||||
char* dst = str.ptr;
|
char* dst = str.ptr;
|
||||||
memcpy(dst, prefix.ptr, prefix.len);
|
memcpy(dst, prefix.ptr, prefix.len);
|
||||||
dst += prefix.len;
|
dst += prefix.len;
|
||||||
|
@ -158,6 +154,7 @@ str8 str8_list_collate(mem_arena* arena, str8_list list, str8 prefix, str8 separ
|
||||||
dst += elt->string.len;
|
dst += elt->string.len;
|
||||||
}
|
}
|
||||||
memcpy(dst, postfix.ptr, postfix.len);
|
memcpy(dst, postfix.ptr, postfix.len);
|
||||||
|
str.ptr[str.len] = '\0';
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +236,9 @@ str16 str16_push_buffer(mem_arena* arena, u64 len, u16* buffer)
|
||||||
{
|
{
|
||||||
str16 str = {0};
|
str16 str = {0};
|
||||||
str.len = len;
|
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));
|
memcpy(str.ptr, buffer, len*sizeof(u16));
|
||||||
|
str.ptr[str.len] = (u16)0;
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +273,7 @@ str16 str16_list_collate(mem_arena* arena, str16_list list, str16 prefix, str16
|
||||||
{
|
{
|
||||||
str16 str = {0};
|
str16 str = {0};
|
||||||
str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len;
|
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;
|
char* dst = (char*)str.ptr;
|
||||||
memcpy(dst, prefix.ptr, prefix.len*sizeof(u16));
|
memcpy(dst, prefix.ptr, prefix.len*sizeof(u16));
|
||||||
dst += 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);
|
dst += elt->string.len*sizeof(u16);
|
||||||
}
|
}
|
||||||
memcpy(dst, postfix.ptr, postfix.len*sizeof(u16));
|
memcpy(dst, postfix.ptr, postfix.len*sizeof(u16));
|
||||||
|
str.ptr[str.len] = (u16)0;
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,8 +322,9 @@ str32 str32_push_buffer(mem_arena* arena, u64 len, u32* buffer)
|
||||||
{
|
{
|
||||||
str32 str = {0};
|
str32 str = {0};
|
||||||
str.len = len;
|
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));
|
memcpy(str.ptr, buffer, len*sizeof(u32));
|
||||||
|
str.ptr[str.len] = 0;
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,7 +359,7 @@ str32 str32_list_collate(mem_arena* arena, str32_list list, str32 prefix, str32
|
||||||
{
|
{
|
||||||
str32 str = {0};
|
str32 str = {0};
|
||||||
str.len = prefix.len + list.len + list.eltCount*separator.len + postfix.len;
|
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;
|
char* dst = (char*)str.ptr;
|
||||||
memcpy(dst, prefix.ptr, prefix.len*sizeof(u32));
|
memcpy(dst, prefix.ptr, prefix.len*sizeof(u32));
|
||||||
dst += 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);
|
dst += elt->string.len*sizeof(u32);
|
||||||
}
|
}
|
||||||
memcpy(dst, postfix.ptr, postfix.len*sizeof(u32));
|
memcpy(dst, postfix.ptr, postfix.len*sizeof(u32));
|
||||||
|
str.ptr[str.len] = 0;
|
||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,18 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
typedef struct str8
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue