dte test coverage


Directory: ./
File: src/util/string.c
Date: 2025-02-14 16:55:22
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 194669 char *string_reserve_space(String *s, size_t more)
24 {
25 194669 BUG_ON(more == 0);
26 194669 size_t min_alloc = xadd(s->len, more);
27
2/2
✓ Branch 0 (5→6) taken 69 times.
✓ Branch 1 (5→7) taken 194600 times.
194669 if (unlikely(s->alloc < min_alloc)) {
28 69 string_grow(s, min_alloc);
29 }
30 194669 return s->buffer + s->len;
31 }
32
33 387 void string_free(String *s)
34 {
35 387 free(s->buffer);
36 387 *s = (String) STRING_INIT;
37 387 }
38
39 149634 void string_append_byte(String *s, unsigned char byte)
40 {
41 149634 string_reserve_space(s, 1);
42 149634 s->buffer[s->len++] = byte;
43 149634 }
44
45 11 size_t string_append_codepoint(String *s, CodePoint u)
46 {
47 11 string_reserve_space(s, 4);
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 11036 void string_append_buf(String *s, const char *ptr, size_t len)
79 {
80
2/2
✓ Branch 0 (2→3) taken 9439 times.
✓ Branch 1 (2→5) taken 1597 times.
11036 if (len == 0) {
81 return;
82 }
83 9439 char *reserved = string_reserve_space(s, len);
84 9439 s->len += len;
85 9439 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 34599 static char *null_terminate(String *s)
122 {
123 34599 string_reserve_space(s, 1);
124 34599 s->buffer[s->len] = '\0';
125 34599 return s->buffer;
126 }
127
128 26655 char *string_steal_cstring(String *s)
129 {
130 26655 char *buf = null_terminate(s);
131 26655 *s = (String) STRING_INIT;
132 26655 return buf;
133 }
134
135 88 char *string_clone_cstring(const String *s)
136 {
137 88 size_t len = s->len;
138 88 char *b = xmalloc(len + 1);
139 88 b[len] = '\0';
140
2/2
✓ Branch 0 (3→4) taken 85 times.
✓ Branch 1 (3→5) taken 3 times.
88 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 7944 const char *string_borrow_cstring(String *s)
154 {
155 7944 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