GCC Code Coverage Report


Directory: src/gate/
File: src/gate/strings_chars.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 90 101 89.1%
Functions: 16 16 100.0%
Branches: 89 136 65.4%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/strings.h"
30
31 #define U8_TERM ((gate_char8_t)(0x80))
32 #define U8_2B ((gate_char8_t)(0xC0))
33 #define U8_3B ((gate_char8_t)(0xE0))
34 #define U8_4B ((gate_char8_t)(0xF0))
35
36 #define U32_07 ((gate_char32_t)(0x07))
37 #define U32_0F ((gate_char32_t)(0x0F))
38 #define U32_3F ((gate_char32_t)(0x3F))
39
40 #define U16_1 ((gate_char16_t)(0xD800))
41 #define U16_2 ((gate_char16_t)(0xDC00))
42 #define U16_M ((gate_char16_t)(0x03FF))
43
44
45 1200 gate_size_t gate_char_read_utf8(gate_char8_t const* src, gate_size_t srclen, gate_char32_t* dst)
46 {
47
1/2
✓ Branch 0 taken 1200 times.
✗ Branch 1 not taken.
1200 if (srclen > 0)
48 {
49
2/2
✓ Branch 0 taken 1196 times.
✓ Branch 1 taken 4 times.
1200 if ((*src & 0x80) == 0)
50 {
51 1196 *dst = (gate_char32_t)*src;
52 1196 return 1;
53 }
54
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 else if (((src[0] & 0xE0) == 0xC0) && (srclen > 1) && ((src[1] & 0xC0) == 0x80))
55 {
56 2 *dst = (gate_char32_t)((gate_char32_t)(src[0] & 0x1F) << 6) | (gate_char32_t)(src[1] & 0x3F);
57 2 return 2;
58 }
59
5/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
2 else if (((src[0] & 0xF0) == 0xE0) && (srclen > 2) && ((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80))
60 {
61 1 *dst = (gate_char32_t)((gate_char32_t)(src[0] & 0x0F) << 12) | (gate_char32_t)((gate_char32_t)(src[1] & 0x3F) << 6) | (gate_char32_t)(src[2] & 0x3F);
62 1 return 3;
63 }
64
5/10
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1 else if (((src[0] & 0xF8) == 0xF0) && (srclen > 3) && ((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80))
65 {
66 1 *dst = (gate_char32_t)((gate_char32_t)(src[0] & 0x07) << 18) | (gate_char32_t)((gate_char32_t)(src[1] & 0x3F) << 12) | (gate_char32_t)((gate_char32_t)(src[2] & 0x3F) << 6) | (gate_char32_t)(src[3] & 0x3F);
67 1 return 4;
68 }
69 }
70 return 0;
71 }
72 74 gate_size_t gate_char_read_utf16(gate_char16_t const* src, gate_size_t srclen, gate_char32_t* dst)
73 {
74
1/2
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
74 if (srclen > 0)
75 {
76
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
74 if (((src[0] & U16_1) == U16_1) && (srclen > 1) && ((src[1] & U16_2) == U16_2))
77 {
78 1 *dst = ((gate_char32_t)(src[0] & U16_M) << 10) | (gate_char32_t)(src[1] & U16_M);
79 1 *dst += 0x10000;
80 1 return 2;
81 }
82 else
83 {
84 73 *dst = (gate_char32_t)(src[0]);
85 73 return 1;
86 }
87 }
88 return 0;
89 }
90 57 gate_size_t gate_char_read_utf32(gate_char32_t const* src, gate_size_t srclen, gate_char32_t* dst)
91 {
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (srclen < 1)
93 {
94 return 0;
95 }
96 57 *dst = *src;
97 57 return 1;
98 }
99 203 gate_size_t gate_char_write_utf8(gate_char32_t src, gate_char8_t* dst, gate_size_t dstlen)
100 {
101
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 3 times.
203 if (src < 0x80)
102 {
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200 times.
200 if (dstlen == 0)
104 {
105 return 0;
106 }
107 200 dst[0] = (gate_char8_t)src;
108 200 return 1;
109 }
110
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 else if (src < 0x800)
111 {
112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dstlen < 2)
113 {
114 return 0;
115 }
116 1 dst[0] = U8_2B | (gate_char8_t)(src >> 6);
117 1 dst[1] = U8_TERM | (gate_char8_t)(src & U32_3F);
118 1 return 2;
119 }
120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 else if (src < 0x010000)
121 {
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dstlen < 3)
123 {
124 return 0;
125 }
126 1 dst[0] = U8_3B | (gate_char8_t)((src >> 12) & U32_0F);
127 1 dst[1] = U8_TERM | (gate_char8_t)((src >> 6) & U32_3F);
128 1 dst[2] = U8_TERM | (gate_char8_t)(src & U32_3F);
129 1 return 3;
130 }
131
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (src < 0x0110000)
132 {
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dstlen < 4)
134 {
135 return 0;
136 }
137 1 dst[0] = U8_4B | (gate_char8_t)(((src >> 18) & U32_07));
138 1 dst[1] = U8_TERM | (gate_char8_t)(((src >> 12) & U32_3F));
139 1 dst[2] = U8_TERM | (gate_char8_t)(((src >> 6) & U32_3F));
140 1 dst[3] = U8_TERM | (gate_char8_t)((src & U32_3F));
141 1 return 4;
142 }
143 return 0;
144 }
145 1109 gate_size_t gate_char_write_utf16(gate_char32_t src, gate_char16_t* dst, gate_size_t dstlen)
146 {
147
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1108 times.
1109 if (src > 0x10000)
148 {
149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (dstlen < 2)
150 {
151 return 0;
152 }
153 1 src -= 0x10000;
154 1 dst[0] = (gate_char16_t)(src >> 10) | U16_1;
155 1 dst[1] = (gate_char16_t)(src & (gate_char32_t)(U16_M)) | U16_2;
156 1 return 2;
157 }
158 else
159 {
160 1108 dst[0] = (gate_char16_t)src;
161 1108 return 1;
162 }
163
164 }
165 12 gate_size_t gate_char_write_utf32(gate_char32_t src, gate_char32_t* dst, gate_size_t dstlen)
166 {
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (dstlen < 1)
168 {
169 return 0;
170 }
171 12 *dst = src;
172 12 return 1;
173 }
174
175
176
177
178 #define UTF_CONVERT(reader, writer, src, srclen, dst, dstlen) \
179 gate_size_t ret = 0; \
180 gate_size_t decoded; \
181 gate_size_t encoded; \
182 gate_char32_t u32; \
183 while((srclen != 0) && (dstlen != 0)) \
184 { \
185 decoded = reader(src, srclen, &u32); \
186 if(decoded == 0) \
187 { \
188 break; \
189 } \
190 src += decoded; \
191 srclen -= decoded; \
192 encoded = writer(u32, dst, dstlen); \
193 if(encoded == 0) \
194 { \
195 break; \
196 } \
197 dst += encoded; \
198 dstlen -= encoded; \
199 ret += encoded; \
200 } \
201 if(dstlen != 0) \
202 { \
203 *dst = 0; \
204 } \
205 return ret;
206
207 4 gate_size_t gate_str_utf8_2_utf16(gate_char8_t const* src, gate_size_t srclen, gate_char16_t* dst, gate_size_t dstlen)
208 {
209
7/10
✗ Branch 1 not taken.
✓ Branch 2 taken 1048 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1048 times.
✓ Branch 6 taken 1048 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1048 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 1 times.
1052 UTF_CONVERT(gate_char_read_utf8, gate_char_write_utf16, src, srclen, dst, dstlen);
210 }
211 2 gate_size_t gate_str_utf8_2_utf32(gate_char8_t const* src, gate_size_t srclen, gate_char32_t* dst, gate_size_t dstlen)
212 {
213
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
10 UTF_CONVERT(gate_char_read_utf8, gate_char_write_utf32, src, srclen, dst, dstlen);
214 }
215 1 gate_size_t gate_str_utf16_2_utf8(gate_char16_t const* src, gate_size_t srclen, gate_char8_t* dst, gate_size_t dstlen)
216 {
217
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
4 UTF_CONVERT(gate_char_read_utf16, gate_char_write_utf8, src, srclen, dst, dstlen);
218 }
219 1 gate_size_t gate_str_utf16_2_utf32(gate_char16_t const* src, gate_size_t srclen, gate_char32_t* dst, gate_size_t dstlen)
220 {
221
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
4 UTF_CONVERT(gate_char_read_utf16, gate_char_write_utf32, src, srclen, dst, dstlen);
222 }
223 13 gate_size_t gate_str_utf32_2_utf8(gate_char32_t const* src, gate_size_t srclen, gate_char8_t* dst, gate_size_t dstlen)
224 {
225
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 52 times.
✓ Branch 6 taken 52 times.
✓ Branch 7 taken 13 times.
✓ Branch 8 taken 52 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 11 not taken.
65 UTF_CONVERT(gate_char_read_utf32, gate_char_write_utf8, src, srclen, dst, dstlen);
226 }
227 1 gate_size_t gate_str_utf32_2_utf16(gate_char32_t const* src, gate_size_t srclen, gate_char16_t* dst, gate_size_t dstlen)
228 {
229
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
4 UTF_CONVERT(gate_char_read_utf32, gate_char_write_utf16, src, srclen, dst, dstlen);
230 }
231
232
233 10041 int gate_char_lowercase(int chr)
234 {
235
4/4
✓ Branch 0 taken 9323 times.
✓ Branch 1 taken 718 times.
✓ Branch 2 taken 148 times.
✓ Branch 3 taken 9175 times.
10041 if ((chr >= 'A') && (chr <= 'Z'))
236 {
237 148 return chr + ('a' - 'A');
238 }
239 9893 return chr;
240 }
241 7 int gate_char_uppercase(int chr)
242 {
243
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 if ((chr >= 'a') && (chr <= 'z'))
244 {
245 7 return chr - ('a' - 'A');
246 }
247 return chr;
248 }
249 115 gate_bool_t gate_char_is_digit(int chr)
250 {
251
4/4
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 3 times.
115 if ((chr >= '0') && (chr <= '9'))
252 {
253 109 return true;
254 }
255 else
256 {
257 6 return false;
258 }
259 }
260 167 gate_bool_t gate_char_is_whitespace(int chr)
261 {
262 static char const ws[] = GATE_STR_WHITESPACES;
263 gate_size_t ndx;
264
2/2
✓ Branch 0 taken 551 times.
✓ Branch 1 taken 128 times.
679 for (ndx = 0; ndx != GATE_STR_WHITESPACES_LENGTH; ++ndx)
265 {
266
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 512 times.
551 if (chr == ws[ndx])
267 {
268 39 return true;
269 }
270 }
271 128 return false;
272 }
273