Blame src-nuklear/nuklear_string.c

b53a5c
#include "nuklear.h"
b53a5c
#include "nuklear_internal.h"
b53a5c
b53a5c
/* ===============================================================
b53a5c
 *
b53a5c
 *                              STRING
b53a5c
 *
b53a5c
 * ===============================================================*/
b53a5c
#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
b53a5c
NK_API void
b53a5c
nk_str_init_default(struct nk_str *str)
b53a5c
{
b53a5c
    struct nk_allocator alloc;
b53a5c
    alloc.userdata.ptr = 0;
b53a5c
    alloc.alloc = nk_malloc;
b53a5c
    alloc.free = nk_mfree;
b53a5c
    nk_buffer_init(&str->buffer, &alloc, 32);
b53a5c
    str->len = 0;
b53a5c
}
b53a5c
#endif
b53a5c
b53a5c
NK_API void
b53a5c
nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
b53a5c
{
b53a5c
    nk_buffer_init(&str->buffer, alloc, size);
b53a5c
    str->len = 0;
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
b53a5c
{
b53a5c
    nk_buffer_init_fixed(&str->buffer, memory, size);
b53a5c
    str->len = 0;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_append_text_char(struct nk_str *s, const char *str, int len)
b53a5c
{
b53a5c
    char *mem;
b53a5c
    NK_ASSERT(s);
b53a5c
    NK_ASSERT(str);
b53a5c
    if (!s || !str || !len) return 0;
b53a5c
    mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
b53a5c
    if (!mem) return 0;
b53a5c
    NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
b53a5c
    s->len += nk_utf_len(str, len);
b53a5c
    return len;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_append_str_char(struct nk_str *s, const char *str)
b53a5c
{
b53a5c
    return nk_str_append_text_char(s, str, nk_strlen(str));
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    int byte_len = 0;
b53a5c
    nk_rune unicode;
b53a5c
    if (!str || !text || !len) return 0;
b53a5c
    for (i = 0; i < len; ++i)
b53a5c
        byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
b53a5c
    nk_str_append_text_char(str, text, byte_len);
b53a5c
    return len;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_append_str_utf8(struct nk_str *str, const char *text)
b53a5c
{
b53a5c
    int byte_len = 0;
b53a5c
    int num_runes = 0;
b53a5c
    int glyph_len = 0;
b53a5c
    nk_rune unicode;
b53a5c
    if (!str || !text) return 0;
b53a5c
b53a5c
    glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
b53a5c
    while (unicode != '\0' && glyph_len) {
b53a5c
        glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
b53a5c
        byte_len += glyph_len;
b53a5c
        num_runes++;
b53a5c
    }
b53a5c
    nk_str_append_text_char(str, text, byte_len);
b53a5c
    return num_runes;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    int byte_len = 0;
b53a5c
    nk_glyph glyph;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    if (!str || !text || !len) return 0;
b53a5c
    for (i = 0; i < len; ++i) {
b53a5c
        byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
b53a5c
        if (!byte_len) break;
b53a5c
        nk_str_append_text_char(str, glyph, byte_len);
b53a5c
    }
b53a5c
    return len;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    nk_glyph glyph;
b53a5c
    int byte_len;
b53a5c
    NK_ASSERT(str);
b53a5c
    if (!str || !runes) return 0;
b53a5c
    while (runes[i] != '\0') {
b53a5c
        byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
b53a5c
        nk_str_append_text_char(str, glyph, byte_len);
b53a5c
        i++;
b53a5c
    }
b53a5c
    return i;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
b53a5c
{
b53a5c
    int i;
b53a5c
    void *mem;
b53a5c
    char *src;
b53a5c
    char *dst;
b53a5c
b53a5c
    int copylen;
b53a5c
    NK_ASSERT(s);
b53a5c
    NK_ASSERT(str);
b53a5c
    NK_ASSERT(len >= 0);
b53a5c
    if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
b53a5c
    if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
b53a5c
        (s->buffer.type == NK_BUFFER_FIXED)) return 0;
b53a5c
b53a5c
    copylen = (int)s->buffer.allocated - pos;
b53a5c
    if (!copylen) {
b53a5c
        nk_str_append_text_char(s, str, len);
b53a5c
        return 1;
b53a5c
    }
b53a5c
    mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
b53a5c
    if (!mem) return 0;
b53a5c
b53a5c
    /* memmove */
b53a5c
    NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
b53a5c
    NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
b53a5c
    dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
b53a5c
    src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
b53a5c
    for (i = 0; i < copylen; ++i) *dst-- = *src--;
b53a5c
    mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
b53a5c
    NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
b53a5c
    s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
b53a5c
    return 1;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
b53a5c
{
b53a5c
    int glyph_len;
b53a5c
    nk_rune unicode;
b53a5c
    const char *begin;
b53a5c
    const char *buffer;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    NK_ASSERT(cstr);
b53a5c
    NK_ASSERT(len);
b53a5c
    if (!str || !cstr || !len) return 0;
b53a5c
    begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
b53a5c
    if (!str->len)
b53a5c
        return nk_str_append_text_char(str, cstr, len);
b53a5c
    buffer = nk_str_get_const(str);
b53a5c
    if (!begin) return 0;
b53a5c
    return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
b53a5c
{
b53a5c
    return nk_str_insert_text_utf8(str, pos, text, len);
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
b53a5c
{
b53a5c
    return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    int byte_len = 0;
b53a5c
    nk_rune unicode;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    NK_ASSERT(text);
b53a5c
    if (!str || !text || !len) return 0;
b53a5c
    for (i = 0; i < len; ++i)
b53a5c
        byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
b53a5c
    nk_str_insert_at_rune(str, pos, text, byte_len);
b53a5c
    return len;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
b53a5c
{
b53a5c
    int byte_len = 0;
b53a5c
    int num_runes = 0;
b53a5c
    int glyph_len = 0;
b53a5c
    nk_rune unicode;
b53a5c
    if (!str || !text) return 0;
b53a5c
b53a5c
    glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
b53a5c
    while (unicode != '\0' && glyph_len) {
b53a5c
        glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
b53a5c
        byte_len += glyph_len;
b53a5c
        num_runes++;
b53a5c
    }
b53a5c
    nk_str_insert_at_rune(str, pos, text, byte_len);
b53a5c
    return num_runes;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    int byte_len = 0;
b53a5c
    nk_glyph glyph;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    if (!str || !runes || !len) return 0;
b53a5c
    for (i = 0; i < len; ++i) {
b53a5c
        byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
b53a5c
        if (!byte_len) break;
b53a5c
        nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
b53a5c
    }
b53a5c
    return len;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    nk_glyph glyph;
b53a5c
    int byte_len;
b53a5c
    NK_ASSERT(str);
b53a5c
    if (!str || !runes) return 0;
b53a5c
    while (runes[i] != '\0') {
b53a5c
        byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
b53a5c
        nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
b53a5c
        i++;
b53a5c
    }
b53a5c
    return i;
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_remove_chars(struct nk_str *s, int len)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    NK_ASSERT(len >= 0);
b53a5c
    if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
b53a5c
    NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
b53a5c
    s->buffer.allocated -= (nk_size)len;
b53a5c
    s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_remove_runes(struct nk_str *str, int len)
b53a5c
{
b53a5c
    int index;
b53a5c
    const char *begin;
b53a5c
    const char *end;
b53a5c
    nk_rune unicode;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    NK_ASSERT(len >= 0);
b53a5c
    if (!str || len < 0) return;
b53a5c
    if (len >= str->len) {
b53a5c
        str->len = 0;
b53a5c
        return;
b53a5c
    }
b53a5c
b53a5c
    index = str->len - len;
b53a5c
    begin = nk_str_at_rune(str, index, &unicode, &len);
b53a5c
    end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
b53a5c
    nk_str_remove_chars(str, (int)(end-begin)+1);
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_delete_chars(struct nk_str *s, int pos, int len)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || !len || (nk_size)pos > s->buffer.allocated ||
b53a5c
        (nk_size)(pos + len) > s->buffer.allocated) return;
b53a5c
b53a5c
    if ((nk_size)(pos + len) < s->buffer.allocated) {
b53a5c
        /* memmove */
b53a5c
        char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
b53a5c
        char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
b53a5c
        NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
b53a5c
        NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
b53a5c
        s->buffer.allocated -= (nk_size)len;
b53a5c
    } else nk_str_remove_chars(s, len);
b53a5c
    s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_delete_runes(struct nk_str *s, int pos, int len)
b53a5c
{
b53a5c
    char *temp;
b53a5c
    nk_rune unicode;
b53a5c
    char *begin;
b53a5c
    char *end;
b53a5c
    int unused;
b53a5c
b53a5c
    NK_ASSERT(s);
b53a5c
    NK_ASSERT(s->len >= pos + len);
b53a5c
    if (s->len < pos + len)
b53a5c
        len = NK_CLAMP(0, (s->len - pos), s->len);
b53a5c
    if (!len) return;
b53a5c
b53a5c
    temp = (char *)s->buffer.memory.ptr;
b53a5c
    begin = nk_str_at_rune(s, pos, &unicode, &unused);
b53a5c
    if (!begin) return;
b53a5c
    s->buffer.memory.ptr = begin;
b53a5c
    end = nk_str_at_rune(s, len, &unicode, &unused);
b53a5c
    s->buffer.memory.ptr = temp;
b53a5c
    if (!end) return;
b53a5c
    nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
b53a5c
}
b53a5c
NK_API char*
b53a5c
nk_str_at_char(struct nk_str *s, int pos)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || pos > (int)s->buffer.allocated) return 0;
b53a5c
    return nk_ptr_add(char, s->buffer.memory.ptr, pos);
b53a5c
}
b53a5c
NK_API char*
b53a5c
nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    int src_len = 0;
b53a5c
    int glyph_len = 0;
b53a5c
    char *text;
b53a5c
    int text_len;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    NK_ASSERT(unicode);
b53a5c
    NK_ASSERT(len);
b53a5c
b53a5c
    if (!str || !unicode || !len) return 0;
b53a5c
    if (pos < 0) {
b53a5c
        *unicode = 0;
b53a5c
        *len = 0;
b53a5c
        return 0;
b53a5c
    }
b53a5c
b53a5c
    text = (char*)str->buffer.memory.ptr;
b53a5c
    text_len = (int)str->buffer.allocated;
b53a5c
    glyph_len = nk_utf_decode(text, unicode, text_len);
b53a5c
    while (glyph_len) {
b53a5c
        if (i == pos) {
b53a5c
            *len = glyph_len;
b53a5c
            break;
b53a5c
        }
b53a5c
b53a5c
        i++;
b53a5c
        src_len = src_len + glyph_len;
b53a5c
        glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
b53a5c
    }
b53a5c
    if (i != pos) return 0;
b53a5c
    return text + src_len;
b53a5c
}
b53a5c
NK_API const char*
b53a5c
nk_str_at_char_const(const struct nk_str *s, int pos)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || pos > (int)s->buffer.allocated) return 0;
b53a5c
    return nk_ptr_add(char, s->buffer.memory.ptr, pos);
b53a5c
}
b53a5c
NK_API const char*
b53a5c
nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
b53a5c
{
b53a5c
    int i = 0;
b53a5c
    int src_len = 0;
b53a5c
    int glyph_len = 0;
b53a5c
    char *text;
b53a5c
    int text_len;
b53a5c
b53a5c
    NK_ASSERT(str);
b53a5c
    NK_ASSERT(unicode);
b53a5c
    NK_ASSERT(len);
b53a5c
b53a5c
    if (!str || !unicode || !len) return 0;
b53a5c
    if (pos < 0) {
b53a5c
        *unicode = 0;
b53a5c
        *len = 0;
b53a5c
        return 0;
b53a5c
    }
b53a5c
b53a5c
    text = (char*)str->buffer.memory.ptr;
b53a5c
    text_len = (int)str->buffer.allocated;
b53a5c
    glyph_len = nk_utf_decode(text, unicode, text_len);
b53a5c
    while (glyph_len) {
b53a5c
        if (i == pos) {
b53a5c
            *len = glyph_len;
b53a5c
            break;
b53a5c
        }
b53a5c
b53a5c
        i++;
b53a5c
        src_len = src_len + glyph_len;
b53a5c
        glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
b53a5c
    }
b53a5c
    if (i != pos) return 0;
b53a5c
    return text + src_len;
b53a5c
}
b53a5c
NK_API nk_rune
b53a5c
nk_str_rune_at(const struct nk_str *str, int pos)
b53a5c
{
b53a5c
    int len;
b53a5c
    nk_rune unicode = 0;
b53a5c
    nk_str_at_const(str, pos, &unicode, &len);
b53a5c
    return unicode;
b53a5c
}
b53a5c
NK_API char*
b53a5c
nk_str_get(struct nk_str *s)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || !s->len || !s->buffer.allocated) return 0;
b53a5c
    return (char*)s->buffer.memory.ptr;
b53a5c
}
b53a5c
NK_API const char*
b53a5c
nk_str_get_const(const struct nk_str *s)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || !s->len || !s->buffer.allocated) return 0;
b53a5c
    return (const char*)s->buffer.memory.ptr;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_len(struct nk_str *s)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || !s->len || !s->buffer.allocated) return 0;
b53a5c
    return s->len;
b53a5c
}
b53a5c
NK_API int
b53a5c
nk_str_len_char(struct nk_str *s)
b53a5c
{
b53a5c
    NK_ASSERT(s);
b53a5c
    if (!s || !s->len || !s->buffer.allocated) return 0;
b53a5c
    return (int)s->buffer.allocated;
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_clear(struct nk_str *str)
b53a5c
{
b53a5c
    NK_ASSERT(str);
b53a5c
    nk_buffer_clear(&str->buffer);
b53a5c
    str->len = 0;
b53a5c
}
b53a5c
NK_API void
b53a5c
nk_str_free(struct nk_str *str)
b53a5c
{
b53a5c
    NK_ASSERT(str);
b53a5c
    nk_buffer_free(&str->buffer);
b53a5c
    str->len = 0;
b53a5c
}
b53a5c