GCC Code Coverage Report


Directory: src/
File: src/misc/jstring.cpp
Date: 2025-10-15 09:43:47
Exec Total Coverage
Lines: 158 165 95.8%
Functions: 8 9 88.9%
Branches: 57 63 90.5%

Line Branch Exec Source
1 #include <algorithm>
2 #include <gyoji-misc/jstring.hpp>
3
4 using namespace Gyoji::misc;
5
6 30596 std::vector<std::string> Gyoji::misc::string_split(const std::string &str, const std::string &delimiter)
7 {
8 30596 std::vector<std::string> ret;
9 30596 size_t pos = 0;
10 while (true) {
11 31090 size_t newpos = str.find(delimiter, pos);
12
2/2
✓ Branch 0 taken 30596 times.
✓ Branch 1 taken 494 times.
31090 if (newpos == std::string::npos) {
13 30596 break;
14 }
15 494 ret.push_back(str.substr(pos, newpos-pos));
16 494 pos = newpos + delimiter.size();
17 494 }
18
1/2
✓ Branch 0 taken 30596 times.
✗ Branch 1 not taken.
30596 if (pos == std::string::npos) {
19 }
20 else {
21 30596 ret.push_back(str.substr(pos));
22 }
23 30596 return ret;
24 }
25
26 std::string
27 Gyoji::misc::join_nonempty(const std::string &a, const std::string & b, const std::string delimiter)
28 {
29 std::string ret;
30 if (a.size() == 0) {
31 return b;
32 }
33 else {
34 return a + delimiter + b;
35 }
36 }
37
38 442 std::string Gyoji::misc::join(const std::vector<std::string> & list, std::string delimiter)
39 {
40 442 std::string ret;
41
42 442 bool first = true;
43
2/2
✓ Branch 4 taken 758 times.
✓ Branch 5 taken 442 times.
1200 for (const auto & s : list) {
44
2/2
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 414 times.
758 if (!first) {
45 344 ret = ret + delimiter;
46 }
47 758 first = false;
48 758 ret = ret + s;
49 }
50
51 442 return ret;
52 }
53
54 814 bool Gyoji::misc::startswith(const std::string & s, const std::string & prefix)
55 {
56 814 size_t found_pos = s.find(prefix);
57
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 752 times.
814 if (found_pos == 0) {
58 62 return true;
59 }
60 752 return false;
61 }
62 1504 bool Gyoji::misc::endswith(const std::string & s, const std::string & suffix)
63 {
64 1504 size_t found_pos = s.find(suffix);
65
6/6
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 1388 times.
✓ Branch 4 taken 114 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 114 times.
✓ Branch 7 taken 1390 times.
1504 if (found_pos != std::string::npos && found_pos == s.size() - suffix.size()) {
66 114 return true;
67 }
68 1390 return false;
69 }
70
71 std::string
72 272 Gyoji::misc::string_remove(const std::string & str, const std::string & remove)
73 {
74 272 std::string ret(str);
75 while (true) {
76 444 size_t start_pos = ret.find(remove);
77 // String is not found at all.
78
2/2
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 172 times.
444 if (start_pos == std::string::npos) {
79 272 break;
80 }
81
82 172 ret.erase(start_pos, remove.length());
83 172 }
84 272 return ret;
85
86 }
87
88 std::string
89 196 Gyoji::misc::string_replace_start(std::string str, const std::string from, const std::string to)
90 {
91 196 std::string ret(str);
92 196 size_t start_pos = str.find(from);
93
94 // String is not found at all.
95
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 16 times.
196 if (start_pos == std::string::npos) {
96 180 return ret;
97 }
98 // If the string is not found at the start, so do nothing.
99
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (start_pos != 0) {
100 2 return ret;
101 }
102
103 // Replace the string.
104 14 ret.replace(start_pos, from.length(), to);
105 14 return ret;
106 }
107
108 // TODO: These need to be implemented and
109 // must guarantee that they are reversible
110 // in all cases.
111
112 24 bool Gyoji::misc::string_c_escape(std::string & escaped_string, const std::string & unescaped_string, bool is_char)
113 {
114 // Take an un-escaped string and insert the \n, \r, \e
115 // escapes exactly as if it were a string literal expressed
116 // in C. Choose exactly one set of escapes as the 'core'
117 // standard set from C, but no more and no less. This should
118 // be the least common denominator for escapes.
119
2/2
✓ Branch 5 taken 242 times.
✓ Branch 6 taken 24 times.
266 for (char c : unescaped_string) {
120
11/11
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 184 times.
242 switch (c) {
121 6 case 0x07:
122 6 escaped_string.push_back('\\');
123 6 escaped_string.push_back('a');
124 6 break;
125 4 case 0x08:
126 4 escaped_string.push_back('\\');
127 4 escaped_string.push_back('b');
128 4 break;
129 4 case 0x1b:
130 4 escaped_string.push_back('\\');
131 4 escaped_string.push_back('e');
132 4 break;
133 4 case 0x0c:
134 4 escaped_string.push_back('\\');
135 4 escaped_string.push_back('f');
136 4 break;
137 8 case 0x0a:
138 8 escaped_string.push_back('\\');
139 8 escaped_string.push_back('n');
140 8 break;
141 4 case 0x0d:
142 4 escaped_string.push_back('\\');
143 4 escaped_string.push_back('r');
144 4 break;
145 4 case 0x09:
146 4 escaped_string.push_back('\\');
147 4 escaped_string.push_back('t');
148 4 break;
149 14 case 0x27:
150
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 if (is_char) {
151 8 escaped_string.push_back('\\');
152 8 escaped_string.push_back('\'');
153 }
154 else {
155 6 escaped_string.push_back('\'');
156 }
157 14 break;
158 6 case 0x22:
159
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (is_char) {
160 4 escaped_string.push_back('\"');
161 }
162 else {
163 2 escaped_string.push_back('\\');
164 2 escaped_string.push_back('\"');
165 }
166 6 break;
167 4 case 0x5c:
168 4 escaped_string.push_back('\\');
169 4 escaped_string.push_back('\\');
170 4 break;
171 184 default:
172 184 escaped_string.push_back(c);
173 184 break;
174 }
175 }
176 24 return true;
177 }
178
179 bool
180 26 Gyoji::misc::string_c_unescape(std::string & unescaped_string, size_t & location, const std::string & escaped_string, bool is_char)
181 {
182 // Take the 'traditional' C escape sequences
183 // and turn them into their 'traditional' counterparts.
184 #define NORMAL 0
185 #define IN_ESCAPE 1
186
187 26 location = 0;
188
189 26 int state = NORMAL;
190
2/2
✓ Branch 4 taken 344 times.
✓ Branch 5 taken 24 times.
368 for (char c : escaped_string) {
191
2/3
✓ Branch 0 taken 294 times.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
344 switch (state) {
192 294 case NORMAL:
193
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 244 times.
294 if (c == '\\') {
194 50 state = IN_ESCAPE;
195 }
196 else {
197 244 unescaped_string.push_back(c);
198 }
199 294 break;
200 50 case IN_ESCAPE:
201
11/11
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 2 times.
50 switch (c) {
202 4 case '\\':
203 4 unescaped_string.push_back(c);
204 4 state = NORMAL;
205 4 break;
206 6 case 'a':
207 6 unescaped_string.push_back(0x07);
208 6 state = NORMAL;
209 6 break;
210 4 case 'b':
211 4 unescaped_string.push_back(0x08);
212 4 state = NORMAL;
213 4 break;
214 4 case 'e':
215 4 unescaped_string.push_back(0x1b);
216 4 state = NORMAL;
217 4 break;
218 4 case 'f':
219 4 unescaped_string.push_back(0x0c);
220 4 state = NORMAL;
221 4 break;
222 8 case 'n':
223 8 unescaped_string.push_back(0x0a);
224 8 state = NORMAL;
225 8 break;
226 4 case 'r':
227 4 unescaped_string.push_back(0x0d);
228 4 state = NORMAL;
229 4 break;
230 4 case 't':
231 4 unescaped_string.push_back(0x09);
232 4 state = NORMAL;
233 4 break;
234 8 case '\'':
235
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (is_char) {
236 8 unescaped_string.push_back(0x27);
237 8 state = NORMAL;
238 }
239 else {
240 2 return false;
241 }
242 8 break;
243 2 case '\"':
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (is_char) {
245 return false;
246 }
247 else {
248 2 unescaped_string.push_back(0x22);
249 2 state = NORMAL;
250 }
251 2 break;
252 2 default:
253 // This is not a valid escape sequence.
254 2 return false;
255
256 }
257 }
258 342 location++;
259 }
260
261 24 return true;
262 }
263
264