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 |