txtbuf.c - ltk - GUI toolkit for X11 (WIP)
HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR 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 }