ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | LICENSE

txtbuf.c (4171B)


      1 /*
      2  * Copyright (c) 2021-2024 lumidify <nobody@lumidify.org>
      3  *
      4  * Permission to use, copy, modify, and/or distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #include <stdarg.h>
     21 
     22 #include "memory.h"
     23 #include "txtbuf.h"
     24 
     25 txtbuf *
     26 txtbuf_new(void) {
     27 	txtbuf *buf = ltk_malloc(sizeof(txtbuf));
     28 	buf->text = NULL;
     29 	buf->cap = buf->len = 0;
     30 	return buf;
     31 }
     32 
     33 txtbuf *
     34 txtbuf_new_from_char(const char *str) {
     35 	txtbuf *buf = ltk_malloc(sizeof(txtbuf));
     36 	buf->text = ltk_strdup(str);
     37 	buf->len = strlen(str);
     38 	buf->cap = buf->len + 1;
     39 	return buf;
     40 }
     41 
     42 txtbuf *
     43 txtbuf_new_from_char_len(const char *str, size_t len) {
     44 	txtbuf *buf = ltk_malloc(sizeof(txtbuf));
     45 	buf->text = ltk_strndup(str, len);
     46 	buf->len = len;
     47 	buf->cap = len + 1;
     48 	return buf;
     49 }
     50 
     51 void
     52 txtbuf_fmt(txtbuf *buf, const char *fmt, ...) {
     53 	va_list args;
     54 	va_start(args, fmt);
     55 	int len = vsnprintf(buf->text, buf->cap, fmt, args);
     56 	/* FIXME: len can never be negative, right? */
     57 	/* FIXME: maybe also shrink here */
     58 	if ((size_t)len >= buf->cap) {
     59 		va_end(args);
     60 		va_start(args, fmt);
     61 		txtbuf_resize(buf, len);
     62 		vsnprintf(buf->text, buf->cap, fmt, args);
     63 	}
     64 	buf->len = len;
     65 	va_end(args);
     66 }
     67 
     68 void
     69 txtbuf_set_text(txtbuf *buf, const char *text) {
     70 	txtbuf_set_textn(buf, text, strlen(text));
     71 }
     72 
     73 void
     74 txtbuf_set_textn(txtbuf *buf, const char *text, size_t len) {
     75 	txtbuf_resize(buf, len);
     76 	buf->len = len;
     77 	memmove(buf->text, text, len);
     78 	buf->text[buf->len] = '\0';
     79 }
     80 
     81 void
     82 txtbuf_append(txtbuf *buf, const char *text) {
     83 	txtbuf_appendn(buf, text, strlen(text));
     84 }
     85 
     86 /* FIXME: some sort of append that does not resize until there's not enough
     87    space so a buffer that will be filled up anyways doesn't have to be
     88    constantly resized */
     89 void
     90 txtbuf_appendn(txtbuf *buf, const char *text, size_t len) {
     91 	/* FIXME: overflow protection here and everywhere else */
     92 	txtbuf_resize(buf, buf->len + len);
     93 	memmove(buf->text + buf->len, text, len);
     94 	buf->len += len;
     95 	buf->text[buf->len] = '\0';
     96 }
     97 
     98 void
     99 txtbuf_resize(txtbuf *buf, size_t sz) {
    100 	/* always leave room for extra \0 */
    101 	size_t cap = ideal_array_size(buf->cap, sz + 1);
    102 	if (cap != buf->cap) {
    103 		buf->text = ltk_realloc(buf->text, cap);
    104 		buf->cap = cap;
    105 	}
    106 }
    107 
    108 void
    109 txtbuf_destroy(txtbuf *buf) {
    110 	if (!buf)
    111 		return;
    112 	free(buf->text);
    113 	free(buf);
    114 }
    115 
    116 void
    117 txtbuf_copy(txtbuf *dst, txtbuf *src) {
    118 	txtbuf_resize(dst, src->len);
    119 	if (src->text && dst->text) {
    120 		memcpy(dst->text, src->text, src->len);
    121 		dst->text[src->len] = '\0';
    122 	}
    123 	dst->len = src->len;
    124 }
    125 
    126 txtbuf *
    127 txtbuf_dup(txtbuf *src) {
    128 	txtbuf *dst = txtbuf_new();
    129 	txtbuf_copy(dst, src);
    130 	return dst;
    131 }
    132 
    133 char *
    134 txtbuf_get_textcopy(txtbuf *buf) {
    135 	return buf->text ? ltk_strndup(buf->text, buf->len) : ltk_strdup("");
    136 }
    137 
    138 const char *
    139 txtbuf_get_text(txtbuf *buf) {
    140 	return buf->text;
    141 }
    142 
    143 size_t
    144 txtbuf_len(txtbuf *buf) {
    145 	return buf->len;
    146 }
    147 
    148 /* FIXME: proper "normalize" function to add nul-termination if needed */
    149 int
    150 txtbuf_cmp(txtbuf *buf1, txtbuf *buf2) {
    151 	/* FIXME: I guess strcmp would be possible as well since it's nul-terminated now */
    152 	/* FIXME: Test this because I was tired while writing it */
    153 	int cmp = strncmp(buf1->text, buf2->text, buf1->len < buf2->len ? buf1->len : buf2->len);
    154 	if (cmp == 0) {
    155 		if (buf1->len < buf2->len)
    156 			return -1;
    157 		else if (buf1->len > buf2->len)
    158 			return 1;
    159 	}
    160 	return cmp;
    161 }
    162 
    163 int
    164 txtbuf_eql(txtbuf *buf1, txtbuf *buf2) {
    165 	return txtbuf_cmp(buf1, buf2) == 0;
    166 }
    167 
    168 void
    169 txtbuf_clear(txtbuf *buf) {
    170 	if (buf->len > 0) {
    171 		buf->len = 0;
    172 		buf->text[0] = '\0';
    173 	}
    174 }