152 lines
3.4 KiB
C++
152 lines
3.4 KiB
C++
// #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 <stdio.h> // vsnprintf
|
|
#include <cstdarg> // 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<u8>(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<u8>(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<u8>(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;
|
|
}
|
|
|