diff options
Diffstat (limited to 'src/str.c')
| -rw-r--r-- | src/str.c | 181 | 
1 files changed, 181 insertions, 0 deletions
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 <assert.h> +#include <stdarg.h> +#include <string.h> + +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); +}  | 
