dte test coverage


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