136 lines
4.5 KiB
C
136 lines
4.5 KiB
C
#ifndef GUF_STR_H
|
|
#define GUF_STR_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "guf_common.h"
|
|
#include "guf_obj.h"
|
|
|
|
#define GUF_STR_ABORT_ON_ALLOC_FAILURE 1
|
|
|
|
// TODO: don't allocate self but take allocator?
|
|
|
|
typedef enum guf_str_state {
|
|
GUF_STR_STATE_INIT = 0,
|
|
GUF_STR_STATE_SHORT = 1,
|
|
GUF_STR_STATE_ALLOC_ERR = 2
|
|
} guf_str_state;
|
|
|
|
typedef struct guf_str {
|
|
guf_str_state state;
|
|
union {
|
|
struct heap {
|
|
char *c_str;
|
|
size_t len, capacity; // len and capacity do not include the null-terminator.
|
|
} heap;
|
|
struct stack { // Short-string optimisation.
|
|
#define GUF_STR_SSO_BUFSIZE (sizeof(struct heap) - sizeof(unsigned char))
|
|
#define GUF_STR_SSO_BUFCAP (GUF_STR_SSO_BUFSIZE - 1)
|
|
char c_str[GUF_STR_SSO_BUFSIZE];
|
|
unsigned char len;
|
|
} stack;
|
|
} data;
|
|
|
|
} guf_str;
|
|
|
|
typedef struct guf_str_view {
|
|
const char *str;
|
|
size_t len;
|
|
} guf_str_view;
|
|
|
|
#define GUF_CSTR_TO_VIEW(C_STR_PTR) ((guf_str_view){.str = (C_STR_PTR), .len = strlen((C_STR_PTR))})
|
|
#define GUF_STR_TO_VIEW(GUF_STR_PTR) ((guf_str_view){.str = guf_str_const_cstr((GUF_STR_PTR)), .len = guf_str_len((GUF_STR_PTR))})
|
|
|
|
extern const guf_str GUF_STR_UNINITIALISED;
|
|
extern const guf_str GUF_STR_UNINITIALISED_FAILED_ALLOC;
|
|
|
|
// TODO: find_first_of and tokenise -> for parsing, see aoclib.
|
|
|
|
// Creation:
|
|
guf_str *guf_str_init(guf_str *str, guf_str_view str_view);
|
|
guf_str *guf_str_init_from_cstr(guf_str *str, const char* c_str);
|
|
guf_str *guf_str_init_empty_with_capacity(guf_str *str, size_t capacity);
|
|
// guf_str_new functions return GUF_DICT_UNINITIALISED or GUF_STR_UNINITIALISED_FAILED_ALLOC on failure (can be checked with guf_str_alloc_success)
|
|
guf_str guf_str_new(guf_str_view str_view);
|
|
guf_str guf_str_new_from_cstr(const char *c_str);
|
|
guf_str guf_str_new_empty_with_capacity(size_t capacity);
|
|
|
|
// Destruction:
|
|
void guf_str_free(guf_str *str);
|
|
|
|
// Modification:
|
|
guf_str *guf_str_append(guf_str *str, guf_str_view to_append);
|
|
guf_str *guf_str_append_cstr(guf_str *str, const char *cstr_to_append);
|
|
guf_str *guf_str_substr(guf_str* str, size_t pos, size_t count);
|
|
|
|
guf_str *guf_str_reserve(guf_str *str, size_t bufsize);
|
|
guf_str *guf_str_shrink_capacity(guf_str *str, size_t shrink_trigger_fac, bool shrink_exact);
|
|
|
|
char guf_str_pop_back(guf_str *str);
|
|
char guf_str_pop_front(guf_str *str);
|
|
|
|
// Copying and viewing:
|
|
guf_str guf_str_substr_cpy(guf_str_view str, size_t pos, size_t count);
|
|
guf_str_view guf_str_substr_view(guf_str_view str, size_t pos, size_t count);
|
|
|
|
// Indexing:
|
|
char *guf_str_at(guf_str *str, size_t idx);
|
|
char *guf_str_back(guf_str *str);
|
|
char *guf_str_front(guf_str *str);
|
|
const char *guf_str_const_cstr(const guf_str *str);
|
|
|
|
// Metadata retrieval:
|
|
size_t guf_str_len(const guf_str *str); // The size (in chars) without the final zero-terminator (size - 1).
|
|
size_t guf_str_capacity(const guf_str *str);
|
|
bool guf_str_is_stack_allocated(const guf_str *str);
|
|
bool guf_str_is_valid(const guf_str *str);
|
|
bool guf_str_alloc_success(const guf_str *str);
|
|
|
|
// Comparison:
|
|
bool guf_str_view_equal(guf_str_view a, guf_str_view b);
|
|
bool guf_str_equal(const guf_str *a, const guf_str *b);
|
|
bool guf_str_equals_cstr(const guf_str *a, const char *c_str);
|
|
bool guf_str_equals_strview(const guf_str *a, guf_str_view b);
|
|
int guf_str_view_cmp(const void *str_view_a, const void *str_view_b); // For qsort etc.
|
|
|
|
// UTF-8 operations.
|
|
bool guf_str_char_is_ascii(char c);
|
|
bool guf_str_is_ascii(const guf_str *str);
|
|
|
|
// TODO:
|
|
// typedef struct guf_str_pool_elem {
|
|
// guf_str str;
|
|
// bool in_use;
|
|
// struct guf_str_pool_elem *next_free;
|
|
// } guf_str_pool_elem;
|
|
|
|
// typedef struct guf_str_pool {
|
|
// guf_str_pool_elem *elems;
|
|
// size_t capacity, num_in_use;
|
|
// size_t min_str_bufsize;
|
|
// guf_str_pool_elem *first_free;
|
|
// } guf_str_pool;
|
|
|
|
// void guf_str_pool_init(guf_str_pool *pool, size_t capacity, size_t str_initial_size)
|
|
// {
|
|
// if (capacity < 1) {
|
|
// capacity = 1;
|
|
// }
|
|
// pool->num_in_use = 0;
|
|
// pool->capacity = capacity;
|
|
// pool->elems = calloc(capacity, sizeof(guf_str_pool_elem));
|
|
// pool->min_str_bufsize = str_initial_size;
|
|
// GUF_ASSERT_RELEASE(pool->elems);
|
|
|
|
// pool->first_free = pool->elems + 0;
|
|
// for (size_t i = 0; i < pool->capacity; ++i) {
|
|
// pool->elems[i].in_use = false;
|
|
// pool->elems[i].str = guf_str_new_empty_with_capacity(pool->min_str_bufsize);
|
|
// pool->elems[i].next_free = i + 1 < pool->capacity ? pool->elems + i + 1 : NULL;
|
|
// }
|
|
// }
|
|
|
|
// find_free and find_free_with_cap
|
|
|
|
#endif |