progress on strings (currently on basic text and escapes)

This commit is contained in:
ed
2025-02-06 19:51:39 -05:00
parent f0b8eaa232
commit 40a67c8da9
2 changed files with 611 additions and 313 deletions
+455 -282
View File
@@ -1,5 +1,7 @@
#ifdef INTELLISENSE_DIRECTIVES #ifdef INTELLISENSE_DIRECTIVES
# pragma once # pragma once
# include "macros.h"
# include "debug.h"
# include "strings.h" # include "strings.h"
# include "thread_context.h" # include "thread_context.h"
#endif #endif
@@ -1217,337 +1219,508 @@ utf16_encode(U16 *str, U32 codepoint) {
//////////////////////////////// ////////////////////////////////
//~ rjf: Unicode String Conversions //~ rjf: Unicode String Conversions
internal String8 String8
str8_from_16(Arena *arena, String16 in){ str8_from_16(Arena* arena, String16 in) {
U64 cap = in.size*3; U64 cap = in.size * 3;
U8 *str = push_array_no_zero(arena, U8, cap + 1); U8* str = push_array_no_zero(arena, U8, cap + 1);
U16 *ptr = in.str; U16* ptr = in.str;
U16 *opl = ptr + in.size; U16* opl = ptr + in.size;
U64 size = 0; U64 size = 0;
UnicodeDecode consume; UnicodeDecode consume;
for (;ptr < opl; ptr += consume.inc){ for (;ptr < opl; ptr += consume.inc) {
consume = utf16_decode(ptr, opl - ptr); consume = utf16_decode(ptr, opl - ptr);
size += utf8_encode(str + size, consume.codepoint); size += utf8_encode(str + size, consume.codepoint);
} }
str[size] = 0; str[size] = 0;
arena_pop(arena, (cap - size)); arena_pop(arena, (cap - size));
return(str8(str, size)); return(str8(str, size));
} }
internal String16 String16
str16_from_8(Arena *arena, String8 in){ str16_from_8(Arena* arena, String8 in) {
U64 cap = in.size*2; U64 cap = in.size * 2;
U16 *str = push_array_no_zero(arena, U16, cap + 1); U16* str = push_array_no_zero(arena, U16, cap + 1);
U8 *ptr = in.str; U8* ptr = in.str;
U8 *opl = ptr + in.size; U8* opl = ptr + in.size;
U64 size = 0; U64 size = 0;
UnicodeDecode consume; UnicodeDecode consume;
for (;ptr < opl; ptr += consume.inc){ for (;ptr < opl; ptr += consume.inc) {
consume = utf8_decode(ptr, opl - ptr); consume = utf8_decode(ptr, opl - ptr);
size += utf16_encode(str + size, consume.codepoint); size += utf16_encode(str + size, consume.codepoint);
} }
str[size] = 0; str[size] = 0;
arena_pop(arena, (cap - size)*2); arena_pop(arena, (cap - size)*2);
return(str16(str, size)); return(str16(str, size));
} }
internal String8 String8
str8_from_32(Arena *arena, String32 in){ str8_from_32(Arena *arena, String32 in){
U64 cap = in.size*4; U64 cap = in.size * 4;
U8 *str = push_array_no_zero(arena, U8, cap + 1); U8* str = push_array_no_zero(arena, U8, cap + 1);
U32 *ptr = in.str; U32* ptr = in.str;
U32 *opl = ptr + in.size; U32* opl = ptr + in.size;
U64 size = 0; U64 size = 0;
for (;ptr < opl; ptr += 1){ for (;ptr < opl; ptr += 1){
size += utf8_encode(str + size, *ptr); size += utf8_encode(str + size, *ptr);
} }
str[size] = 0; str[size] = 0;
arena_pop(arena, (cap - size)); arena_pop(arena, (cap - size));
return(str8(str, size)); return(str8(str, size));
} }
internal String32 String32
str32_from_8(Arena *arena, String8 in){ str32_from_8(Arena *arena, String8 in){
U64 cap = in.size; U64 cap = in.size;
U32 *str = push_array_no_zero(arena, U32, cap + 1); U32* str = push_array_no_zero(arena, U32, cap + 1);
U8 *ptr = in.str; U8* ptr = in.str;
U8 *opl = ptr + in.size; U8* opl = ptr + in.size;
U64 size = 0; U64 size = 0;
UnicodeDecode consume; UnicodeDecode consume;
for (;ptr < opl; ptr += consume.inc){ for (;ptr < opl; ptr += consume.inc){
consume = utf8_decode(ptr, opl - ptr); consume = utf8_decode(ptr, opl - ptr);
str[size] = consume.codepoint; str[size] = consume.codepoint;
size += 1; size += 1;
} }
str[size] = 0; str[size] = 0;
arena_pop(arena, (cap - size)*4); arena_pop(arena, (cap - size)*4);
return(str32(str, size)); 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 typedef struct OS_EnumMap OS_EnumMap;
string_from_dimension(Dimension dimension){ struct OS_EnumMap
local_persist String8 strings[] = { {
str8_lit_comp("X"), String8 string;
str8_lit_comp("Y"), OperatingSystem os;
str8_lit_comp("Z"), };
str8_lit_comp("W"),
};
String8 result = str8_lit("error");
if ((U32)dimension < 4){
result = strings[dimension];
}
return(result);
}
internal String8 read_only global OS_EnumMap g_os_enum_map[] =
string_from_side(Side side){ {
local_persist String8 strings[] = { { str8_lit_comp(""), OperatingSystem_Null },
str8_lit_comp("Min"), { str8_lit_comp("Windows"), OperatingSystem_Windows, },
str8_lit_comp("Max"), { str8_lit_comp("Linux"), OperatingSystem_Linux, },
}; { str8_lit_comp("Mac"), OperatingSystem_Mac, },
String8 result = str8_lit("error"); };
if ((U32)side < 2){ md_static_assert(array_count(g_os_enum_map) == OperatingSystem_COUNT, g_os_enum_map_count_check);
result = strings[side];
}
return(result);
}
internal String8 OperatingSystem
string_from_operating_system(OperatingSystem os){ operating_system_from_string(String8 string)
local_persist String8 strings[] = { {
str8_lit_comp("Null"), for (U64 i = 0; i < array_count(g_os_enum_map); ++i) {
str8_lit_comp("Windows"), if(str8_match(g_os_enum_map[i].string, string, StringMatchFlag_CaseInsensitive)) {
str8_lit_comp("Linux"), return g_os_enum_map[i].os;
str8_lit_comp("Mac"), }
}; }
String8 result = str8_lit("error"); return OperatingSystem_Null;
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);
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Time Types -> String //~ rjf: Time Types -> String
internal String8 String8
string_from_week_day(WeekDay week_day){ push_date_time_string(Arena* arena, DateTime* date_time) {
local_persist String8 strings[] = { char* mon_str = (char*)string_from_month(date_time->month).str;
str8_lit_comp("Sun"),
str8_lit_comp("Mon"), U32 adjusted_hour = date_time->hour % 12;
str8_lit_comp("Tue"), if (adjusted_hour == 0){
str8_lit_comp("Wed"), adjusted_hour = 12;
str8_lit_comp("Thu"), }
str8_lit_comp("Fri"),
str8_lit_comp("Sat"), char* ampm = "am";
}; if (date_time->hour >= 12){
String8 result = str8_lit("Err"); ampm = "pm";
if ((U32)week_day < WeekDay_COUNT){ }
result = strings[week_day];
} String8 result = push_str8f(arena,
return(result); "%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 String8
string_from_month(Month month){ push_file_name_date_time_string(Arena* arena, DateTime* date_time) {
local_persist String8 strings[] = { char* mon_str = (char*)string_from_month(date_time->month).str;
str8_lit_comp("Jan"),
str8_lit_comp("Feb"), String8 result = push_str8f(arena,
str8_lit_comp("Mar"), "%d-%s-%0d--%02d-%02d-%02d",
str8_lit_comp("Apr"), date_time->year, mon_str, date_time->day,
str8_lit_comp("May"), date_time->hour, date_time->min, date_time->sec
str8_lit_comp("Jun"), );
str8_lit_comp("Jul"), return(result);
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);
} }
internal String8 String8
push_date_time_string(Arena *arena, DateTime *date_time){ string_from_elapsed_time(Arena* arena, DateTime dt) {
char *mon_str = (char*)string_from_month(date_time->month).str; TempArena scratch = scratch_begin(&arena, 1);
U32 adjusted_hour = date_time->hour%12; String8List list = {0};
if (adjusted_hour == 0){ if (dt.year) {
adjusted_hour = 12; str8_list_pushf(scratch.arena, &list, "%dy", dt.year);
} str8_list_pushf(scratch.arena, &list, "%um", dt.mon);
char *ampm = "am"; str8_list_pushf(scratch.arena, &list, "%ud", dt.day);
if (date_time->hour >= 12){ } else if (dt.mon) {
ampm = "pm"; str8_list_pushf(scratch.arena, &list, "%um", dt.mon);
} str8_list_pushf(scratch.arena, &list, "%ud", dt.day);
String8 result = push_str8f(arena, "%d %s %d, %02d:%02d:%02d %s", } else if (dt.day) {
date_time->day, mon_str, date_time->year, str8_list_pushf(scratch.arena, &list, "%ud", dt.day);
adjusted_hour, date_time->min, date_time->sec, ampm); }
return(result); 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 String8
push_file_name_date_time_string(Arena *arena, DateTime *date_time){ push_date_time_string(AllocatorInfo ainfo, DateTime* date_time) {
char *mon_str = (char*)string_from_month(date_time->month).str; 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, U32 adjusted_hour = date_time->hour % 12;
date_time->hour, date_time->min, date_time->sec); if (adjusted_hour == 0){
return(result); 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 B32
escaped_from_raw_str8(Arena *arena, String8 string) try_guid_from_string(String8 string, Guid *guid_out)
{ {
TempArena scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(0,0);
String8List parts = {0}; B32 is_parsed = 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;
}
internal String8 String8List list = str8_split_by_string_chars(scratch.arena, string, str8_lit("-"), StringSplitFlag_KeepEmpties);
raw_from_escaped_str8(Arena *arena, String8 string) if(list.node_count == 5)
{ {
TempArena scratch = scratch_begin(&arena, 1); String8 data1_str = list.first->string;
String8List strs = {0}; String8 data2_str = list.first->next->string;
U64 start = 0; String8 data3_str = list.first->next->next->string;
for(U64 idx = 0; idx <= string.size; idx += 1) String8 data4_hi_str = list.first->next->next->next->string;
{ String8 data4_lo_str = list.first->next->next->next->next->string;
if(idx == string.size || string.str[idx] == '\\' || string.str[idx] == '\r') if( str8_is_integer(data1_str, 16) &&
{ str8_is_integer(data2_str, 16) &&
String8 str = str8_substr(string, r1u64(start, idx)); str8_is_integer(data3_str, 16) &&
if(str.size != 0) str8_is_integer(data4_hi_str, 16) &&
{ str8_is_integer(data4_lo_str, 16) )
str8_list_push(scratch.arena, &strs, str); {
} U64 data1 = u64_from_str8(data1_str, 16);
start = idx+1; U64 data2 = u64_from_str8(data2_str, 16);
} U64 data3 = u64_from_str8(data3_str, 16);
if(idx < string.size && string.str[idx] == '\\') U64 data4_hi = u64_from_str8(data4_hi_str, 16);
{ U64 data4_lo = u64_from_str8(data4_lo_str, 16);
U8 next_char = string.str[idx+1]; if( data1 <= MAX_U32 &&
U8 replace_byte = 0; data2 <= MAX_U16 &&
switch(next_char) data3 <= MAX_U16 &&
{ data4_hi <= MAX_U16 &&
default:{}break; data4_lo <= 0xffffffffffff )
case 'a': replace_byte = 0x07; break; {
case 'b': replace_byte = 0x08; break; guid_out->data1 = (U32)data1;
case 'e': replace_byte = 0x1b; break; guid_out->data2 = (U16)data2;
case 'f': replace_byte = 0x0c; break; guid_out->data3 = (U16)data3;
case 'n': replace_byte = 0x0a; break;
case 'r': replace_byte = 0x0d; break; U64 data4 = (data4_hi << 48) | data4_lo;
case 't': replace_byte = 0x09; break; memory_copy(&guid_out->data4[0], &data4, sizeof(data4));
case 'v': replace_byte = 0x0b; break; is_parsed = 1;
case '\\':replace_byte = '\\'; break; }
case '\'':replace_byte = '\''; break; }
case '"': replace_byte = '"'; break; }
case '?': replace_byte = '?'; break; scratch_end(scratch);
} return is_parsed;
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;
} }
//////////////////////////////// ////////////////////////////////
//~ rjf: Basic Text Indentation //~ rjf: Basic Text Indentation
internal String8 String8
indented_from_string(Arena *arena, String8 string) indented_from_string(Arena* arena, String8 string)
{ {
TempArena scratch = scratch_begin(&arena, 1); TempArena scratch = scratch_begin(&arena, 1);
read_only local_persist U8 indentation_bytes[] = " "; read_only local_persist U8 indentation_bytes[] = " ";
String8List indented_strings = {0}; String8List indented_strings = {0};
S64 depth = 0;
S64 next_depth = 0; S64 depth = 0;
S64 next_depth = 0;
U64 line_begin_off = 0; U64 line_begin_off = 0;
for(U64 off = 0; off <= string.size; off += 1) for(U64 off = 0; off <= string.size; off += 1)
{ {
U8 byte = off<string.size ? string.str[off] : 0; U8 byte = off<string.size ? string.str[off] : 0;
switch(byte) switch(byte)
{ {
default:{}break; default:{}break;
case '{':case '[':case '(':{next_depth += 1; next_depth = max(0, next_depth);}break; case '{':case '[':case '(':{next_depth += 1; next_depth = max(0, next_depth);}break;
case '}':case ']':case ')':{next_depth -= 1; next_depth = max(0, next_depth); depth = next_depth;}break; case '}':case ']':case ')':{next_depth -= 1; next_depth = max(0, next_depth); depth = next_depth;}break;
case '\n': case '\n':
case 0: case 0:
{ {
String8 line = str8_skip_chop_whitespace(str8_substr(string, r1u64(line_begin_off, off))); String8 line = str8_skip_chop_whitespace(str8_substr(string, r1u64(line_begin_off, off)));
if(line.size != 0) if(line.size != 0) {
{ str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth * 2, indentation_bytes, line);
str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth*2, indentation_bytes, line); }
} line_begin_off = off + 1;
line_begin_off = off+1; depth = next_depth;
depth = next_depth; }break;
}break; }
}
} }
String8 result = str8_list_join(arena, &indented_strings, 0); String8 result = str8_list_join(arena, &indented_strings, 0);
scratch_end(scratch); scratch_end(scratch);
return result; return result;
} }
String8
indented_from_string_alloc(AllocatorInfo ainfo, String8 string)
{
Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1));
TempArena scratch = scratch_begin(&arena, 1);
read_only local_persist U8 indentation_bytes[] = " ";
String8List indented_strings = {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<string.size ? string.str[off] : 0;
switch(byte)
{
default:{}break;
case '{':case '[':case '(':{next_depth += 1; next_depth = max(0, next_depth);}break;
case '}':case ']':case ')':{next_depth -= 1; next_depth = max(0, next_depth); depth = next_depth;}break;
case '\n':
case 0:
{
String8 line = str8_skip_chop_whitespace(str8_substr(string, r1u64(line_begin_off, off)));
if(line.size != 0) {
str8_list_pushf(scratch.arena, &indented_strings, "%.*s%S\n", (int)depth * 2, indentation_bytes, line);
}
line_begin_off = off + 1;
depth = next_depth;
}break;
}
}
String8 result = str8_list_join_alloc(ainfo, &indented_strings, 0);
scratch_end(scratch);
arena_release(arena);
return result;
}
////////////////////////////////
//~ rjf: Text Escaping
String8
escaped_from_raw_str8(Arena* arena, String8 string)
{
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;
}
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;
}
//////////////////////////////// ////////////////////////////////
//~ rjf: Text Wrapping //~ rjf: Text Wrapping
+156 -31
View File
@@ -531,10 +531,10 @@ String8List str8_split_by_string_chars_alloc (AllocatorInfo ainfo, String8
String8List str8_list_split_by_string_chars (Arena* arena, String8List list, String8 split_chars, StringSplitFlags flags); String8List str8_list_split_by_string_chars (Arena* arena, String8List list, String8 split_chars, StringSplitFlags flags);
String8List str8_list_split_by_string_chars_alloc(AllocatorInfo ainfo, String8List list, String8 split_chars, StringSplitFlags flags); String8List str8_list_split_by_string_chars_alloc(AllocatorInfo ainfo, String8List list, String8 split_chars, StringSplitFlags flags);
MD_API String8 str8_list_join (Arena* arena, String8List* list, StringJoin* optional_params); MD_API String8 str8_list_join (Arena* arena, String8List* list, StringJoin* optional_params);
MD_API String8 str8_list_join_alloc (AllocatorInfo ainfo, String8List* list, StringJoin* optional_params); MD_API String8 str8_list_join_alloc (AllocatorInfo ainfo, String8List* list, StringJoin* optional_params);
void str8_list_from_flags (Arena* arena, String8List* list, U32 flags, String8* flag_string_table, U32 flag_string_count); void str8_list_from_flags (Arena* arena, String8List* list, U32 flags, String8* flag_string_table, U32 flag_string_count);
void str8_list_from_flags_alloc(AllocatorInfo ainfo, String8List* list, U32 flags, String8* flag_string_table, U32 flag_string_count); void str8_list_from_flags_alloc(AllocatorInfo ainfo, String8List* list, U32 flags, String8* flag_string_table, U32 flag_string_count);
inline String8List inline String8List
str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags) { str8_split_by_string_chars(Arena *arena, String8 string, String8 split_chars, StringSplitFlags flags) {
@@ -694,74 +694,199 @@ inline U32 utf8_from_utf32_single(U8* buffer, U32 character){ return(utf8_encode
//////////////////////////////// ////////////////////////////////
//~ rjf: Unicode String Conversions //~ rjf: Unicode String Conversions
internal String8 str8_from_16(Arena* arena, String16 in); MD_API String8 str8_from_16(Arena* arena, String16 in);
internal String16 str16_from_8(Arena* arena, String8 in); MD_API String16 str16_from_8(Arena* arena, String8 in);
internal String8 str8_from_32(Arena* arena, String32 in); MD_API String8 str8_from_32(Arena* arena, String32 in);
internal String32 str32_from_8(Arena* arena, String8 in); MD_API String32 str32_from_8(Arena* arena, String8 in);
MD_API String8 str8_from_16_alloc(AllocatorInfo ainfo, String16 in);
MD_API String16 str16_from_8_alloc(AllocatorInfo ainfo, String8 in);
MD_API String8 str8_from_32_alloc(AllocatorInfo ainfo, String32 in);
MD_API String32 str32_from_8_alloc(AllocatorInfo ainfo, String8 in);
//////////////////////////////// ////////////////////////////////
//~ String -> Enum Conversions //~ String -> 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 //~ rjf: Basic Types & Space Enum -> String Conversions
internal String8 string_from_dimension(Dimension dimension); inline String8
internal String8 string_from_side(Side side); string_from_dimension(Dimension dimension) {
internal String8 string_from_operating_system(OperatingSystem os); local_persist String8 strings[] = {
internal String8 string_from_arch(Arch arch); 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 //~ rjf: Time Types -> String
internal String8 string_from_week_day (WeekDay week_day); inline String8
internal String8 string_from_month (Month month); string_from_week_day(WeekDay week_day) {
internal String8 push_date_time_string (Arena* arena, DateTime* date_time); local_persist String8 strings[] = {
internal String8 push_file_name_date_time_string(Arena* arena, DateTime* date_time); str8_lit_comp("Sun"),
internal String8 string_from_elapsed_time (Arena* arena, DateTime dt); 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 //~ Globally Unique Ids
internal String8 string_from_guid(Arena *arena, Guid guid); inline String8
internal B32 try_guid_from_string(String8 string, Guid *guid_out); string_from_guid(Arena* arena, Guid guid) {
internal Guid guid_from_string(String8 string); 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 //~ 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 //~ rjf: Text Escaping
internal String8 escaped_from_raw_str8(Arena *arena, String8 string); MD_API 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(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 //~ 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 //~ 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); internal Vec4F32 rgba_from_hex_string_4f32(String8 hex_string);
//////////////////////////////// ////////////////////////////////
//~ rjf: String Fuzzy Matching //~ rjf: String Fuzzy Matching
internal FuzzyMatchRangeList fuzzy_match_find (Arena *arena, String8 needle, String8 haystack); 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_range_list_copy(Arena* arena, FuzzyMatchRangeList* src);
//////////////////////////////// ////////////////////////////////
//~ NOTE(allen): Serialization Helpers //~ 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 void str8_serial_begin (Arena *arena, String8List *srl);
internal String8 str8_serial_end (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 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_size (Arena *arena, String8List *srl, U64 size);
internal void* str8_serial_push_data (Arena *arena, String8List *srl, void *data, 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_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_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_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_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_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_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))) #define str8_deserial_read_struct(string, off, ptr) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr)), sizeof( *(ptr)))