txtbuf.c - ledit - Text editor (WIP)
HTML git clone git://lumidify.org/ledit.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ledit.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
txtbuf.c (3012B)
---
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 = ledit_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(char *str) {
21 txtbuf *buf = ledit_malloc(sizeof(txtbuf));
22 buf->text = ledit_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(char *str, size_t len) {
30 txtbuf *buf = ledit_malloc(sizeof(txtbuf));
31 buf->text = ledit_strndup(str, len);
32 buf->len = len;
33 buf->cap = len + 1;
34 return buf;
35 }
36
37 void
38 txtbuf_fmt(txtbuf *buf, 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, char *text) {
56 txtbuf_set_textn(buf, text, strlen(text));
57 }
58
59 void
60 txtbuf_set_textn(txtbuf *buf, 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, 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, char *text, size_t len) {
77 txtbuf_resize(buf, add_sz(buf->len, len));
78 memmove(buf->text + buf->len, text, len);
79 buf->len += len;
80 buf->text[buf->len] = '\0';
81 }
82
83 void
84 txtbuf_resize(txtbuf *buf, size_t sz) {
85 /* always leave room for extra \0 */
86 size_t cap = ideal_array_size(buf->cap, add_sz(sz, 1));
87 if (cap != buf->cap) {
88 buf->text = ledit_realloc(buf->text, cap);
89 buf->cap = cap;
90 }
91 }
92
93 void
94 txtbuf_destroy(txtbuf *buf) {
95 if (!buf)
96 return;
97 free(buf->text);
98 free(buf);
99 }
100
101 void
102 txtbuf_copy(txtbuf *dst, txtbuf *src) {
103 txtbuf_resize(dst, src->len);
104 if (src->text && dst->text) {
105 memcpy(dst->text, src->text, src->len);
106 dst->text[src->len] = '\0';
107 }
108 dst->len = src->len;
109 }
110
111 txtbuf *
112 txtbuf_dup(txtbuf *src) {
113 txtbuf *dst = txtbuf_new();
114 txtbuf_copy(dst, src);
115 return dst;
116 }
117
118 int
119 txtbuf_cmp(txtbuf *buf1, txtbuf *buf2) {
120 /* FIXME: I guess strcmp would be possible as well since it's nul-terminated now */
121 /* FIXME: Test this because I was tired while writing it */
122 int cmp = strncmp(buf1->text, buf2->text, LEDIT_MIN(buf1->len, buf2->len));
123 if (cmp == 0) {
124 if (buf1->len < buf2->len)
125 return -1;
126 else if (buf1->len > buf2->len)
127 return 1;
128 }
129 return cmp;
130 }
131
132 int
133 txtbuf_eql(txtbuf *buf1, txtbuf *buf2) {
134 return txtbuf_cmp(buf1, buf2) == 0;
135 }
136
137 void
138 txtbuf_clear(txtbuf *buf) {
139 if (buf->len > 0) {
140 buf->len = 0;
141 buf->text[0] = '\0';
142 }
143 }