ltk

Socket-based GUI for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

txtbuf.c (3291B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <stdarg.h>
      5 
      6 #include "util.h"
      7 #include "memory.h"
      8 #include "txtbuf.h"
      9 #include "assert.h"
     10 
     11 txtbuf *
     12 txtbuf_new(void) {
     13 	txtbuf *buf = ltk_malloc(sizeof(txtbuf));
     14 	buf->text = NULL;
     15 	buf->cap = buf->len = 0;
     16 	return buf;
     17 }
     18 
     19 txtbuf *
     20 txtbuf_new_from_char(const char *str) {
     21 	txtbuf *buf = ltk_malloc(sizeof(txtbuf));
     22 	buf->text = ltk_strdup(str);
     23 	buf->len = strlen(str);
     24 	buf->cap = buf->len + 1;
     25 	return buf;
     26 }
     27 
     28 txtbuf *
     29 txtbuf_new_from_char_len(const char *str, size_t len) {
     30 	txtbuf *buf = ltk_malloc(sizeof(txtbuf));
     31 	buf->text = ltk_strndup(str, len);
     32 	buf->len = len;
     33 	buf->cap = len + 1;
     34 	return buf;
     35 }
     36 
     37 void
     38 txtbuf_fmt(txtbuf *buf, const char *fmt, ...) {
     39 	va_list args;
     40 	va_start(args, fmt);
     41 	int len = vsnprintf(buf->text, buf->cap, fmt, args);
     42 	/* FIXME: len can never be negative, right? */
     43 	/* FIXME: maybe also shrink here */
     44 	if ((size_t)len >= buf->cap) {
     45 		va_end(args);
     46 		va_start(args, fmt);
     47 		txtbuf_resize(buf, len);
     48 		vsnprintf(buf->text, buf->cap, fmt, args);
     49 	}
     50 	buf->len = len;
     51 	va_end(args);
     52 }
     53 
     54 void
     55 txtbuf_set_text(txtbuf *buf, const char *text) {
     56 	txtbuf_set_textn(buf, text, strlen(text));
     57 }
     58 
     59 void
     60 txtbuf_set_textn(txtbuf *buf, const char *text, size_t len) {
     61 	txtbuf_resize(buf, len);
     62 	buf->len = len;
     63 	memmove(buf->text, text, len);
     64 	buf->text[buf->len] = '\0';
     65 }
     66 
     67 void
     68 txtbuf_append(txtbuf *buf, const char *text) {
     69 	txtbuf_appendn(buf, text, strlen(text));
     70 }
     71 
     72 /* FIXME: some sort of append that does not resize until there's not enough
     73    space so a buffer that will be filled up anyways doesn't have to be
     74    constantly resized */
     75 void
     76 txtbuf_appendn(txtbuf *buf, const char *text, size_t len) {
     77 	/* FIXME: overflow protection here and everywhere else */
     78 	txtbuf_resize(buf, buf->len + len);
     79 	memmove(buf->text + buf->len, text, len);
     80 	buf->len += len;
     81 	buf->text[buf->len] = '\0';
     82 }
     83 
     84 void
     85 txtbuf_resize(txtbuf *buf, size_t sz) {
     86 	/* always leave room for extra \0 */
     87 	size_t cap = ideal_array_size(buf->cap, sz + 1);
     88 	if (cap != buf->cap) {
     89 		buf->text = ltk_realloc(buf->text, cap);
     90 		buf->cap = cap;
     91 	}
     92 }
     93 
     94 void
     95 txtbuf_destroy(txtbuf *buf) {
     96 	if (!buf)
     97 		return;
     98 	free(buf->text);
     99 	free(buf);
    100 }
    101 
    102 void
    103 txtbuf_copy(txtbuf *dst, txtbuf *src) {
    104 	txtbuf_resize(dst, src->len);
    105 	if (src->text && dst->text) {
    106 		memcpy(dst->text, src->text, src->len);
    107 		dst->text[src->len] = '\0';
    108 	}
    109 	dst->len = src->len;
    110 }
    111 
    112 txtbuf *
    113 txtbuf_dup(txtbuf *src) {
    114 	txtbuf *dst = txtbuf_new();
    115 	txtbuf_copy(dst, src);
    116 	return dst;
    117 }
    118 
    119 char *
    120 txtbuf_get_textcopy(txtbuf *buf) {
    121 	return buf->text ? ltk_strndup(buf->text, buf->len) : ltk_strdup("");
    122 }
    123 
    124 /* FIXME: proper "normalize" function to add nul-termination if needed */
    125 int
    126 txtbuf_cmp(txtbuf *buf1, txtbuf *buf2) {
    127 	/* FIXME: I guess strcmp would be possible as well since it's nul-terminated now */
    128 	/* FIXME: Test this because I was tired while writing it */
    129 	int cmp = strncmp(buf1->text, buf2->text, buf1->len < buf2->len ? buf1->len : buf2->len);
    130 	if (cmp == 0) {
    131 		if (buf1->len < buf2->len)
    132 			return -1;
    133 		else if (buf1->len > buf2->len)
    134 			return 1;
    135 	}
    136 	return cmp;
    137 }
    138 
    139 int
    140 txtbuf_eql(txtbuf *buf1, txtbuf *buf2) {
    141 	return txtbuf_cmp(buf1, buf2) == 0;
    142 }
    143 
    144 void
    145 txtbuf_clear(txtbuf *buf) {
    146 	if (buf->len > 0) {
    147 		buf->len = 0;
    148 		buf->text[0] = '\0';
    149 	}
    150 }