dte test coverage


Directory: ./
File: src/util/string.c
Date: 2025-05-08 15:05:54
Exec Total Coverage
Lines: 89 89 100.0%
Functions: 17 17 100.0%
Branches: 14 14 100.0%

Line Branch Exec Source
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include "string.h"
5 #include "debug.h"
6 #include "utf8.h"
7 #include "xmalloc.h"
8
9 69 static COLD void string_grow(String *s, size_t min_alloc)
10 {
11 69 size_t alloc = s->alloc;
12
2/2
✓ Branch 0 (4→3) taken 238 times.
✓ Branch 1 (4→5) taken 69 times.
307 while (alloc < min_alloc) {
13 238 alloc = (alloc * 3 + 2) / 2;
14 }
15 69 alloc = next_multiple(alloc, 16);
16 69 s->alloc = alloc;
17 69 s->buffer = xrealloc(s->buffer, alloc);
18 69 }
19
20 // Reserve `more` bytes of additional space and return a pointer to the
21 // start of it, to allow writing directly to the buffer. Updating `s->len`
22 // to reflect the new length is left up to the caller.
23 204270 char *string_reserve_space(String *s, size_t more)
24 {
25 204270 BUG_ON(more == 0);
26 204270 size_t min_alloc = xadd(s->len, more);
27
2/2
✓ Branch 0 (5→6) taken 69 times.
✓ Branch 1 (5→7) taken 204201 times.
204270 if (unlikely(s->alloc < min_alloc)) {
28 69 string_grow(s, min_alloc);
29 }
30 204270 return s->buffer + s->len;
31 }
32
33 400 void string_free(String *s)
34 {
35 400 free(s->buffer);
36 400 *s = (String) STRING_INIT;
37 400 }
38
39 156898 void string_append_byte(String *s, unsigned char byte)
40 {
41 156898 string_reserve_space(s, 1);
42 156898 s->buffer[s->len++] = byte;
43 156898 }
44
45 11 size_t string_append_codepoint(String *s, CodePoint u)
46 {
47 11 string_reserve_space(s, UTF8_MAX_SEQ_LEN);
48 11 size_t n = u_set_char_raw(s->buffer + s->len, u);
49 11 s->len += n;
50 11 return n;
51 }
52
53 7 static char *string_make_space(String *s, size_t pos, size_t len)
54 {
55 7 BUG_ON(pos > s->len);
56 7 BUG_ON(len == 0);
57 7 string_reserve_space(s, len);
58 7 char *start = s->buffer + pos;
59 7 memmove(start + len, start, s->len - pos);
60 7 s->len += len;
61 7 return start;
62 }
63
64 6 size_t string_insert_codepoint(String *s, size_t pos, CodePoint u)
65 {
66 6 size_t len = u_char_size(u);
67 6 return u_set_char_raw(string_make_space(s, pos, len), u);
68 }
69
70 2 void string_insert_buf(String *s, size_t pos, const char *buf, size_t len)
71 {
72
2/2
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→5) taken 1 times.
2 if (len == 0) {
73 return;
74 }
75 1 memcpy(string_make_space(s, pos, len), buf, len);
76 }
77
78 11593 void string_append_buf(String *s, const char *ptr, size_t len)
79 {
80
2/2
✓ Branch 0 (2→3) taken 9948 times.
✓ Branch 1 (2→5) taken 1645 times.
11593 if (len == 0) {
81 return;
82 }
83 9948 char *reserved = string_reserve_space(s, len);
84 9948 s->len += len;
85 9948 memcpy(reserved, ptr, len);
86 }
87
88 3 void string_append_memset(String *s, unsigned char byte, size_t len)
89 {
90
2/2
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→5) taken 2 times.
3 if (len == 0) {
91 return;
92 }
93 1 char *reserved = string_reserve_space(s, len);
94 1 s->len += len;
95 1 memset(reserved, byte, len);
96 }
97
98 VPRINTF(2)
99 6 static void string_vsprintf(String *s, const char *fmt, va_list ap)
100 {
101 6 va_list ap2;
102 6 va_copy(ap2, ap);
103 // Calculate the required size
104 6 int n = vsnprintf(NULL, 0, fmt, ap2);
105 6 va_end(ap2);
106 6 BUG_ON(n < 0);
107 6 string_reserve_space(s, n + 1);
108 6 int wrote = vsnprintf(s->buffer + s->len, n + 1, fmt, ap);
109 6 BUG_ON(wrote != n);
110 6 s->len += wrote;
111 6 }
112
113 6 void string_sprintf(String *s, const char *fmt, ...)
114 {
115 6 va_list ap;
116 6 va_start(ap, fmt);
117 6 string_vsprintf(s, fmt, ap);
118 6 va_end(ap);
119 6 }
120
121 36426 static char *null_terminate(String *s)
122 {
123 36426 string_reserve_space(s, 1);
124 36426 s->buffer[s->len] = '\0';
125 36426 return s->buffer;
126 }
127
128 28190 char *string_steal_cstring(String *s)
129 {
130 28190 char *buf = null_terminate(s);
131 28190 *s = (String) STRING_INIT;
132 28190 return buf;
133 }
134
135 89 char *string_clone_cstring(const String *s)
136 {
137 89 size_t len = s->len;
138 89 char *b = xmalloc(len + 1);
139 89 b[len] = '\0';
140
2/2
✓ Branch 0 (3→4) taken 86 times.
✓ Branch 1 (3→5) taken 3 times.
89 return likely(len) ? memcpy(b, s->buffer, len) : b;
141 }
142
143 /*
144 * This method first ensures that the String buffer is null-terminated
145 * and then returns a const pointer to it, without doing any copying.
146 *
147 * NOTE: the returned pointer only remains valid so long as no other
148 * methods are called on the String. There are no exceptions to this
149 * rule. If the buffer is realloc'd, the pointer will be dangling and
150 * using it will invoke undefined behaviour. If unsure, just use
151 * string_clone_cstring() instead.
152 */
153 8236 const char *string_borrow_cstring(String *s)
154 {
155 8236 return null_terminate(s);
156 }
157
158 9 void string_remove(String *s, size_t pos, size_t len)
159 {
160
2/2
✓ Branch 0 (2→3) taken 8 times.
✓ Branch 1 (2→6) taken 1 times.
9 if (len == 0) {
161 return;
162 }
163 8 size_t oldlen = s->len;
164 8 BUG_ON(pos + len > oldlen);
165 8 s->len -= len;
166 8 memmove(s->buffer + pos, s->buffer + pos + len, oldlen - pos - len);
167 }
168