From b71eac2069a30349435c192d682e865718c86a15 Mon Sep 17 00:00:00 2001 From: Clement Sibille Date: Mon, 5 May 2025 08:32:33 +0200 Subject: Add a vulkan renderer that renders an OBJ --- src/str.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/str.c (limited to 'src/str.c') diff --git a/src/str.c b/src/str.c new file mode 100644 index 0000000..9c68d43 --- /dev/null +++ b/src/str.c @@ -0,0 +1,181 @@ +#include "str.h" +#include "alloc.h" +#include "hash.h" +#include "platform.h" +#include +#include +#include + +struct vgltf_string_view vgltf_string_view_from_literal(const char *str) { + assert(str); + size_t length = strlen(str); + return (struct vgltf_string_view){.length = length, .data = str}; +} +struct vgltf_string_view vgltf_string_view_from_string(struct vgltf_string string) { + return (struct vgltf_string_view){.length = string.length, .data = string.data}; +} +char vgltf_string_view_at(const struct vgltf_string_view *string_view, + size_t index) { + assert(string_view); + assert(index < string_view->length); + return string_view->data[index]; +} +bool vgltf_string_view_eq(struct vgltf_string_view view, + struct vgltf_string_view other) { + return view.length == other.length && + (strncmp(view.data, other.data, view.length) == 0); +} +size_t vgltf_string_view_length(const struct vgltf_string_view *string_view) { + assert(string_view); + return string_view->length; +} + +uint64_t vgltf_string_view_hash(const struct vgltf_string_view view) { + return vgltf_hash_fnv_1a(view.data, view.length); +} + +int vgltf_string_view_utf8_codepoint_at_offset(struct vgltf_string_view view, + size_t offset, + uint32_t *codepoint) { + assert(codepoint); + assert(offset < view.length); + + const unsigned char *s = (unsigned char *)&view.data[offset]; + + int size; + if ((*s & 0x80) == 0) { + *codepoint = *s; + size = 1; + } else if ((*s & 0xE0) == 0xC0) { + *codepoint = *s & 0x1f; + size = 2; + } else if ((*s & 0xF0) == 0xE0) { + *codepoint = *s & 0x0f; + size = 3; + } else if ((*s & 0xF8) == 0xF0) { + *codepoint = *s & 0x07; + size = 4; + } else { + VGLTF_LOG_ERR("Invalid UTF-8 sequence"); + return 0; + } + + for (int i = 1; i < size; i++) { + if ((s[i] & 0xC0) != 0x80) { + VGLTF_LOG_ERR("Invalid UTF-8 continuation byte"); + return 0; + } + + *codepoint = (*codepoint << 6) | (s[i] & 0x3F); + } + + return size; +} +int vgltf_string_utf8_encode_codepoint(uint32_t codepoint, + char encoded_codepoint[4]) { + assert(encoded_codepoint); + if (codepoint > 0x10FFFF) { + return -1; + } + + if (codepoint <= 0x7F) { + encoded_codepoint[0] = (uint8_t)codepoint; + return 1; + } else if (codepoint <= 0x7FF) { + encoded_codepoint[0] = 0xC0 | ((codepoint >> 6) & 0x1F); + encoded_codepoint[1] = 0x80 | (codepoint & 0x3F); + return 2; + } else if (codepoint <= 0xFFFF) { + encoded_codepoint[0] = 0xE0 | ((codepoint >> 12) & 0x0F); + encoded_codepoint[1] = 0x80 | ((codepoint >> 6) & 0x3F); + encoded_codepoint[2] = 0x80 | (codepoint & 0x3F); + return 3; + } else { + encoded_codepoint[0] = 0xF0 | ((codepoint >> 18) & 0x07); + encoded_codepoint[1] = 0x80 | ((codepoint >> 12) & 0x3F); + encoded_codepoint[2] = 0x80 | ((codepoint >> 6) & 0x3F); + encoded_codepoint[3] = 0x80 | (codepoint & 0x3F); + return 4; + } +} + +struct vgltf_string +vgltf_string_from_null_terminated(struct vgltf_allocator *allocator, + const char *str) { + assert(allocator); + assert(str); + struct vgltf_string string; + size_t length = strlen(str); + char *data = vgltf_allocator_allocate(allocator, length + 1); + if (!data) { + VGLTF_PANIC("Couldn't allocate string"); + } + strncpy(data, str, length); + string.length = length; + string.data = data; + return string; +} +struct vgltf_string vgltf_string_clone(struct vgltf_allocator *allocator, + const struct vgltf_string string) { + assert(allocator); + + size_t length = string.length; + char *data = vgltf_allocator_allocate(allocator, length + 1); + memcpy(data, string.data, length); + data[length] = '\0'; + + return (struct vgltf_string){.data = data, .length = length}; +} +struct vgltf_string vgltf_string_concatenate(struct vgltf_allocator *allocator, + struct vgltf_string_view head, + struct vgltf_string_view tail) { + assert(allocator); + size_t length = head.length + tail.length; + char *data = vgltf_allocator_allocate(allocator, length + 1); + memcpy(data, head.data, head.length); + memcpy(data + head.length, tail.data, tail.length); + data[length] = '\0'; + return (struct vgltf_string){.data = data, .length = length}; +} +struct vgltf_string vgltf_string_formatted(struct vgltf_allocator *allocator, + struct vgltf_string_view fmt, ...) { + va_list args; + va_start(args, fmt); + struct vgltf_string formatted_string = + vgltf_string_vformatted(allocator, fmt, args); + va_end(args); + + return formatted_string; +} +struct vgltf_string vgltf_string_vformatted(struct vgltf_allocator *allocator, + struct vgltf_string_view fmt, + va_list args) { + assert(allocator); + char str[1024]; + size_t length = vsnprintf(str, 1024, fmt.data, args); + char *data = vgltf_allocator_allocate(allocator, length + 1); + memcpy(data, str, length); + data[length] = '\0'; + return (struct vgltf_string){.data = data, .length = length}; +} +void vgltf_string_deinit(struct vgltf_allocator *allocator, + struct vgltf_string *string) { + assert(allocator); + assert(string); + vgltf_allocator_free(allocator, string->data); +} +size_t vgltf_string_length(const struct vgltf_string *string) { + return string->length; +} +bool vgltf_string_eq_view(const struct vgltf_string string, + const struct vgltf_string_view view) { + return string.length == view.length && + (strncmp(string.data, view.data, string.length) == 0); +} +uint64_t vgltf_string_hash(const struct vgltf_string string) { + return vgltf_hash_fnv_1a(string.data, string.length); +} +bool vgltf_string_eq(struct vgltf_string string, struct vgltf_string other) { + return string.length == other.length && + (strncmp(string.data, other.data, string.length) == 0); +} -- cgit v1.2.3