diff --git a/code/base/strings.c b/code/base/strings.c index 66a0b44..54000e3 100644 --- a/code/base/strings.c +++ b/code/base/strings.c @@ -1,5 +1,7 @@ #ifdef INTELLISENSE_DIRECTIVES # pragma once +# include "macros.h" +# include "debug.h" # include "strings.h" # include "thread_context.h" #endif @@ -1217,337 +1219,508 @@ utf16_encode(U16 *str, U32 codepoint) { //////////////////////////////// //~ rjf: Unicode String Conversions -internal String8 -str8_from_16(Arena *arena, String16 in){ - U64 cap = in.size*3; - U8 *str = push_array_no_zero(arena, U8, cap + 1); - U16 *ptr = in.str; - U16 *opl = ptr + in.size; - U64 size = 0; - UnicodeDecode consume; - for (;ptr < opl; ptr += consume.inc){ - consume = utf16_decode(ptr, opl - ptr); - size += utf8_encode(str + size, consume.codepoint); - } - str[size] = 0; - arena_pop(arena, (cap - size)); - return(str8(str, size)); +String8 +str8_from_16(Arena* arena, String16 in) { + U64 cap = in.size * 3; + U8* str = push_array_no_zero(arena, U8, cap + 1); + U16* ptr = in.str; + U16* opl = ptr + in.size; + U64 size = 0; + UnicodeDecode consume; + for (;ptr < opl; ptr += consume.inc) { + consume = utf16_decode(ptr, opl - ptr); + size += utf8_encode(str + size, consume.codepoint); + } + str[size] = 0; + arena_pop(arena, (cap - size)); + return(str8(str, size)); } -internal String16 -str16_from_8(Arena *arena, String8 in){ - U64 cap = in.size*2; - U16 *str = push_array_no_zero(arena, U16, cap + 1); - U8 *ptr = in.str; - U8 *opl = ptr + in.size; - U64 size = 0; - UnicodeDecode consume; - for (;ptr < opl; ptr += consume.inc){ - consume = utf8_decode(ptr, opl - ptr); - size += utf16_encode(str + size, consume.codepoint); - } - str[size] = 0; - arena_pop(arena, (cap - size)*2); - return(str16(str, size)); +String16 +str16_from_8(Arena* arena, String8 in) { + U64 cap = in.size * 2; + U16* str = push_array_no_zero(arena, U16, cap + 1); + U8* ptr = in.str; + U8* opl = ptr + in.size; + U64 size = 0; + UnicodeDecode consume; + for (;ptr < opl; ptr += consume.inc) { + consume = utf8_decode(ptr, opl - ptr); + size += utf16_encode(str + size, consume.codepoint); + } + str[size] = 0; + arena_pop(arena, (cap - size)*2); + return(str16(str, size)); } -internal String8 +String8 str8_from_32(Arena *arena, String32 in){ - U64 cap = in.size*4; - U8 *str = push_array_no_zero(arena, U8, cap + 1); - U32 *ptr = in.str; - U32 *opl = ptr + in.size; - U64 size = 0; - for (;ptr < opl; ptr += 1){ - size += utf8_encode(str + size, *ptr); - } - str[size] = 0; - arena_pop(arena, (cap - size)); - return(str8(str, size)); + U64 cap = in.size * 4; + U8* str = push_array_no_zero(arena, U8, cap + 1); + U32* ptr = in.str; + U32* opl = ptr + in.size; + U64 size = 0; + for (;ptr < opl; ptr += 1){ + size += utf8_encode(str + size, *ptr); + } + str[size] = 0; + arena_pop(arena, (cap - size)); + return(str8(str, size)); } -internal String32 +String32 str32_from_8(Arena *arena, String8 in){ - U64 cap = in.size; - U32 *str = push_array_no_zero(arena, U32, cap + 1); - U8 *ptr = in.str; - U8 *opl = ptr + in.size; - U64 size = 0; - UnicodeDecode consume; - for (;ptr < opl; ptr += consume.inc){ - consume = utf8_decode(ptr, opl - ptr); - str[size] = consume.codepoint; - size += 1; - } - str[size] = 0; - arena_pop(arena, (cap - size)*4); - return(str32(str, size)); + U64 cap = in.size; + U32* str = push_array_no_zero(arena, U32, cap + 1); + U8* ptr = in.str; + U8* opl = ptr + in.size; + U64 size = 0; + UnicodeDecode consume; + for (;ptr < opl; ptr += consume.inc){ + consume = utf8_decode(ptr, opl - ptr); + str[size] = consume.codepoint; + size += 1; + } + str[size] = 0; + arena_pop(arena, (cap - size)*4); + return(str32(str, size)); +} + +String8 +str8_from_16(AllocatorInfo ainfo, String16 in) { + U64 cap = in.size * 3; + U8* str = alloc_array_no_zero(ainfo, U8, cap + 1); + U16* ptr = in.str; + U16* opl = ptr + in.size; + U64 size = 0; + UnicodeDecode consume; + for (;ptr < opl; ptr += consume.inc) { + consume = utf16_decode(ptr, opl - ptr); + size += utf8_encode(str + size, consume.codepoint); + } + str[size] = 0; + resize(ainfo, str, (cap - size)); + return(str8(str, size)); +} + +String16 +str16_from_8(AllocatorInfo ainfo, String8 in) { + U64 cap = in.size * 2; + U16* str = alloc_array_no_zero(ainfo, U16, cap + 1); + U8* ptr = in.str; + U8* opl = ptr + in.size; + U64 size = 0; + UnicodeDecode consume; + for (;ptr < opl; ptr += consume.inc) { + consume = utf8_decode(ptr, opl - ptr); + size += utf16_encode(str + size, consume.codepoint); + } + str[size] = 0; + resize(ainfo, str, (cap - size)); + return(str16(str, size)); +} + +String8 +str8_from_32(AllocatorInfo ainfo, String32 in){ + U64 cap = in.size * 4; + U8* str = alloc_array_no_zero(ainfo, U8, cap + 1); + U32* ptr = in.str; + U32* opl = ptr + in.size; + U64 size = 0; + for (;ptr < opl; ptr += 1){ + size += utf8_encode(str + size, *ptr); + } + str[size] = 0; + resize(ainfo, str, (cap - size)); + return(str8(str, size)); +} + +String32 +str32_from_8(AllocatorInfo ainfo, String8 in){ + U64 cap = in.size; + U32* str = alloc_array_no_zero(ainfo, U32, cap + 1); + U8* ptr = in.str; + U8* opl = ptr + in.size; + U64 size = 0; + UnicodeDecode consume; + for (;ptr < opl; ptr += consume.inc){ + consume = utf8_decode(ptr, opl - ptr); + str[size] = consume.codepoint; + size += 1; + } + str[size] = 0; + resize(ainfo, str, (cap - size)); + return(str32(str, size)); } //////////////////////////////// -//~ rjf: Basic Types & Space Enum -> String Conversions +//~ String -> Enum Conversions -internal String8 -string_from_dimension(Dimension dimension){ - local_persist String8 strings[] = { - str8_lit_comp("X"), - str8_lit_comp("Y"), - str8_lit_comp("Z"), - str8_lit_comp("W"), - }; - String8 result = str8_lit("error"); - if ((U32)dimension < 4){ - result = strings[dimension]; - } - return(result); -} +typedef struct OS_EnumMap OS_EnumMap; +struct OS_EnumMap +{ + String8 string; + OperatingSystem os; +}; -internal String8 -string_from_side(Side side){ - local_persist String8 strings[] = { - str8_lit_comp("Min"), - str8_lit_comp("Max"), - }; - String8 result = str8_lit("error"); - if ((U32)side < 2){ - result = strings[side]; - } - return(result); -} +read_only global OS_EnumMap g_os_enum_map[] = +{ + { str8_lit_comp(""), OperatingSystem_Null }, + { str8_lit_comp("Windows"), OperatingSystem_Windows, }, + { str8_lit_comp("Linux"), OperatingSystem_Linux, }, + { str8_lit_comp("Mac"), OperatingSystem_Mac, }, +}; +md_static_assert(array_count(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check); -internal String8 -string_from_operating_system(OperatingSystem os){ - local_persist String8 strings[] = { - str8_lit_comp("Null"), - str8_lit_comp("Windows"), - str8_lit_comp("Linux"), - str8_lit_comp("Mac"), - }; - String8 result = str8_lit("error"); - if (os < OperatingSystem_COUNT){ - result = strings[os]; - } - return(result); -} - -internal String8 -string_from_architecture(Architecture arch){ - local_persist String8 strings[] = { - str8_lit_comp("Null"), - str8_lit_comp("x64"), - str8_lit_comp("x86"), - str8_lit_comp("arm64"), - str8_lit_comp("arm32"), - }; - String8 result = str8_lit("error"); - if (arch < Architecture_COUNT){ - result = strings[arch]; - } - return(result); +OperatingSystem +operating_system_from_string(String8 string) +{ + for (U64 i = 0; i < array_count(g_os_enum_map); ++i) { + if(str8_match(g_os_enum_map[i].string, string, StringMatchFlag_CaseInsensitive)) { + return g_os_enum_map[i].os; + } + } + return OperatingSystem_Null; } //////////////////////////////// //~ rjf: Time Types -> String -internal String8 -string_from_week_day(WeekDay week_day){ - local_persist String8 strings[] = { - str8_lit_comp("Sun"), - str8_lit_comp("Mon"), - str8_lit_comp("Tue"), - str8_lit_comp("Wed"), - str8_lit_comp("Thu"), - str8_lit_comp("Fri"), - str8_lit_comp("Sat"), - }; - String8 result = str8_lit("Err"); - if ((U32)week_day < WeekDay_COUNT){ - result = strings[week_day]; - } - return(result); +String8 +push_date_time_string(Arena* arena, DateTime* date_time) { + char* mon_str = (char*)string_from_month(date_time->month).str; + + U32 adjusted_hour = date_time->hour % 12; + if (adjusted_hour == 0){ + adjusted_hour = 12; + } + + char* ampm = "am"; + if (date_time->hour >= 12){ + ampm = "pm"; + } + + String8 result = push_str8f(arena, + "%d %s %d, %02d:%02d:%02d %s", + date_time->day, mon_str, date_time->year, + adjusted_hour, date_time->min, date_time->sec, ampm + ); + return(result); } -internal String8 -string_from_month(Month month){ - local_persist String8 strings[] = { - str8_lit_comp("Jan"), - str8_lit_comp("Feb"), - str8_lit_comp("Mar"), - str8_lit_comp("Apr"), - str8_lit_comp("May"), - str8_lit_comp("Jun"), - str8_lit_comp("Jul"), - str8_lit_comp("Aug"), - str8_lit_comp("Sep"), - str8_lit_comp("Oct"), - str8_lit_comp("Nov"), - str8_lit_comp("Dec"), - }; - String8 result = str8_lit("Err"); - if ((U32)month < Month_COUNT){ - result = strings[month]; - } - return(result); +String8 +push_file_name_date_time_string(Arena* arena, DateTime* date_time) { + char* mon_str = (char*)string_from_month(date_time->month).str; + + String8 result = push_str8f(arena, + "%d-%s-%0d--%02d-%02d-%02d", + date_time->year, mon_str, date_time->day, + date_time->hour, date_time->min, date_time->sec + ); + return(result); } -internal String8 -push_date_time_string(Arena *arena, DateTime *date_time){ - char *mon_str = (char*)string_from_month(date_time->month).str; - U32 adjusted_hour = date_time->hour%12; - if (adjusted_hour == 0){ - adjusted_hour = 12; - } - char *ampm = "am"; - if (date_time->hour >= 12){ - ampm = "pm"; - } - String8 result = push_str8f(arena, "%d %s %d, %02d:%02d:%02d %s", - date_time->day, mon_str, date_time->year, - adjusted_hour, date_time->min, date_time->sec, ampm); - return(result); +String8 +string_from_elapsed_time(Arena* arena, DateTime dt) { + TempArena scratch = scratch_begin(&arena, 1); + String8List list = {0}; + if (dt.year) { + str8_list_pushf(scratch.arena, &list, "%dy", dt.year); + str8_list_pushf(scratch.arena, &list, "%um", dt.mon); + str8_list_pushf(scratch.arena, &list, "%ud", dt.day); + } else if (dt.mon) { + str8_list_pushf(scratch.arena, &list, "%um", dt.mon); + str8_list_pushf(scratch.arena, &list, "%ud", dt.day); + } else if (dt.day) { + str8_list_pushf(scratch.arena, &list, "%ud", dt.day); + } + str8_list_pushf(scratch.arena, &list, "%u:%u:%u:%u ms", dt.hour, dt.min, dt.sec, dt.msec); + StringJoin join = { str8_lit_comp(""), str8_lit_comp(" "), str8_lit_comp("") }; + String8 result = str8_list_join(arena, &list, &join); + scratch_end(scratch); + return(result); } -internal String8 -push_file_name_date_time_string(Arena *arena, DateTime *date_time){ - char *mon_str = (char*)string_from_month(date_time->month).str; - String8 result = push_str8f(arena, "%d-%s-%0d--%02d-%02d-%02d", - date_time->year, mon_str, date_time->day, - date_time->hour, date_time->min, date_time->sec); - return(result); +String8 +push_date_time_string(AllocatorInfo ainfo, DateTime* date_time) { + char* mon_str = (char*)string_from_month(date_time->month).str; + + U32 adjusted_hour = date_time->hour % 12; + if (adjusted_hour == 0){ + adjusted_hour = 12; + } + + char* ampm = "am"; + if (date_time->hour >= 12){ + ampm = "pm"; + } + + String8 result = str8f(ainfo, + "%d %s %d, %02d:%02d:%02d %s", + date_time->day, mon_str, date_time->year, + adjusted_hour, date_time->min, date_time->sec, ampm + ); + return(result); +} + +String8 +push_file_name_date_time_string(AllocatorInfo ainfo, DateTime* date_time) { + char* mon_str = (char*)string_from_month(date_time->month).str; + + String8 result = str8f(ainfo, + "%d-%s-%0d--%02d-%02d-%02d", + date_time->year, mon_str, date_time->day, + date_time->hour, date_time->min, date_time->sec + ); + return(result); +} + +String8 +string_from_elapsed_time(AllocatorInfo ainfo, DateTime dt) { + U8 bytes[KB(8)]; + FArena arena = farena_from_memory(bytes, size_of(bytes)); + AllocatorInfo scratch = farena_allocator(arena); + + String8List list = {0}; + if (dt.year) { + str8_list_allocf(scratch, &list, "%dy", dt.year); + str8_list_allocf(scratch, &list, "%um", dt.mon); + str8_list_allocf(scratch, &list, "%ud", dt.day); + } else if (dt.mon) { + str8_list_allocf(scratch, &list, "%um", dt.mon); + str8_list_allocf(scratch, &list, "%ud", dt.day); + } else if (dt.day) { + str8_list_allocf(scratch, &list, "%ud", dt.day); + } + str8_list_allocf(scratch, &list, "%u:%u:%u:%u ms", dt.hour, dt.min, dt.sec, dt.msec); + + StringJoin join = { str8_lit_comp(""), str8_lit_comp(" "), str8_lit_comp("") }; + String8 result = str8_list_join_alloc(ainfo, &list, &join); + return(result); } //////////////////////////////// -//~ rjf: Text Escaping +//~ Globally UNique Ids -internal String8 -escaped_from_raw_str8(Arena *arena, String8 string) +B32 +try_guid_from_string(String8 string, Guid *guid_out) { - TempArena scratch = scratch_begin(&arena, 1); - String8List parts = {0}; - U64 start_split_idx = 0; - for(U64 idx = 0; idx <= string.size; idx += 1) - { - U8 byte = (idx < string.size) ? string.str[idx] : 0; - B32 split = 1; - String8 separator_replace = {0}; - switch(byte) - { - default:{split = 0;}break; - case 0: {}break; - case '\a': {separator_replace = str8_lit("\\a");}break; - case '\b': {separator_replace = str8_lit("\\b");}break; - case '\f': {separator_replace = str8_lit("\\f");}break; - case '\n': {separator_replace = str8_lit("\\n");}break; - case '\r': {separator_replace = str8_lit("\\r");}break; - case '\t': {separator_replace = str8_lit("\\t");}break; - case '\v': {separator_replace = str8_lit("\\v");}break; - case '\\': {separator_replace = str8_lit("\\\\");}break; - case '"': {separator_replace = str8_lit("\\\"");}break; - case '?': {separator_replace = str8_lit("\\?");}break; - } - if(split) - { - String8 substr = str8_substr(string, r1u64(start_split_idx, idx)); - start_split_idx = idx+1; - str8_list_push(scratch.arena, &parts, substr); - if(separator_replace.size != 0) - { - str8_list_push(scratch.arena, &parts, separator_replace); - } - } - } - StringJoin join = {0}; - String8 result = str8_list_join(arena, &parts, &join); - scratch_end(scratch); - return result; -} + TempArena scratch = scratch_begin(0,0); + B32 is_parsed = 0; -internal String8 -raw_from_escaped_str8(Arena *arena, String8 string) -{ - TempArena scratch = scratch_begin(&arena, 1); - String8List strs = {0}; - U64 start = 0; - for(U64 idx = 0; idx <= string.size; idx += 1) - { - if(idx == string.size || string.str[idx] == '\\' || string.str[idx] == '\r') - { - String8 str = str8_substr(string, r1u64(start, idx)); - if(str.size != 0) - { - str8_list_push(scratch.arena, &strs, str); - } - start = idx+1; - } - if(idx < string.size && string.str[idx] == '\\') - { - U8 next_char = string.str[idx+1]; - U8 replace_byte = 0; - switch(next_char) - { - default:{}break; - case 'a': replace_byte = 0x07; break; - case 'b': replace_byte = 0x08; break; - case 'e': replace_byte = 0x1b; break; - case 'f': replace_byte = 0x0c; break; - case 'n': replace_byte = 0x0a; break; - case 'r': replace_byte = 0x0d; break; - case 't': replace_byte = 0x09; break; - case 'v': replace_byte = 0x0b; break; - case '\\':replace_byte = '\\'; break; - case '\'':replace_byte = '\''; break; - case '"': replace_byte = '"'; break; - case '?': replace_byte = '?'; break; - } - String8 replace_string = push_str8_copy(scratch.arena, str8(&replace_byte, 1)); - str8_list_push(scratch.arena, &strs, replace_string); - idx += 1; - start += 1; - } - } - String8 result = str8_list_join(arena, &strs, 0); - scratch_end(scratch); - return result; + String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties); + if(list.node_count == 5) + { + String8 data1_str = list.first->string; + String8 data2_str = list.first->next->string; + String8 data3_str = list.first->next->next->string; + String8 data4_hi_str = list.first->next->next->next->string; + String8 data4_lo_str = list.first->next->next->next->next->string; + if( str8_is_integer(data1_str, 16) && + str8_is_integer(data2_str, 16) && + str8_is_integer(data3_str, 16) && + str8_is_integer(data4_hi_str, 16) && + str8_is_integer(data4_lo_str, 16) ) + { + U64 data1 = u64_from_str8(data1_str, 16); + U64 data2 = u64_from_str8(data2_str, 16); + U64 data3 = u64_from_str8(data3_str, 16); + U64 data4_hi = u64_from_str8(data4_hi_str, 16); + U64 data4_lo = u64_from_str8(data4_lo_str, 16); + if( data1 <= MAX_U32 && + data2 <= MAX_U16 && + data3 <= MAX_U16 && + data4_hi <= MAX_U16 && + data4_lo <= 0xffffffffffff ) + { + guid_out->data1 = (U32)data1; + guid_out->data2 = (U16)data2; + guid_out->data3 = (U16)data3; + + U64 data4 = (data4_hi << 48) | data4_lo; + memory_copy(&guid_out->data4[0], &data4, sizeof(data4)); + is_parsed = 1; + } + } + } + scratch_end(scratch); + return is_parsed; } //////////////////////////////// //~ rjf: Basic Text Indentation -internal String8 -indented_from_string(Arena *arena, String8 string) +String8 +indented_from_string(Arena* arena, String8 string) { TempArena scratch = scratch_begin(&arena, 1); + read_only local_persist U8 indentation_bytes[] = " "; String8List indented_strings = {0}; - S64 depth = 0; - S64 next_depth = 0; + + S64 depth = 0; + S64 next_depth = 0; U64 line_begin_off = 0; for(U64 off = 0; off <= string.size; off += 1) { - U8 byte = off Enum Conversions -internal OperatingSystem operating_system_from_string(String8 string); +MD_API OperatingSystem operating_system_from_string(String8 string); //////////////////////////////// //~ rjf: Basic Types & Space Enum -> String Conversions -internal String8 string_from_dimension(Dimension dimension); -internal String8 string_from_side(Side side); -internal String8 string_from_operating_system(OperatingSystem os); -internal String8 string_from_arch(Arch arch); +inline String8 +string_from_dimension(Dimension dimension) { + local_persist String8 strings[] = { + str8_lit_comp("X"), + str8_lit_comp("Y"), + str8_lit_comp("Z"), + str8_lit_comp("W"), + }; + String8 result = str8_lit("error"); + if ((U32)dimension < 4) { + result = strings[dimension]; + } + return(result); +} + +inline String8 +string_from_side(Side side) { + local_persist String8 strings[] = { + str8_lit_comp("Min"), + str8_lit_comp("Max"), + }; + String8 result = str8_lit("error"); + if ((U32)side < 2) { + result = strings[side]; + } + return(result); +} + +inline String8 +string_from_operating_system(OperatingSystem os) { + local_persist String8 strings[] = { + str8_lit_comp("Null"), + str8_lit_comp("Windows"), + str8_lit_comp("Linux"), + str8_lit_comp("Mac"), + }; + String8 result = str8_lit("error"); + if (os < OperatingSystem_COUNT) { + result = strings[os]; + } + return(result); +} + +inline String8 +string_from_architecture(Arch arch) { + local_persist String8 strings[] = { + str8_lit_comp("Null"), + str8_lit_comp("x64"), + str8_lit_comp("x86"), + str8_lit_comp("arm64"), + str8_lit_comp("arm32"), + }; + String8 result = str8_lit("error"); + if (arch < Arch_COUNT) { + result = strings[arch]; + } + return(result); +} //////////////////////////////// //~ rjf: Time Types -> String -internal String8 string_from_week_day (WeekDay week_day); -internal String8 string_from_month (Month month); -internal String8 push_date_time_string (Arena* arena, DateTime* date_time); -internal String8 push_file_name_date_time_string(Arena* arena, DateTime* date_time); -internal String8 string_from_elapsed_time (Arena* arena, DateTime dt); +inline String8 +string_from_week_day(WeekDay week_day) { + local_persist String8 strings[] = { + str8_lit_comp("Sun"), + str8_lit_comp("Mon"), + str8_lit_comp("Tue"), + str8_lit_comp("Wed"), + str8_lit_comp("Thu"), + str8_lit_comp("Fri"), + str8_lit_comp("Sat"), + }; + String8 result = str8_lit("Err"); + if ((U32)week_day < WeekDay_COUNT) { + result = strings[week_day]; + } + return(result); +} + +inline String8 +string_from_month(Month month) { + local_persist String8 strings[] = { + str8_lit_comp("Jan"), + str8_lit_comp("Feb"), + str8_lit_comp("Mar"), + str8_lit_comp("Apr"), + str8_lit_comp("May"), + str8_lit_comp("Jun"), + str8_lit_comp("Jul"), + str8_lit_comp("Aug"), + str8_lit_comp("Sep"), + str8_lit_comp("Oct"), + str8_lit_comp("Nov"), + str8_lit_comp("Dec"), + }; + String8 result = str8_lit("Err"); + if ((U32)month < Month_COUNT) { + result = strings[month]; + } + return(result); +} + +MD_API String8 push_date_time_string (Arena* arena, DateTime* date_time); +MD_API String8 push_file_name_date_time_string(Arena* arena, DateTime* date_time); +MD_API String8 string_from_elapsed_time (Arena* arena, DateTime date_time); + +MD_API String8 alloc_date_time_string (AllocatorInfo ainfo, DateTime* date_time); +MD_API String8 alloc_file_name_date_time_string(AllocatorInfo ainfo, DateTime* date_time); +MD_API String8 string_from_elapsed_time_alloc (AllocatorInfo ainfo, DateTime date_time); //////////////////////////////// //~ Globally Unique Ids -internal String8 string_from_guid(Arena *arena, Guid guid); -internal B32 try_guid_from_string(String8 string, Guid *guid_out); -internal Guid guid_from_string(String8 string); +inline String8 +string_from_guid(Arena* arena, Guid guid) { + String8 result = push_str8f(arena, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + guid.data1, + guid.data2, + guid.data3, + guid.data4[0], + guid.data4[1], + guid.data4[2], + guid.data4[3], + guid.data4[4], + guid.data4[5], + guid.data4[6], + guid.data4[7] + ); + return result; +} + +inline Guid guid_from_string(String8 string) { Guid guid = {0}; try_guid_from_string(string, &guid); return guid; } + +MD_API B32 try_guid_from_string(String8 string, Guid* guid_out); //////////////////////////////// //~ rjf: Basic Text Indentation -internal String8 indented_from_string(Arena *arena, String8 string); +MD_API String8 indented_from_string(Arena* arena, String8 string); +MD_API String8 indented_from_string(AllocatorInfo arena, String8 string); //////////////////////////////// //~ rjf: Text Escaping -internal String8 escaped_from_raw_str8(Arena *arena, String8 string); -internal String8 raw_from_escaped_str8(Arena *arena, String8 string); +MD_API String8 escaped_from_raw_str8(Arena* arena, String8 string); +MD_API String8 escaped_from_raw_str8(AllocatorInfo ainfo, String8 string); +MD_API String8 raw_from_escaped_str8(Arena* arena, String8 string); +MD_API String8 raw_from_escaped_str8(AllocatorInfo ainfo, String8 string); //////////////////////////////// //~ rjf: Text Wrapping -String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent); +String8List wrapped_lines_from_string(Arena* arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent); //////////////////////////////// //~ rjf: String <-> Color -internal String8 hex_string_from_rgba_4f32(Arena *arena, Vec4F32 rgba); +internal String8 hex_string_from_rgba_4f32(Arena* arena, Vec4F32 rgba); internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string); //////////////////////////////// //~ rjf: String Fuzzy Matching -internal FuzzyMatchRangeList fuzzy_match_find (Arena *arena, String8 needle, String8 haystack); -internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena *arena, FuzzyMatchRangeList *src); +internal FuzzyMatchRangeList fuzzy_match_find (Arena* arena, String8 needle, String8 haystack); +internal FuzzyMatchRangeList fuzzy_match_range_list_copy(Arena* arena, FuzzyMatchRangeList* src); //////////////////////////////// //~ NOTE(allen): Serialization Helpers +internal void str8_serial_write_to_dst (String8List *srl, void *out); + internal void str8_serial_begin (Arena *arena, String8List *srl); internal String8 str8_serial_end (Arena *arena, String8List *srl); -internal void str8_serial_write_to_dst (String8List *srl, void *out); internal U64 str8_serial_push_align (Arena *arena, String8List *srl, U64 align); internal void* str8_serial_push_size (Arena *arena, String8List *srl, U64 size); internal void* str8_serial_push_data (Arena *arena, String8List *srl, void *data, U64 size); @@ -785,8 +910,8 @@ internal void* str8_deserial_get_raw_ptr (String8 string, U64 off internal U64 str8_deserial_read_cstr (String8 string, U64 off, String8* cstr_out); internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16* str_out); internal U64 str8_deserial_read_block (String8 string, U64 off, U64 size, String8* block_out); -internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out); -internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out); +internal U64 str8_deserial_read_uleb128 (String8 string, U64 off, U64* value_out); +internal U64 str8_deserial_read_sleb128 (String8 string, U64 off, S64* value_out); #define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)) * (count), sizeof( *(ptr))) #define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof( *(ptr)))