// #TODO: Integrate Allocator / context.allocator // Need to sort out how formatted strings and string builders are allocated // Maybe just use context.allocator? // What about temp strings? use context.temp? struct string { s64 count; u8* data; // Construct from a string literal or C-string string () { // default constructor count = 0; data = nullptr; } string (char* cstr) { count = strlen(cstr); data = (u8*)cstr; } string (s64 _count, char* str) { count = _count; data = (u8*)str; } string (s64 _count, u8* str) { count = _count; data = str; } }; // ~ API ~ #TODO string copy_string (string str); bool strings_match(string first_string, string second_string); // Unicode stuff string wide_to_utf8 (u16* source, s32 length); // string string_view(string n_string, int start_index, int view_count); // string copy_string(char* c_string); // void free(string& n_string); bool is_valid(string n_string); bool is_c_string(string n_string); char* to_c_string(string n_string); string format_string(char* format, ...); string string_from_literal(char* literal); #include "General_Purpose_Allocator.h" #include // vsnprintf #include // va_list, ... bool is_c_string(string n_string) { return (n_string.data && n_string.data[n_string.count] == '\0'); } bool is_valid(string n_string) { return (n_string.data != nullptr && n_string.count > 0); } string copy_string (string str) { string new_str = {}; new_str.count = str.count; new_str.data = (u8*)internal_alloc(str.count); memcpy(new_str.data, str.data, str.count); return new_str; } string format_string (char* format, ...) { constexpr s64 BUFFER_SIZE = 4096; string str = {0}; str.data = NewArray(BUFFER_SIZE); va_list args; va_start(args, format); // Note that this *is* null-terminated for compatibility. str.count = (s64)vsnprintf((char*)str.data, (size_t)BUFFER_SIZE, format, args); va_end(args); return str; } string copy_string(char* c_string) { string str = {0}; s64 string_length = strlen(c_string); str.data = NewArray(string_length + 1); memcpy(str.data, c_string, string_length); str.count = string_length; return str; } bool strings_match(string first_string, string second_string) { if (first_string.count != second_string.count) { return false; } for (s64 i = 0; i < first_string.count; i += 1) { if (first_string.data[i] != second_string.data[i]) { return false; } } return true; } string string_from_literal(char* literal) { string new_string; new_string.count = strlen(literal); new_string.data = (u8*) literal; return new_string; } void free(string& n_string) { internal_free(n_string.data); n_string.data = nullptr; n_string.count = 0; } // Unicode nonsense string wide_to_utf8 (u16* source, s32 length) { if (length == 0) return { }; s32 query_result = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)source, length, nullptr, 0, nullptr, nullptr); if (query_result <= 0) return { }; // Make room for a null terminator: query_result += 1; u8* memory = NewArray(query_result); string utf8_string; utf8_string.count = query_result; utf8_string.data = memory; s32 result = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)source, length, (LPSTR)memory, query_result, nullptr, nullptr); if (result <= 0) { internal_free(memory); return { }; } return utf8_string; }