File: | _build/../src/parser-glue.hh |
Warning: | line 754, column 33 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | ||||
2 | * Copyright © 2017, 2018 Christian Persch | ||||
3 | * | ||||
4 | * This library is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU Lesser General Public | ||||
6 | * License as published by the Free Software Foundation; either | ||||
7 | * version 3 of the License, or (at your option) any later version. | ||||
8 | * | ||||
9 | * This library is distributed in the hope that it will be useful, | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
12 | * Lesser General Public License for more details. | ||||
13 | * | ||||
14 | * You should have received a copy of the GNU General Public License | ||||
15 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
16 | */ | ||||
17 | |||||
18 | #include "config.h" | ||||
19 | |||||
20 | #include <string.h> | ||||
21 | |||||
22 | #include <algorithm> | ||||
23 | #include <cstddef> | ||||
24 | #include <cstdint> | ||||
25 | #include <string> | ||||
26 | #include <vector> | ||||
27 | |||||
28 | using namespace std::literals; | ||||
29 | |||||
30 | #include <glib.h> | ||||
31 | |||||
32 | #include "parser.hh" | ||||
33 | #include "parser-glue.hh" | ||||
34 | #include "parser-charset-tables.hh" | ||||
35 | |||||
36 | #ifdef PARSER_INCLUDE_NOP1 | ||||
37 | #define _BTE_NOP(...)_BTE_CMD(...) _BTE_CMD(__VA_ARGS__) | ||||
38 | #define _BTE_NOQ(...)_BTE_SEQ(...) _BTE_SEQ(__VA_ARGS__) | ||||
39 | #else | ||||
40 | #define _BTE_NOP(...)_BTE_CMD(...) | ||||
41 | #define _BTE_NOQ(...)_BTE_SEQ(...) | ||||
42 | #endif | ||||
43 | |||||
44 | using namespace bte::parser; | ||||
45 | |||||
46 | Parser parser{}; | ||||
47 | Sequence seq{parser}; | ||||
48 | |||||
49 | #if 0 | ||||
50 | static char const* | ||||
51 | seq_to_str(unsigned int type) | ||||
52 | { | ||||
53 | switch (type) { | ||||
54 | case BTE_SEQ_NONE: return "NONE"; | ||||
55 | case BTE_SEQ_IGNORE: return "IGNORE"; | ||||
56 | case BTE_SEQ_GRAPHIC: return "GRAPHIC"; | ||||
57 | case BTE_SEQ_CONTROL: return "CONTROL"; | ||||
58 | case BTE_SEQ_ESCAPE: return "ESCAPE"; | ||||
59 | case BTE_SEQ_CSI: return "CSI"; | ||||
60 | case BTE_SEQ_DCS: return "DCS"; | ||||
61 | case BTE_SEQ_OSC: return "OSC"; | ||||
62 | case BTE_SEQ_APC: return "APC"; | ||||
63 | case BTE_SEQ_PM: return "PM"; | ||||
64 | case BTE_SEQ_SOS: return "SOS"; | ||||
65 | case BTE_SEQ_SCI: return "SCI"; | ||||
66 | default: | ||||
67 | g_assert_not_reached()do { g_assertion_message_expr (((gchar*) 0), "../src/parser-test.cc" , 67, ((const char*) (__PRETTY_FUNCTION__)), __null); } while (0); | ||||
68 | } | ||||
69 | } | ||||
70 | |||||
71 | static char const* | ||||
72 | cmd_to_str(unsigned int command) | ||||
73 | { | ||||
74 | switch (command) { | ||||
75 | #define _BTE_CMD(cmd) case BTE_CMD_##cmd: return #cmd; | ||||
76 | #include "parser-cmd.hh" | ||||
77 | #undef _BTE_CMD | ||||
78 | default: | ||||
79 | static char buf[32]; | ||||
80 | snprintf(buf, sizeof(buf), "UNKOWN(%u)", command); | ||||
81 | return buf; | ||||
82 | } | ||||
83 | } | ||||
84 | |||||
85 | static char const* | ||||
86 | charset_to_str(unsigned int cs) | ||||
87 | { | ||||
88 | switch (cs) { | ||||
89 | #define _BTE_CHARSET_PASTE(name) case BTE_CHARSET_##name: return #name; | ||||
90 | #define _BTE_CHARSET(name) _BTE_CHARSET_PASTE(name) | ||||
91 | #define _BTE_CHARSET_ALIAS_PASTE(name1,name2) | ||||
92 | #define _BTE_CHARSET_ALIAS(name1,name2) | ||||
93 | #include "parser-charset.hh" | ||||
94 | #undef _BTE_CHARSET_PASTE | ||||
95 | #undef _BTE_CHARSET | ||||
96 | #undef _BTE_CHARSET_ALIAS_PASTE | ||||
97 | #undef _BTE_CHARSET_ALIAS | ||||
98 | default: | ||||
99 | static char buf[32]; | ||||
100 | snprintf(buf, sizeof(buf), "UNKOWN(%u)", cs); | ||||
101 | return buf; | ||||
102 | } | ||||
103 | } | ||||
104 | #endif | ||||
105 | |||||
106 | static const char c0str[][6] = { | ||||
107 | "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", | ||||
108 | "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", | ||||
109 | "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", | ||||
110 | "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US", | ||||
111 | "SPACE" | ||||
112 | }; | ||||
113 | |||||
114 | static const char c1str[][5] = { | ||||
115 | "DEL", | ||||
116 | "0x80", "0x81", "BPH", "NBH", "0x84", "NEL", "SSA", "ESA", | ||||
117 | "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3", | ||||
118 | "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA", | ||||
119 | "SOS", "0x99", "SCI", "CSI", "ST", "OSC", "PM", "APC" | ||||
120 | }; | ||||
121 | |||||
122 | static void | ||||
123 | print_escaped(std::u32string const& s) | ||||
124 | { | ||||
125 | for (auto it : s) { | ||||
126 | uint32_t c = (char32_t)it; | ||||
127 | |||||
128 | if (c <= 0x20) | ||||
129 | g_print("%s ", c0str[c]); | ||||
130 | else if (c < 0x7f) | ||||
131 | g_print("%c ", c); | ||||
132 | else if (c < 0xa0) | ||||
133 | g_print("%s ", c1str[c - 0x7f]); | ||||
134 | else | ||||
135 | g_print("U+%04X", c); | ||||
136 | } | ||||
137 | g_print("\n"); | ||||
138 | } | ||||
139 | |||||
140 | #if 0 | ||||
141 | static void | ||||
142 | print_seq() | ||||
143 | { | ||||
144 | auto c = seq.terminator(); | ||||
145 | if (seq.command() == BTE_CMD_GRAPHIC) { | ||||
146 | char buf[7]; | ||||
147 | buf[g_unichar_to_utf8(c, buf)] = 0; | ||||
148 | g_print("%s U+%04X [%s]\n", cmd_to_str(seq.command()), | ||||
149 | c, | ||||
150 | g_unichar_isprint(c) ? buf : "�"); | ||||
151 | } else { | ||||
152 | g_print("%s", cmd_to_str(seq.command())); | ||||
153 | if (seq.size()) { | ||||
154 | g_print(" "); | ||||
155 | for (unsigned int i = 0; i < seq.size(); i++) { | ||||
156 | if (i > 0) | ||||
157 | g_print(";"); | ||||
158 | g_print("%d", seq.param(i)); | ||||
159 | } | ||||
160 | } | ||||
161 | g_print("\n"); | ||||
162 | } | ||||
163 | } | ||||
164 | #endif | ||||
165 | |||||
166 | class bte_seq_builder : public u32SequenceBuilder { | ||||
167 | public: | ||||
168 | bte_seq_builder(unsigned int type, | ||||
169 | uint32_t f) | ||||
170 | : u32SequenceBuilder(type, f) | ||||
171 | { | ||||
172 | } | ||||
173 | |||||
174 | bte_seq_builder(unsigned int type, | ||||
175 | u32SequenceBuilder::string_type const& str) | ||||
176 | : u32SequenceBuilder(type) | ||||
177 | { | ||||
178 | set_string(str); | ||||
179 | } | ||||
180 | |||||
181 | void set_intermediates(uint32_t* i, | ||||
182 | unsigned int ni) noexcept | ||||
183 | { | ||||
184 | for (unsigned int n = 0; n < ni; ++n) | ||||
185 | append_intermediate(i[n]); | ||||
186 | } | ||||
187 | |||||
188 | |||||
189 | void set_params(int* params, | ||||
190 | unsigned int n) noexcept | ||||
191 | { | ||||
192 | for (unsigned int i = 0; i < n; ++i) | ||||
193 | append_param(params[i]); | ||||
194 | } | ||||
195 | |||||
196 | void print(bool c1 = false) const noexcept | ||||
197 | { | ||||
198 | std::u32string s; | ||||
199 | to_string(s, c1); | ||||
200 | print_escaped(s); | ||||
201 | } | ||||
202 | }; | ||||
203 | |||||
204 | static int | ||||
205 | feed_parser(std::u32string const& s) | ||||
206 | { | ||||
207 | int rv = BTE_SEQ_NONE; | ||||
208 | for (auto it : s) { | ||||
209 | rv = parser.feed((uint32_t)(char32_t)it); | ||||
210 | if (rv < 0) | ||||
211 | break; | ||||
212 | } | ||||
213 | return rv; | ||||
214 | } | ||||
215 | |||||
216 | static int | ||||
217 | feed_parser(bte_seq_builder& b, | ||||
218 | bool c1 = false) | ||||
219 | { | ||||
220 | std::u32string s; | ||||
221 | b.to_string(s, c1); | ||||
222 | |||||
223 | return feed_parser(s); | ||||
224 | } | ||||
225 | |||||
226 | static void | ||||
227 | test_seq_arg(void) | ||||
228 | { | ||||
229 | /* Basic test */ | ||||
230 | bte_seq_arg_t arg = BTE_SEQ_ARG_INIT_DEFAULT(0); | ||||
231 | g_assert_false(bte_seq_arg_started(arg))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_49 ; if (!(bte_seq_arg_started(arg))) _g_boolean_var_49 = 1; else _g_boolean_var_49 = 0; _g_boolean_var_49; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 231, ((const char*) ( __PRETTY_FUNCTION__)), "'" "bte_seq_arg_started(arg)" "' should be FALSE" ); } while (0); | ||||
232 | g_assert_true(bte_seq_arg_default(arg))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_50 ; if (bte_seq_arg_default(arg)) _g_boolean_var_50 = 1; else _g_boolean_var_50 = 0; _g_boolean_var_50; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 232, ((const char*) (__PRETTY_FUNCTION__ )), "'" "bte_seq_arg_default(arg)" "' should be TRUE"); } while (0); | ||||
233 | |||||
234 | bte_seq_arg_push(&arg, '1'); | ||||
235 | bte_seq_arg_push(&arg, '2'); | ||||
236 | bte_seq_arg_push(&arg, '3'); | ||||
237 | bte_seq_arg_finish(&arg); | ||||
238 | |||||
239 | g_assert_cmpint(bte_seq_arg_value(arg), ==, 123)do { gint64 __n1 = (bte_seq_arg_value(arg)), __n2 = (123); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0 ), "../src/parser-test.cc", 239, ((const char*) (__PRETTY_FUNCTION__ )), "bte_seq_arg_value(arg)" " " "==" " " "123", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
240 | g_assert_false(bte_seq_arg_default(arg))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_51 ; if (!(bte_seq_arg_default(arg))) _g_boolean_var_51 = 1; else _g_boolean_var_51 = 0; _g_boolean_var_51; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 240, ((const char*) ( __PRETTY_FUNCTION__)), "'" "bte_seq_arg_default(arg)" "' should be FALSE" ); } while (0); | ||||
241 | |||||
242 | /* Test max value */ | ||||
243 | arg = BTE_SEQ_ARG_INIT_DEFAULT(0); | ||||
244 | bte_seq_arg_push(&arg, '6'); | ||||
245 | bte_seq_arg_push(&arg, '5'); | ||||
246 | bte_seq_arg_push(&arg, '5'); | ||||
247 | bte_seq_arg_push(&arg, '3'); | ||||
248 | bte_seq_arg_push(&arg, '6'); | ||||
249 | bte_seq_arg_finish(&arg); | ||||
250 | |||||
251 | g_assert_cmpint(bte_seq_arg_value(arg), ==, 65535)do { gint64 __n1 = (bte_seq_arg_value(arg)), __n2 = (65535); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0 ), "../src/parser-test.cc", 251, ((const char*) (__PRETTY_FUNCTION__ )), "bte_seq_arg_value(arg)" " " "==" " " "65535", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
252 | } | ||||
253 | |||||
254 | static void | ||||
255 | test_seq_string(void) | ||||
256 | { | ||||
257 | bte_seq_string_t str; | ||||
258 | bte_seq_string_init(&str); | ||||
259 | |||||
260 | size_t len; | ||||
261 | auto buf = bte_seq_string_get(&str, &len); | ||||
262 | g_assert_cmpuint(len, ==, 0)do { guint64 __n1 = (len), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 262, ((const char*) (__PRETTY_FUNCTION__)), "len" " " "==" " " "0", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
263 | |||||
264 | for (unsigned int i = 0; i < BTE_SEQ_STRING_MAX_CAPACITY(1 << 12); ++i) { | ||||
265 | auto rv = bte_seq_string_push(&str, 0xfffdU); | ||||
266 | g_assert_true(rv)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_52 ; if (rv) _g_boolean_var_52 = 1; else _g_boolean_var_52 = 0; _g_boolean_var_52 ; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 266, ((const char*) (__PRETTY_FUNCTION__)), "'" "rv" "' should be TRUE" ); } while (0); | ||||
267 | |||||
268 | buf = bte_seq_string_get(&str, &len); | ||||
269 | g_assert_cmpuint(len, ==, i + 1)do { guint64 __n1 = (len), __n2 = (i + 1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 269, ((const char*) (__PRETTY_FUNCTION__)), "len" " " "==" " " "i + 1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
270 | } | ||||
271 | |||||
272 | /* Try one more */ | ||||
273 | auto rv = bte_seq_string_push(&str, 0xfffdU); | ||||
274 | g_assert_false(rv)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_53 ; if (!(rv)) _g_boolean_var_53 = 1; else _g_boolean_var_53 = 0 ; _g_boolean_var_53; }), 1)) ; else g_assertion_message (((gchar *) 0), "../src/parser-test.cc", 274, ((const char*) (__PRETTY_FUNCTION__ )), "'" "rv" "' should be FALSE"); } while (0); | ||||
275 | |||||
276 | buf = bte_seq_string_get(&str, &len); | ||||
277 | for (unsigned int i = 0; i < len; i++) | ||||
278 | g_assert_cmpuint(buf[i], ==, 0xfffdU)do { guint64 __n1 = (buf[i]), __n2 = (0xfffdU); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 278, ((const char*) (__PRETTY_FUNCTION__)), "buf[i]" " " "==" " " "0xfffdU", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
279 | |||||
280 | bte_seq_string_reset(&str); | ||||
281 | buf = bte_seq_string_get(&str, &len); | ||||
282 | g_assert_cmpuint(len, ==, 0)do { guint64 __n1 = (len), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 282, ((const char*) (__PRETTY_FUNCTION__)), "len" " " "==" " " "0", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
283 | |||||
284 | bte_seq_string_free(&str); | ||||
285 | } | ||||
286 | |||||
287 | static void | ||||
288 | test_seq_control(void) | ||||
289 | { | ||||
290 | static struct { | ||||
291 | uint32_t c; | ||||
292 | unsigned int cmd; | ||||
293 | } const controls [] = { | ||||
294 | #define _BTE_SEQ(cmd,type,f,pi,ni,i0) { f, BTE_CMD_##cmd }, | ||||
295 | #include "parser-c01.hh" | ||||
296 | #undef _BTE_SEQ | ||||
297 | }; | ||||
298 | |||||
299 | for (unsigned int i = 0; i < G_N_ELEMENTS(controls)(sizeof (controls) / sizeof ((controls)[0])); i++) { | ||||
300 | parser.reset(); | ||||
301 | auto rv = parser.feed(controls[i].c); | ||||
302 | g_assert_cmpuint(rv, ==, BTE_SEQ_CONTROL)do { guint64 __n1 = (rv), __n2 = (BTE_SEQ_CONTROL); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 302, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_CONTROL", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
303 | g_assert_cmpuint(controls[i].cmd, ==, seq.command())do { guint64 __n1 = (controls[i].cmd), __n2 = (seq.command()) ; if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 303, ((const char*) (__PRETTY_FUNCTION__ )), "controls[i].cmd" " " "==" " " "seq.command()", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
304 | } | ||||
305 | } | ||||
306 | |||||
307 | static void | ||||
308 | test_seq_esc_invalid(void) | ||||
309 | { | ||||
310 | /* Tests invalid ESC 0/n and ESC 1/n sequences, which should never result in | ||||
311 | * an BTE_SEQ_ESCAPE type sequence, but instead always in the C0 control. | ||||
312 | */ | ||||
313 | for (uint32_t f = 0x0; f < 0x20; f++) { | ||||
314 | parser.reset(); | ||||
315 | |||||
316 | bte_seq_builder b{BTE_SEQ_ESCAPE, f}; | ||||
317 | auto rv = feed_parser(b); | ||||
318 | g_assert_cmpint(rv, !=, BTE_SEQ_ESCAPE)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_ESCAPE); if (__n1 != __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 318, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "!=" " " "BTE_SEQ_ESCAPE", (long double) __n1, "!=", (long double) __n2 , 'i'); } while (0); | ||||
319 | } | ||||
320 | } | ||||
321 | |||||
322 | static void | ||||
323 | test_seq_esc(uint32_t f, | ||||
324 | uint32_t i[], | ||||
325 | unsigned int ni) | ||||
326 | { | ||||
327 | bte_seq_builder b{BTE_SEQ_ESCAPE, f}; | ||||
328 | b.set_intermediates(i, ni); | ||||
329 | |||||
330 | parser.reset(); | ||||
331 | auto rv = feed_parser(b); | ||||
332 | if (rv != BTE_SEQ_ESCAPE) | ||||
333 | return; | ||||
334 | |||||
335 | b.assert_equal(seq); | ||||
336 | } | ||||
337 | |||||
338 | static void | ||||
339 | test_seq_esc_nF(void) | ||||
340 | { | ||||
341 | /* Tests nF sequences, that is ESC 2/n [2/m..] F with F being 3/0..7/14. | ||||
342 | * They could have any number of itermediates, but we only test up to 4. | ||||
343 | */ | ||||
344 | |||||
345 | uint32_t i[4]; | ||||
346 | for (uint32_t f = 0x30; f < 0x7f; f++) { | ||||
347 | test_seq_esc(f, i, 0); | ||||
348 | for (i[0] = 0x20; i[0] < 0x30; i[0]++) { | ||||
349 | test_seq_esc(f, i, 1); | ||||
350 | for (i[1] = 0x20; i[1] < 0x30; i[1]++) { | ||||
351 | test_seq_esc(f, i, 2); | ||||
352 | for (i[2] = 0x20; i[2] < 0x30; i[2]++) { | ||||
353 | test_seq_esc(f, i, 3); | ||||
354 | for (i[3] = 0x20; i[3] < 0x30; i[3]++) { | ||||
355 | test_seq_esc(f, i, 4); | ||||
356 | } | ||||
357 | } | ||||
358 | } | ||||
359 | } | ||||
360 | } | ||||
361 | } | ||||
362 | |||||
363 | static void | ||||
364 | test_seq_esc_charset(uint32_t f, /* final */ | ||||
365 | uint32_t i[], /* intermediates */ | ||||
366 | unsigned int ni, /* number of intermediates */ | ||||
367 | unsigned int cmd, /* expected command */ | ||||
368 | unsigned int cs /* expected charset */, | ||||
369 | unsigned int slot /* expected slot */) | ||||
370 | { | ||||
371 | bte_seq_builder b{BTE_SEQ_ESCAPE, f}; | ||||
372 | b.set_intermediates(i, ni); | ||||
373 | |||||
374 | parser.reset(); | ||||
375 | auto rv = feed_parser(b); | ||||
376 | g_assert_cmpint(rv, ==, BTE_SEQ_ESCAPE)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_ESCAPE); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 376, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_ESCAPE", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
377 | b.assert_equal(seq); | ||||
378 | |||||
379 | g_assert_cmpint(seq.command(), ==, cmd)do { gint64 __n1 = (seq.command()), __n2 = (cmd); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 379, ((const char*) (__PRETTY_FUNCTION__)), "seq.command()" " " "==" " " "cmd", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
380 | g_assert_cmpint(seq.charset(), ==, cs)do { gint64 __n1 = (seq.charset()), __n2 = (cs); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 380, ((const char*) (__PRETTY_FUNCTION__)), "seq.charset()" " " "==" " " "cs", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
381 | g_assert_cmpint(seq.slot(), ==, slot)do { gint64 __n1 = (seq.slot()), __n2 = (slot); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 381, ((const char*) (__PRETTY_FUNCTION__)), "seq.slot()" " " "==" " " "slot", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
382 | } | ||||
383 | |||||
384 | static void | ||||
385 | test_seq_esc_charset(uint32_t i[], /* intermediates */ | ||||
386 | unsigned int ni, /* number of intermediates */ | ||||
387 | uint8_t const* const table, /* table */ | ||||
388 | unsigned int ntable, /* number of table entries */ | ||||
389 | uint32_t ts, /* start of table */ | ||||
390 | unsigned int cmd, /* expected command */ | ||||
391 | unsigned int defaultcs /* default charset */, | ||||
392 | unsigned int slot /* expected slot */) | ||||
393 | { | ||||
394 | for (uint32_t f = 0x30; f < 0x7f; f++) { | ||||
395 | int cs; | ||||
396 | |||||
397 | if (f >= ts && f < (ts + ntable)) | ||||
398 | cs = table[f - ts]; | ||||
399 | else | ||||
400 | cs = defaultcs; | ||||
401 | |||||
402 | test_seq_esc_charset(f, i, ni, cmd, cs, slot); | ||||
403 | } | ||||
404 | } | ||||
405 | |||||
406 | static void | ||||
407 | test_seq_esc_charset_94(void) | ||||
408 | { | ||||
409 | uint32_t i[4]; | ||||
410 | |||||
411 | /* Single byte 94-sets */ | ||||
412 | for (i[0] = 0x28; i[0] <= 0x2b; i[0]++) { | ||||
413 | int slot = i[0] - 0x28; | ||||
414 | |||||
415 | test_seq_esc_charset(i, 1, | ||||
416 | charset_graphic_94, | ||||
417 | G_N_ELEMENTS(charset_graphic_94)(sizeof (charset_graphic_94) / sizeof ((charset_graphic_94)[0 ])), | ||||
418 | 0x30, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
419 | |||||
420 | i[1] = 0x20; | ||||
421 | test_seq_esc_charset(i, 2, nullptr, 0, 0, | ||||
422 | BTE_CMD_GnDm, BTE_CHARSET_DRCS, slot); | ||||
423 | |||||
424 | i[1] = 0x21; | ||||
425 | test_seq_esc_charset(i, 2, | ||||
426 | charset_graphic_94_with_2_1, | ||||
427 | G_N_ELEMENTS(charset_graphic_94_with_2_1)(sizeof (charset_graphic_94_with_2_1) / sizeof ((charset_graphic_94_with_2_1 )[0])), | ||||
428 | 0x40, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
429 | |||||
430 | i[1] = 0x22; | ||||
431 | test_seq_esc_charset(i, 2, | ||||
432 | charset_graphic_94_with_2_2, | ||||
433 | G_N_ELEMENTS(charset_graphic_94_with_2_2)(sizeof (charset_graphic_94_with_2_2) / sizeof ((charset_graphic_94_with_2_2 )[0])), | ||||
434 | 0x30, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
435 | |||||
436 | i[1] = 0x23; | ||||
437 | test_seq_esc_charset(i, 2, nullptr, 0, | ||||
438 | 0x30, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
439 | |||||
440 | /* 2/4 is multibyte charsets */ | ||||
441 | |||||
442 | i[1] = 0x25; | ||||
443 | test_seq_esc_charset(i, 2, | ||||
444 | charset_graphic_94_with_2_5, | ||||
445 | G_N_ELEMENTS(charset_graphic_94_with_2_5)(sizeof (charset_graphic_94_with_2_5) / sizeof ((charset_graphic_94_with_2_5 )[0])), | ||||
446 | 0x30, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
447 | |||||
448 | i[1] = 0x26; | ||||
449 | test_seq_esc_charset(i, 2, | ||||
450 | charset_graphic_94_with_2_6, | ||||
451 | G_N_ELEMENTS(charset_graphic_94_with_2_6)(sizeof (charset_graphic_94_with_2_6) / sizeof ((charset_graphic_94_with_2_6 )[0])), | ||||
452 | 0x30, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
453 | |||||
454 | i[1] = 0x27; | ||||
455 | test_seq_esc_charset(i, 2, nullptr, 0, 0, | ||||
456 | BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
457 | } | ||||
458 | } | ||||
459 | |||||
460 | static void | ||||
461 | test_seq_esc_charset_96(void) | ||||
462 | { | ||||
463 | uint32_t i[4]; | ||||
464 | |||||
465 | /* Single byte 96-sets */ | ||||
466 | for (i[0] = 0x2d; i[0] <= 0x2f; i[0]++) { | ||||
467 | int slot = i[0] - 0x2c; | ||||
468 | |||||
469 | test_seq_esc_charset(i, 1, | ||||
470 | charset_graphic_96, | ||||
471 | G_N_ELEMENTS(charset_graphic_96)(sizeof (charset_graphic_96) / sizeof ((charset_graphic_96)[0 ])), | ||||
472 | 0x30, BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
473 | |||||
474 | i[1] = 0x20; | ||||
475 | test_seq_esc_charset(i, 2, nullptr, 0, 0, | ||||
476 | BTE_CMD_GnDm, BTE_CHARSET_DRCS, slot); | ||||
477 | |||||
478 | /* 2/4 is multibyte charsets, 2/5 is DOCS. Other indermediates may be present | ||||
479 | * in Fp sequences, but none are actually in use. | ||||
480 | */ | ||||
481 | for (i[1] = 0x21; i[1] < 0x28; i[1]++) { | ||||
482 | if (i[1] == 0x24 || i[1] == 0x25) | ||||
483 | continue; | ||||
484 | |||||
485 | test_seq_esc_charset(i, 2, nullptr, 0, 0, | ||||
486 | BTE_CMD_GnDm, BTE_CHARSET_NONE, slot); | ||||
487 | } | ||||
488 | } | ||||
489 | } | ||||
490 | |||||
491 | static void | ||||
492 | test_seq_esc_charset_94_n(void) | ||||
493 | { | ||||
494 | uint32_t i[4]; | ||||
495 | |||||
496 | /* Multibyte 94-sets */ | ||||
497 | i[0] = 0x24; | ||||
498 | for (i[1] = 0x28; i[1] <= 0x2b; i[1]++) { | ||||
499 | int slot = i[1] - 0x28; | ||||
500 | |||||
501 | test_seq_esc_charset(i, 2, | ||||
502 | charset_graphic_94_n, | ||||
503 | G_N_ELEMENTS(charset_graphic_94_n)(sizeof (charset_graphic_94_n) / sizeof ((charset_graphic_94_n )[0])), | ||||
504 | 0x30, BTE_CMD_GnDMm, BTE_CHARSET_NONE, slot); | ||||
505 | |||||
506 | i[2] = 0x20; | ||||
507 | test_seq_esc_charset(i, 3, nullptr, 0, 0, | ||||
508 | BTE_CMD_GnDMm, BTE_CHARSET_DRCS, slot); | ||||
509 | |||||
510 | /* There could be one more intermediate byte. */ | ||||
511 | for (i[2] = 0x21; i[2] < 0x28; i[2]++) { | ||||
512 | if (i[2] == 0x24) /* TODO */ | ||||
513 | continue; | ||||
514 | |||||
515 | test_seq_esc_charset(i, 3, nullptr, 0, 0, | ||||
516 | BTE_CMD_GnDMm, BTE_CHARSET_NONE, slot); | ||||
517 | } | ||||
518 | } | ||||
519 | |||||
520 | /* As a special exception, ESC 2/4 4/[012] are also possible */ | ||||
521 | test_seq_esc_charset(0x40, i, 1, BTE_CMD_GnDMm, charset_graphic_94_n[0x40 - 0x30], 0); | ||||
522 | test_seq_esc_charset(0x41, i, 1, BTE_CMD_GnDMm, charset_graphic_94_n[0x41 - 0x30], 0); | ||||
523 | test_seq_esc_charset(0x42, i, 1, BTE_CMD_GnDMm, charset_graphic_94_n[0x42 - 0x30], 0); | ||||
524 | } | ||||
525 | |||||
526 | static void | ||||
527 | test_seq_esc_charset_96_n(void) | ||||
528 | { | ||||
529 | uint32_t i[4]; | ||||
530 | |||||
531 | /* Multibyte 94-sets */ | ||||
532 | i[0] = 0x24; | ||||
533 | for (i[1] = 0x2d; i[1] <= 0x2f; i[1]++) { | ||||
534 | int slot = i[1] - 0x2c; | ||||
535 | |||||
536 | test_seq_esc_charset(i, 2, nullptr, 0, 0, | ||||
537 | BTE_CMD_GnDMm, BTE_CHARSET_NONE, slot); | ||||
538 | |||||
539 | i[2] = 0x20; | ||||
540 | test_seq_esc_charset(i, 3, nullptr, 0, 0, | ||||
541 | BTE_CMD_GnDMm, BTE_CHARSET_DRCS, slot); | ||||
542 | |||||
543 | /* There could be one more intermediate byte. */ | ||||
544 | for (i[2] = 0x21; i[2] < 0x28; i[2]++) { | ||||
545 | test_seq_esc_charset(i, 3, nullptr, 0, 0, | ||||
546 | BTE_CMD_GnDMm, BTE_CHARSET_NONE, slot); | ||||
547 | } | ||||
548 | } | ||||
549 | } | ||||
550 | |||||
551 | static void | ||||
552 | test_seq_esc_charset_control(void) | ||||
553 | { | ||||
554 | uint32_t i[4]; | ||||
555 | |||||
556 | /* C0 controls: ESC 2/1 F */ | ||||
557 | i[0] = 0x21; | ||||
558 | test_seq_esc_charset(i, 1, | ||||
559 | charset_control_c0, | ||||
560 | G_N_ELEMENTS(charset_control_c0)(sizeof (charset_control_c0) / sizeof ((charset_control_c0)[0 ])), | ||||
561 | 0x40, BTE_CMD_CnD, BTE_CHARSET_NONE, 0); | ||||
562 | |||||
563 | /* C1 controls: ESC 2/2 F */ | ||||
564 | i[0] = 0x22; | ||||
565 | test_seq_esc_charset(i, 1, | ||||
566 | charset_control_c1, | ||||
567 | G_N_ELEMENTS(charset_control_c1)(sizeof (charset_control_c1) / sizeof ((charset_control_c1)[0 ])), | ||||
568 | 0x40, BTE_CMD_CnD, BTE_CHARSET_NONE, 1); | ||||
569 | } | ||||
570 | |||||
571 | static void | ||||
572 | test_seq_esc_charset_other(void) | ||||
573 | { | ||||
574 | uint32_t i[4]; | ||||
575 | |||||
576 | /* Other coding systems: ESC 2/5 F or ESC 2/5 I F */ | ||||
577 | i[0] = 0x25; | ||||
578 | test_seq_esc_charset(i, 1, | ||||
579 | charset_ocs, | ||||
580 | G_N_ELEMENTS(charset_ocs)(sizeof (charset_ocs) / sizeof ((charset_ocs)[0])), | ||||
581 | 0x30, BTE_CMD_DOCS, BTE_CHARSET_NONE, 0); | ||||
582 | |||||
583 | i[1] = 0x20; | ||||
584 | test_seq_esc_charset(i, 2, | ||||
585 | charset_ocs_with_2_0, | ||||
586 | G_N_ELEMENTS(charset_ocs_with_2_0)(sizeof (charset_ocs_with_2_0) / sizeof ((charset_ocs_with_2_0 )[0])), | ||||
587 | 0x30, BTE_CMD_DOCS, BTE_CHARSET_NONE, 0); | ||||
588 | |||||
589 | i[1] = 0x2f; | ||||
590 | test_seq_esc_charset(i, 2, | ||||
591 | charset_ocs_with_2_15, | ||||
592 | G_N_ELEMENTS(charset_ocs_with_2_15)(sizeof (charset_ocs_with_2_15) / sizeof ((charset_ocs_with_2_15 )[0])), | ||||
593 | 0x40, BTE_CMD_DOCS, BTE_CHARSET_NONE, 0); | ||||
594 | } | ||||
595 | |||||
596 | static void | ||||
597 | test_seq_esc_Fpes(void) | ||||
598 | { | ||||
599 | /* Tests Fp, Fe and Ft sequences, that is ESC 3/n .. ESC 7/14 */ | ||||
600 | |||||
601 | for (uint32_t f = 0x30; f < 0x7f; f++) { | ||||
602 | parser.reset(); | ||||
603 | |||||
604 | bte_seq_builder b{BTE_SEQ_ESCAPE, f}; | ||||
605 | |||||
606 | auto rv = feed_parser(b); | ||||
607 | int expected_rv; | ||||
608 | switch (f) { | ||||
609 | case 'P': /* DCS */ | ||||
610 | case 'X': /* SOS */ | ||||
611 | case 'Z': /* SCI */ | ||||
612 | case '_': /* APC */ | ||||
613 | case '[': /* CSI */ | ||||
614 | case ']': /* OSC */ | ||||
615 | case '^': /* PM */ | ||||
616 | expected_rv = BTE_SEQ_NONE; | ||||
617 | break; | ||||
618 | default: | ||||
619 | expected_rv = BTE_SEQ_ESCAPE; | ||||
620 | break; | ||||
621 | } | ||||
622 | g_assert_cmpint(rv, ==, expected_rv)do { gint64 __n1 = (rv), __n2 = (expected_rv); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 622, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "expected_rv", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
623 | if (rv != BTE_SEQ_NONE) | ||||
624 | b.assert_equal(seq); | ||||
625 | } | ||||
626 | } | ||||
627 | |||||
628 | static void | ||||
629 | test_seq_esc_known(uint32_t f, | ||||
630 | uint32_t i, | ||||
631 | unsigned int cmd) | ||||
632 | { | ||||
633 | bte_seq_builder b{BTE_SEQ_ESCAPE, f}; | ||||
634 | if (i != 0) | ||||
635 | b.set_intermediates(&i, 1); | ||||
636 | |||||
637 | auto rv = feed_parser(b); | ||||
638 | g_assert_cmpint(rv, ==, BTE_SEQ_ESCAPE)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_ESCAPE); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 638, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_ESCAPE", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
639 | g_assert_cmpint(seq.command(), ==, cmd)do { gint64 __n1 = (seq.command()), __n2 = (cmd); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 639, ((const char*) (__PRETTY_FUNCTION__)), "seq.command()" " " "==" " " "cmd", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
640 | } | ||||
641 | |||||
642 | static void | ||||
643 | test_seq_esc_known(void) | ||||
644 | { | ||||
645 | parser.reset(); | ||||
646 | |||||
647 | #define _BTE_SEQ(cmd,type,f,p,ni,i) \ | ||||
648 | test_seq_esc_known(f, BTE_SEQ_INTERMEDIATE_CHAR_##i, BTE_CMD_##cmd); | ||||
649 | #include "parser-esc.hh" | ||||
650 | #undef _BTE_SEQ | ||||
651 | } | ||||
652 | |||||
653 | static void | ||||
654 | test_seq_csi(uint32_t f, | ||||
655 | uint32_t p, | ||||
656 | bte_seq_arg_t params[16], | ||||
657 | uint32_t i[4], | ||||
658 | unsigned int ni) | ||||
659 | { | ||||
660 | bte_seq_builder b{BTE_SEQ_CSI, f}; | ||||
661 | b.set_intermediates(i, ni); | ||||
662 | b.set_param_intro(p); | ||||
663 | |||||
664 | int expected_rv = (f & 0xF0) == 0x30 ? BTE_SEQ_NONE : BTE_SEQ_CSI; | ||||
665 | |||||
666 | for (unsigned int n = 0; n <= 16; n++) { | ||||
667 | b.reset_params(); | ||||
668 | b.set_params(params, n); | ||||
669 | |||||
670 | parser.reset(); | ||||
671 | /* First with C0 CSI */ | ||||
672 | auto rv = feed_parser(b, false); | ||||
673 | g_assert_cmpint(rv, ==, expected_rv)do { gint64 __n1 = (rv), __n2 = (expected_rv); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 673, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "expected_rv", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
674 | if (rv
| ||||
675 | b.assert_equal_full(seq); | ||||
676 | |||||
677 | /* Now with C1 CSI */ | ||||
678 | rv = feed_parser(b, true); | ||||
679 | if (rv != BTE_SEQ_NONE) | ||||
680 | b.assert_equal_full(seq); | ||||
681 | } | ||||
682 | } | ||||
683 | |||||
684 | static void | ||||
685 | test_seq_csi(uint32_t p, | ||||
686 | bte_seq_arg_t params[16]) | ||||
687 | { | ||||
688 | uint32_t i[4]; | ||||
689 | for (uint32_t f = 0x30; f < 0x7f; f++) { | ||||
690 | test_seq_csi(f, p, params, i, 0); | ||||
691 | for (i[0] = 0x20; i[0] < 0x30; i[0]++) { | ||||
692 | test_seq_csi(f, p, params, i, 1); | ||||
693 | for (i[1] = 0x20; i[1] < 0x30; i[1]++) { | ||||
694 | test_seq_csi(f, p, params, i, 2); | ||||
695 | } | ||||
696 | } | ||||
697 | } | ||||
698 | } | ||||
699 | |||||
700 | static void | ||||
701 | test_seq_csi(bte_seq_arg_t params[16]) | ||||
702 | { | ||||
703 | test_seq_csi(0, params); | ||||
704 | for (uint32_t p = 0x3c; p <= 0x3f; p++) | ||||
705 | test_seq_csi(p, params); | ||||
706 | } | ||||
707 | |||||
708 | static void | ||||
709 | test_seq_csi(void) | ||||
710 | { | ||||
711 | /* Tests CSI sequences, that is sequences of the form | ||||
712 | * CSI P...P I...I F | ||||
713 | * with parameter bytes P from 3/0..3/15, intermediate bytes I from 2/0..2/15 and | ||||
714 | * final byte F from 4/0..7/14. | ||||
715 | * There could be any number of intermediate bytes, but we only test up to 2. | ||||
716 | * There could be any number of extra params bytes, but we only test up to 1. | ||||
717 | * CSI can be either the C1 control itself, or ESC [ | ||||
718 | */ | ||||
719 | bte_seq_arg_t params1[16]{ -1, 0, 1, 9, 10, 99, 100, 999, | ||||
720 | 1000, 9999, 10000, 65534, 65535, 65536, -1, -1 }; | ||||
721 | test_seq_csi(params1); | ||||
| |||||
722 | |||||
723 | bte_seq_arg_t params2[16]{ 1, -1, -1, -1, 1, -1, 1, 1, | ||||
724 | 1, -1, -1, -1, -1, 1, 1, 1 }; | ||||
725 | test_seq_csi(params2); | ||||
726 | } | ||||
727 | |||||
728 | static void | ||||
729 | test_seq_sci(uint32_t f, | ||||
730 | bool valid) | ||||
731 | { | ||||
732 | bte_seq_builder b{BTE_SEQ_SCI, f}; | ||||
733 | |||||
734 | /* First with C0 SCI */ | ||||
735 | auto rv = feed_parser(b, false); | ||||
736 | if (valid) { | ||||
737 | g_assert_cmpint(rv, ==, BTE_SEQ_SCI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_SCI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 737, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_SCI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
738 | b.assert_equal_full(seq); | ||||
739 | } else | ||||
740 | g_assert_cmpint(rv, !=, BTE_SEQ_SCI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_SCI); if (__n1 != __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 740, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "!=" " " "BTE_SEQ_SCI", (long double) __n1, "!=", (long double) __n2, 'i'); } while (0); | ||||
741 | |||||
742 | /* Now with C1 SCI */ | ||||
743 | rv = feed_parser(b, true); | ||||
744 | if (valid) { | ||||
745 | g_assert_cmpint(rv, ==, BTE_SEQ_SCI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_SCI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 745, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_SCI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
746 | b.assert_equal_full(seq); | ||||
747 | } else | ||||
748 | g_assert_cmpint(rv, !=, BTE_SEQ_SCI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_SCI); if (__n1 != __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 748, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "!=" " " "BTE_SEQ_SCI", (long double) __n1, "!=", (long double) __n2, 'i'); } while (0); | ||||
749 | } | ||||
750 | |||||
751 | static void | ||||
752 | test_seq_sci(void) | ||||
753 | { | ||||
754 | /* Tests SCI sequences, that is sequences of the form SCI F | ||||
755 | * with final byte 0/8..0/13 or 2/0..7/14 | ||||
756 | * SCI can be either the C1 control itself, or ESC Z | ||||
757 | */ | ||||
758 | parser.reset(); | ||||
759 | |||||
760 | for (uint32_t f = 0x8; f <= 0xd; ++f) | ||||
761 | test_seq_sci(f, true); | ||||
762 | for (uint32_t f = 0x20; f <= 0x7e; ++f) | ||||
763 | test_seq_sci(f, true); | ||||
764 | for (uint32_t f = 0x7f; f <= 0xff; ++f) | ||||
765 | test_seq_sci(f, false); | ||||
766 | } | ||||
767 | |||||
768 | G_GNUC_UNUSED__attribute__ ((__unused__)) | ||||
769 | static void | ||||
770 | test_seq_sci_known(uint32_t f, | ||||
771 | unsigned int cmd) | ||||
772 | { | ||||
773 | bte_seq_builder b{BTE_SEQ_SCI, f}; | ||||
774 | |||||
775 | auto rv = feed_parser(b); | ||||
776 | g_assert_cmpint(rv, ==, BTE_SEQ_SCI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_SCI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 776, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_SCI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
777 | g_assert_cmpint(seq.command(), ==, cmd)do { gint64 __n1 = (seq.command()), __n2 = (cmd); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 777, ((const char*) (__PRETTY_FUNCTION__)), "seq.command()" " " "==" " " "cmd", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
778 | } | ||||
779 | |||||
780 | static void | ||||
781 | test_seq_sci_known(void) | ||||
782 | { | ||||
783 | parser.reset(); | ||||
784 | |||||
785 | #define _BTE_SEQ(cmd,type,f,p,ni,i) \ | ||||
786 | test_seq_sci_known(f, BTE_CMD_##cmd); | ||||
787 | #include "parser-sci.hh" | ||||
788 | #undef _BTE_SEQ | ||||
789 | } | ||||
790 | |||||
791 | static void | ||||
792 | test_seq_csi_known(uint32_t f, | ||||
793 | uint32_t p, | ||||
794 | uint32_t i, | ||||
795 | unsigned int cmd) | ||||
796 | { | ||||
797 | bte_seq_builder b{BTE_SEQ_CSI, f}; | ||||
798 | if (p != 0) | ||||
799 | b.set_param_intro(p); | ||||
800 | if (i != 0) | ||||
801 | b.set_intermediates(&i, 1); | ||||
802 | |||||
803 | auto rv = feed_parser(b); | ||||
804 | g_assert_cmpint(rv, ==, BTE_SEQ_CSI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_CSI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 804, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_CSI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
805 | g_assert_cmpint(seq.command(), ==, cmd)do { gint64 __n1 = (seq.command()), __n2 = (cmd); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 805, ((const char*) (__PRETTY_FUNCTION__)), "seq.command()" " " "==" " " "cmd", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
806 | } | ||||
807 | |||||
808 | static void | ||||
809 | test_seq_csi_known(void) | ||||
810 | { | ||||
811 | parser.reset(); | ||||
812 | |||||
813 | #define _BTE_SEQ(cmd,type,f,p,ni,i) \ | ||||
814 | test_seq_csi_known(f, BTE_SEQ_PARAMETER_CHAR_##p, BTE_SEQ_INTERMEDIATE_CHAR_##i, BTE_CMD_##cmd); | ||||
815 | #include "parser-csi.hh" | ||||
816 | #undef _BTE_SEQ | ||||
817 | } | ||||
818 | |||||
819 | static void | ||||
820 | test_seq_dcs(uint32_t f, | ||||
821 | uint32_t p, | ||||
822 | bte_seq_arg_t params[16], | ||||
823 | uint32_t i[4], | ||||
824 | unsigned int ni, | ||||
825 | std::u32string const& str, | ||||
826 | int expected_rv = BTE_SEQ_DCS) | ||||
827 | { | ||||
828 | bte_seq_builder b{BTE_SEQ_DCS, f}; | ||||
829 | b.set_intermediates(i, ni); | ||||
830 | b.set_param_intro(p); | ||||
831 | b.set_string(str); | ||||
832 | |||||
833 | int expected_rv0 = (f & 0xF0) == 0x30 || expected_rv == BTE_SEQ_NONE ? BTE_SEQ_ESCAPE /* the C0 ST */ : expected_rv; | ||||
834 | int expected_rv1 = (f & 0xF0) == 0x30 ? BTE_SEQ_NONE : expected_rv; | ||||
835 | |||||
836 | for (unsigned int n = 0; n <= 16; n++) { | ||||
837 | b.reset_params(); | ||||
838 | b.set_params(params, n); | ||||
839 | |||||
840 | parser.reset(); | ||||
841 | |||||
842 | /* First with C0 DCS */ | ||||
843 | auto rv0 = feed_parser(b, false); | ||||
844 | g_assert_cmpint(rv0, ==, expected_rv0)do { gint64 __n1 = (rv0), __n2 = (expected_rv0); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 844, ((const char*) (__PRETTY_FUNCTION__)), "rv0" " " "==" " " "expected_rv0", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
845 | if (rv0 != BTE_SEQ_ESCAPE && rv0 != BTE_SEQ_NONE) | ||||
846 | b.assert_equal_full(seq); | ||||
847 | if (rv0 == BTE_SEQ_ESCAPE) | ||||
848 | g_assert_cmpint(seq.command(), ==, BTE_CMD_ST)do { gint64 __n1 = (seq.command()), __n2 = (BTE_CMD_ST); if ( __n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0) , "../src/parser-test.cc", 848, ((const char*) (__PRETTY_FUNCTION__ )), "seq.command()" " " "==" " " "BTE_CMD_ST", (long double) __n1 , "==", (long double) __n2, 'i'); } while (0); | ||||
849 | |||||
850 | /* Now with C1 DCS */ | ||||
851 | auto rv1 = feed_parser(b, true); | ||||
852 | g_assert_cmpint(rv1, ==, expected_rv1)do { gint64 __n1 = (rv1), __n2 = (expected_rv1); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 852, ((const char*) (__PRETTY_FUNCTION__)), "rv1" " " "==" " " "expected_rv1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
853 | if (rv1 != BTE_SEQ_NONE) | ||||
854 | b.assert_equal_full(seq); | ||||
855 | } | ||||
856 | } | ||||
857 | |||||
858 | static void | ||||
859 | test_seq_dcs(uint32_t p, | ||||
860 | bte_seq_arg_t params[16], | ||||
861 | std::u32string const& str, | ||||
862 | int expected_rv = BTE_SEQ_DCS) | ||||
863 | { | ||||
864 | uint32_t i[4]; | ||||
865 | for (uint32_t f = 0x40; f < 0x7f; f++) { | ||||
866 | test_seq_dcs(f, p, params, i, 0, str, expected_rv); | ||||
867 | } | ||||
868 | |||||
869 | for (uint32_t f = 0x30; f < 0x7f; f++) { | ||||
870 | for (i[0] = 0x20; i[0] < 0x30; i[0]++) { | ||||
871 | test_seq_dcs(f, p, params, i, 1, str, expected_rv); | ||||
872 | for (i[1] = 0x20; i[1] < 0x30; i[1]++) { | ||||
873 | test_seq_dcs(f, p, params, i, 2, str, expected_rv); | ||||
874 | } | ||||
875 | } | ||||
876 | } | ||||
877 | } | ||||
878 | |||||
879 | static void | ||||
880 | test_seq_dcs(bte_seq_arg_t params[16], | ||||
881 | std::u32string const& str, | ||||
882 | int expected_rv = BTE_SEQ_DCS) | ||||
883 | { | ||||
884 | test_seq_dcs(0, params, str); | ||||
885 | for (uint32_t p = 0x3c; p <= 0x3f; p++) | ||||
886 | test_seq_dcs(p, params, str, expected_rv); | ||||
887 | } | ||||
888 | |||||
889 | static void | ||||
890 | test_seq_dcs(std::u32string const& str, | ||||
891 | int expected_rv = BTE_SEQ_DCS) | ||||
892 | { | ||||
893 | /* Tests DCS sequences, that is sequences of the form | ||||
894 | * DCS P...P I...I F D...D ST | ||||
895 | * with parameter bytes P from 3/0..3/15, intermediate bytes I from 2/0..2/15 and | ||||
896 | * final byte F from 4/0..7/14. | ||||
897 | * There could be any number of intermediate bytes, but we only test up to 2. | ||||
898 | * There could be any number of extra params bytes, but we only test up to 1. | ||||
899 | * DCS can be either the C1 control itself, or ESC [; ST can be either the C1 | ||||
900 | * control itself, or ESC \\ | ||||
901 | */ | ||||
902 | bte_seq_arg_t params1[16]{ -1, 0, 1, 9, 10, 99, 100, 999, | ||||
903 | 1000, 9999, 10000, 65534, 65535, 65536, -1, -1 }; | ||||
904 | test_seq_dcs(params1, str, expected_rv); | ||||
905 | |||||
906 | bte_seq_arg_t params2[16]{ 1, -1, -1, -1, 1, -1, 1, 1, | ||||
907 | 1, -1, -1, -1, -1, 1, 1, 1 }; | ||||
908 | test_seq_dcs(params2, str, expected_rv); | ||||
909 | } | ||||
910 | |||||
911 | static void | ||||
912 | test_seq_dcs_simple(std::u32string const& str, | ||||
913 | int expected_rv = BTE_SEQ_DCS) | ||||
914 | { | ||||
915 | bte_seq_arg_t params[16]{ 1, -1, -1, -1, 1, -1, 1, 1, | ||||
916 | 1, -1, -1, -1, -1, 1, 1, 1 }; | ||||
917 | uint32_t i[4]; | ||||
918 | |||||
919 | test_seq_dcs(0x40, 0, params, i, 0, str, expected_rv); | ||||
920 | } | ||||
921 | |||||
922 | static void | ||||
923 | test_seq_dcs(void) | ||||
924 | { | ||||
925 | /* Length exceeded */ | ||||
926 | test_seq_dcs_simple(std::u32string(BTE_SEQ_STRING_MAX_CAPACITY(1 << 12) + 1, 0x100000), BTE_SEQ_NONE); | ||||
927 | |||||
928 | test_seq_dcs(U""s); | ||||
929 | test_seq_dcs(U"123;TESTING"s); | ||||
930 | } | ||||
931 | |||||
932 | static void | ||||
933 | test_seq_dcs_known(uint32_t f, | ||||
934 | uint32_t p, | ||||
935 | uint32_t i, | ||||
936 | unsigned int cmd) | ||||
937 | { | ||||
938 | bte_seq_builder b{BTE_SEQ_DCS, f}; | ||||
939 | if (p != 0) | ||||
940 | b.set_param_intro(p); | ||||
941 | if (i != 0) | ||||
942 | b.set_intermediates(&i, 1); | ||||
943 | |||||
944 | auto rv = feed_parser(b); | ||||
945 | g_assert_cmpint(rv, ==, BTE_SEQ_DCS)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_DCS); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 945, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_DCS", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
946 | g_assert_cmpint(seq.command(), ==, cmd)do { gint64 __n1 = (seq.command()), __n2 = (cmd); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 946, ((const char*) (__PRETTY_FUNCTION__)), "seq.command()" " " "==" " " "cmd", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
947 | } | ||||
948 | |||||
949 | static void | ||||
950 | test_seq_dcs_known(void) | ||||
951 | { | ||||
952 | parser.reset(); | ||||
953 | |||||
954 | #define _BTE_SEQ(cmd,type,f,p,ni,i) \ | ||||
955 | test_seq_dcs_known(f, BTE_SEQ_PARAMETER_CHAR_##p, BTE_SEQ_INTERMEDIATE_CHAR_##i, BTE_CMD_##cmd); | ||||
956 | #include "parser-dcs.hh" | ||||
957 | #undef _BTE_SEQ | ||||
958 | } | ||||
959 | |||||
960 | static void | ||||
961 | test_seq_parse(char const* str) | ||||
962 | { | ||||
963 | std::u32string s; | ||||
964 | s.push_back(0x9B); /* CSI */ | ||||
965 | for (unsigned int i = 0; str[i]; i++) | ||||
966 | s.push_back(str[i]); | ||||
967 | s.push_back(0x6d); /* m = SGR */ | ||||
968 | |||||
969 | parser.reset(); | ||||
970 | auto rv = feed_parser(s); | ||||
971 | g_assert_cmpint(rv, ==, BTE_SEQ_CSI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_CSI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 971, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_CSI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
972 | } | ||||
973 | |||||
974 | static void | ||||
975 | test_seq_csi_param(char const* str, | ||||
976 | std::vector<int> args, | ||||
977 | std::vector<bool> args_nonfinal) | ||||
978 | { | ||||
979 | g_assert_cmpuint(args.size(), ==, args_nonfinal.size())do { guint64 __n1 = (args.size()), __n2 = (args_nonfinal.size ()); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 979, ((const char*) (__PRETTY_FUNCTION__ )), "args.size()" " " "==" " " "args_nonfinal.size()", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
980 | |||||
981 | test_seq_parse(str); | ||||
982 | |||||
983 | if (seq.size() < BTE_PARSER_ARG_MAX(32)) | ||||
984 | g_assert_cmpuint(seq.size(), ==, args.size())do { guint64 __n1 = (seq.size()), __n2 = (args.size()); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 984, ((const char*) (__PRETTY_FUNCTION__)), "seq.size()" " " "==" " " "args.size()", (long double) __n1, "==", (long double ) __n2, 'i'); } while (0); | ||||
985 | |||||
986 | unsigned int n_final_args = 0; | ||||
987 | for (unsigned int i = 0; i < seq.size(); i++) { | ||||
988 | g_assert_cmpint(seq.param(i), ==, args[i])do { gint64 __n1 = (seq.param(i)), __n2 = (args[i]); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 988, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(i)" " " "==" " " "args[i]", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
989 | |||||
990 | auto is_nonfinal = args_nonfinal[i]; | ||||
991 | if (!is_nonfinal) | ||||
992 | n_final_args++; | ||||
993 | |||||
994 | g_assert_cmpint(seq.param_nonfinal(i), ==, is_nonfinal)do { gint64 __n1 = (seq.param_nonfinal(i)), __n2 = (is_nonfinal ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 994, ((const char*) (__PRETTY_FUNCTION__ )), "seq.param_nonfinal(i)" " " "==" " " "is_nonfinal", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
995 | } | ||||
996 | |||||
997 | g_assert_cmpuint(seq.size_final(), ==, n_final_args)do { guint64 __n1 = (seq.size_final()), __n2 = (n_final_args) ; if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 997, ((const char*) (__PRETTY_FUNCTION__ )), "seq.size_final()" " " "==" " " "n_final_args", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
998 | } | ||||
999 | |||||
1000 | static void | ||||
1001 | test_seq_csi_param(void) | ||||
1002 | { | ||||
1003 | /* Tests that CSI parameters and subparameters are parsed correctly. */ | ||||
1004 | |||||
1005 | test_seq_csi_param("", { }, { }); | ||||
1006 | test_seq_csi_param(";", { -1, -1 }, { false, false }); | ||||
1007 | test_seq_csi_param(":", { -1, -1 }, { true, false }); | ||||
1008 | test_seq_csi_param(";:", { -1, -1, -1 }, { false, true, false }); | ||||
1009 | test_seq_csi_param("::;;", { -1, -1, -1, -1, -1 }, { true, true, false, false, false }); | ||||
1010 | |||||
1011 | test_seq_csi_param("1;2:3:4:5:6;7:8;9:0", | ||||
1012 | { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, | ||||
1013 | { false, true, true, true, true, false, true, false, true, false }); | ||||
1014 | |||||
1015 | test_seq_csi_param("1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1", | ||||
1016 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||||
1017 | { false, false, false, false, false, false, false, false, | ||||
1018 | false, false, false, false, false, false, false, false }); | ||||
1019 | |||||
1020 | test_seq_csi_param("1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", | ||||
1021 | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||||
1022 | { true, true, true, true, true, true, true, true, | ||||
1023 | true, true, true, true, true, true, true, false }); | ||||
1024 | |||||
1025 | } | ||||
1026 | |||||
1027 | static void | ||||
1028 | test_seq_csi_clear(void) | ||||
1029 | { | ||||
1030 | /* Check that parameters are cleared from when a sequence was aborted. */ | ||||
1031 | |||||
1032 | bte_seq_builder b0{BTE_SEQ_CSI, 'm'}; | ||||
1033 | b0.set_param_intro(BTE_SEQ_PARAMETER_CHAR_WHAT); | ||||
1034 | for (unsigned int i = 0; i < BTE_PARSER_ARG_MAX(32); ++i) | ||||
1035 | b0.append_param(127 * i + 17); | ||||
1036 | |||||
1037 | std::u32string str0; | ||||
1038 | b0.to_string(str0); | ||||
1039 | |||||
1040 | parser.reset(); | ||||
1041 | for (size_t len0 = 1; len0 <= str0.size(); ++len0) { | ||||
1042 | for (unsigned int n_args = 0; n_args < BTE_PARSER_ARG_MAX(32); ++n_args) { | ||||
1043 | feed_parser(str0.substr(0, len0)); | ||||
1044 | |||||
1045 | bte_seq_builder b1{BTE_SEQ_CSI, 'n'}; | ||||
1046 | b1.set_param_intro(BTE_SEQ_PARAMETER_CHAR_GT); | ||||
1047 | for (unsigned int i = 0; i < n_args; ++i) | ||||
1048 | b1.append_param(257 * i + 31); | ||||
1049 | |||||
1050 | std::u32string str1; | ||||
1051 | b1.to_string(str1); | ||||
1052 | |||||
1053 | auto rv = feed_parser(str1); | ||||
1054 | g_assert_cmpint(rv, ==, BTE_SEQ_CSI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_CSI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1054, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_CSI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1055 | b1.assert_equal_full(seq); | ||||
1056 | for (unsigned int n = seq.size(); n < BTE_PARSER_ARG_MAX(32); n++) | ||||
1057 | g_assert_true(seq.param_default(n))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_54 ; if (seq.param_default(n)) _g_boolean_var_54 = 1; else _g_boolean_var_54 = 0; _g_boolean_var_54; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1057, ((const char*) ( __PRETTY_FUNCTION__)), "'" "seq.param_default(n)" "' should be TRUE" ); } while (0); | ||||
1058 | } | ||||
1059 | } | ||||
1060 | } | ||||
1061 | |||||
1062 | static void | ||||
1063 | test_seq_csi_max(std::u32string const& start, | ||||
1064 | std::u32string const& more, | ||||
1065 | int expected_rv = BTE_SEQ_NONE) | ||||
1066 | { | ||||
1067 | parser.reset(); | ||||
1068 | feed_parser(start); | ||||
1069 | feed_parser(more); | ||||
1070 | auto rv = feed_parser(U"m"s); /* final character */ | ||||
1071 | g_assert_cmpint(rv, ==, expected_rv)do { gint64 __n1 = (rv), __n2 = (expected_rv); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1071, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "expected_rv", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1072 | } | ||||
1073 | |||||
1074 | static void | ||||
1075 | test_seq_csi_max(void) | ||||
1076 | { | ||||
1077 | /* Check that an excessive number of parameters causes the | ||||
1078 | * sequence to be ignored. | ||||
1079 | * | ||||
1080 | * Since SequenceBuilder is limited in the same number of | ||||
1081 | * parameters as the parser, can't use it directly to | ||||
1082 | * produce a sequence with too may parameters. | ||||
1083 | */ | ||||
1084 | |||||
1085 | bte_seq_builder b{BTE_SEQ_CSI, 'm'}; | ||||
1086 | b.set_param_intro(BTE_SEQ_PARAMETER_CHAR_WHAT); | ||||
1087 | for (unsigned int i = 0; i < BTE_PARSER_ARG_MAX(32); ++i) | ||||
1088 | b.append_param(i); | ||||
1089 | |||||
1090 | std::u32string str; | ||||
1091 | b.to_string(str); | ||||
1092 | |||||
1093 | /* The sequence with BTE_PARSER_ARG_MAX args must be parsed */ | ||||
1094 | auto rv = feed_parser(str); | ||||
1095 | g_assert_cmpint(rv, ==, BTE_SEQ_CSI)do { gint64 __n1 = (rv), __n2 = (BTE_SEQ_CSI); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1095, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "BTE_SEQ_CSI", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1096 | |||||
1097 | /* Now test that adding one more parameter (whether with an | ||||
1098 | * explicit value, or default, causes the sequence to be ignored. | ||||
1099 | */ | ||||
1100 | str.pop_back(); /* erase final character */ | ||||
1101 | test_seq_csi_max(str, U":"s); | ||||
1102 | test_seq_csi_max(str, U";"s); | ||||
1103 | test_seq_csi_max(str, U":12345"s); | ||||
1104 | test_seq_csi_max(str, U";12345"s); | ||||
1105 | test_seq_csi_max(str, U":12345;"s); | ||||
1106 | test_seq_csi_max(str, U";12345:"s); | ||||
1107 | test_seq_csi_max(str, U":12345;"s); | ||||
1108 | test_seq_csi_max(str, U":12345:"s); | ||||
1109 | } | ||||
1110 | |||||
1111 | static void | ||||
1112 | test_seq_glue_arg(char const* str, | ||||
1113 | unsigned int n_args, | ||||
1114 | unsigned int n_final_args) | ||||
1115 | { | ||||
1116 | test_seq_parse(str); | ||||
1117 | |||||
1118 | auto raw_seq = *seq.seq_ptr(); | ||||
1119 | g_assert_cmpuint(seq.size(), ==, n_args)do { guint64 __n1 = (seq.size()), __n2 = (n_args); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1119, ((const char*) (__PRETTY_FUNCTION__)), "seq.size()" " " "==" " " "n_args", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1120 | g_assert_cmpuint(raw_seq->n_args, ==, n_args)do { guint64 __n1 = (raw_seq->n_args), __n2 = (n_args); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0 ), "../src/parser-test.cc", 1120, ((const char*) (__PRETTY_FUNCTION__ )), "raw_seq->n_args" " " "==" " " "n_args", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1121 | g_assert_cmpuint(seq.size_final(), ==, n_final_args)do { guint64 __n1 = (seq.size_final()), __n2 = (n_final_args) ; if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1121, ((const char*) (__PRETTY_FUNCTION__ )), "seq.size_final()" " " "==" " " "n_final_args", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1122 | g_assert_cmpuint(raw_seq->n_final_args, ==, n_final_args)do { guint64 __n1 = (raw_seq->n_final_args), __n2 = (n_final_args ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1122, ((const char*) (__PRETTY_FUNCTION__ )), "raw_seq->n_final_args" " " "==" " " "n_final_args", ( long double) __n1, "==", (long double) __n2, 'i'); } while (0 ); | ||||
1123 | |||||
1124 | g_assert_cmpuint(seq.type(), ==, raw_seq->type)do { guint64 __n1 = (seq.type()), __n2 = (raw_seq->type); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0 ), "../src/parser-test.cc", 1124, ((const char*) (__PRETTY_FUNCTION__ )), "seq.type()" " " "==" " " "raw_seq->type", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1125 | g_assert_cmpuint(seq.command(), ==, raw_seq->command)do { guint64 __n1 = (seq.command()), __n2 = (raw_seq->command ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1125, ((const char*) (__PRETTY_FUNCTION__ )), "seq.command()" " " "==" " " "raw_seq->command", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1126 | g_assert_cmpuint(seq.terminator(), ==, raw_seq->terminator)do { guint64 __n1 = (seq.terminator()), __n2 = (raw_seq->terminator ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1126, ((const char*) (__PRETTY_FUNCTION__ )), "seq.terminator()" " " "==" " " "raw_seq->terminator", (long double) __n1, "==", (long double) __n2, 'i'); } while ( 0); | ||||
1127 | |||||
1128 | for (unsigned int i = 0; i < raw_seq->n_args; i++) | ||||
1129 | g_assert_cmpuint(seq.param(i), ==, bte_seq_arg_value(raw_seq->args[i]))do { guint64 __n1 = (seq.param(i)), __n2 = (bte_seq_arg_value (raw_seq->args[i])); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1129, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(i)" " " "==" " " "bte_seq_arg_value(raw_seq->args[i])" , (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1130 | } | ||||
1131 | |||||
1132 | static void | ||||
1133 | test_seq_glue_arg(void) | ||||
1134 | { | ||||
1135 | test_seq_glue_arg(":0:1000;2;3;4;:;", 9, 6); | ||||
1136 | g_assert_cmpuint(seq.cbegin(), ==, 0)do { guint64 __n1 = (seq.cbegin()), __n2 = (0); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1136, ((const char*) (__PRETTY_FUNCTION__)), "seq.cbegin()" " " "==" " " "0", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1137 | g_assert_cmpuint(seq.cend(), ==, 9)do { guint64 __n1 = (seq.cend()), __n2 = (9); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1137, ((const char*) (__PRETTY_FUNCTION__)), "seq.cend()" " " "==" " " "9", (long double) __n1, "==", (long double) __n2, 'i' ); } while (0); | ||||
1138 | |||||
1139 | auto it = seq.cbegin(); | ||||
1140 | g_assert_cmpuint(it, ==, 0)do { guint64 __n1 = (it), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1140, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "0", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1141 | it = seq.next(it); | ||||
1142 | g_assert_cmpuint(it, ==, 3)do { guint64 __n1 = (it), __n2 = (3); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1142, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "3", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1143 | it = seq.next(it); | ||||
1144 | g_assert_cmpuint(it, ==, 4)do { guint64 __n1 = (it), __n2 = (4); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1144, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "4", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1145 | it = seq.next(it); | ||||
1146 | g_assert_cmpuint(it, ==, 5)do { guint64 __n1 = (it), __n2 = (5); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1146, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "5", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1147 | it = seq.next(it); | ||||
1148 | g_assert_cmpuint(it, ==, 6)do { guint64 __n1 = (it), __n2 = (6); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1148, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "6", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1149 | it = seq.next(it); | ||||
1150 | g_assert_cmpuint(it, ==, 8)do { guint64 __n1 = (it), __n2 = (8); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1150, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "8", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1151 | it = seq.next(it); | ||||
1152 | g_assert_cmpuint(it, ==, 9)do { guint64 __n1 = (it), __n2 = (9); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1152, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "9", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1153 | |||||
1154 | it = seq.cbegin(); | ||||
1155 | g_assert_cmpint(seq.param(it++), ==, -1)do { gint64 __n1 = (seq.param(it++)), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1155, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1156 | g_assert_cmpint(seq.param(it++), ==, 0)do { gint64 __n1 = (seq.param(it++)), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1156, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "0", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1157 | g_assert_cmpint(seq.param(it++), ==, 1000)do { gint64 __n1 = (seq.param(it++)), __n2 = (1000); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1157, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "1000", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1158 | g_assert_cmpint(seq.param(it++), ==, 2)do { gint64 __n1 = (seq.param(it++)), __n2 = (2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1158, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1159 | g_assert_cmpint(seq.param(it++), ==, 3)do { gint64 __n1 = (seq.param(it++)), __n2 = (3); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1159, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "3", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1160 | g_assert_cmpint(seq.param(it++), ==, 4)do { gint64 __n1 = (seq.param(it++)), __n2 = (4); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1160, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "4", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1161 | g_assert_cmpint(seq.param(it++), ==, -1)do { gint64 __n1 = (seq.param(it++)), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1161, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1162 | g_assert_cmpint(seq.param(it++), ==, -1)do { gint64 __n1 = (seq.param(it++)), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1162, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1163 | g_assert_cmpint(seq.param(it++), ==, -1)do { gint64 __n1 = (seq.param(it++)), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1163, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it++)" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1164 | g_assert_cmpint(it, ==, seq.cend())do { gint64 __n1 = (it), __n2 = (seq.cend()); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1164, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "seq.cend()", (long double) __n1, "==", (long double) __n2, 'i' ); } while (0); | ||||
1165 | |||||
1166 | it = seq.cbegin(); | ||||
1167 | g_assert_cmpint(seq.param(it, -2), ==, -2)do { gint64 __n1 = (seq.param(it, -2)), __n2 = (-2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1167, ((const char*) (__PRETTY_FUNCTION__)), "seq.param(it, -2)" " " "==" " " "-2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1168 | g_assert_cmpint(seq.param(it, -2, 0, 100), ==, 0)do { gint64 __n1 = (seq.param(it, -2, 0, 100)), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0 ), "../src/parser-test.cc", 1168, ((const char*) (__PRETTY_FUNCTION__ )), "seq.param(it, -2, 0, 100)" " " "==" " " "0", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1169 | it++; it++; | ||||
1170 | g_assert_cmpint(seq.param(it, -2), ==, seq.param(it))do { gint64 __n1 = (seq.param(it, -2)), __n2 = (seq.param(it) ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1170, ((const char*) (__PRETTY_FUNCTION__ )), "seq.param(it, -2)" " " "==" " " "seq.param(it)", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1171 | g_assert_cmpint(seq.param(it, -2, 20, 100), ==, 100)do { gint64 __n1 = (seq.param(it, -2, 20, 100)), __n2 = (100) ; if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1171, ((const char*) (__PRETTY_FUNCTION__ )), "seq.param(it, -2, 20, 100)" " " "==" " " "100", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1172 | g_assert_cmpint(seq.param(it, -2, 200, 2000), ==, 1000)do { gint64 __n1 = (seq.param(it, -2, 200, 2000)), __n2 = (1000 ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1172, ((const char*) (__PRETTY_FUNCTION__ )), "seq.param(it, -2, 200, 2000)" " " "==" " " "1000", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1173 | g_assert_cmpint(seq.param(it, -2, 2000, 4000), ==, 2000)do { gint64 __n1 = (seq.param(it, -2, 2000, 4000)), __n2 = (2000 ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1173, ((const char*) (__PRETTY_FUNCTION__ )), "seq.param(it, -2, 2000, 4000)" " " "==" " " "2000", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1174 | |||||
1175 | int a, b, c,d ; | ||||
1176 | it = seq.cbegin(); | ||||
1177 | g_assert_false(seq.collect(it, {&a, &b, &c}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_55 ; if (!(seq.collect(it, {&a, &b, &c}))) _g_boolean_var_55 = 1; else _g_boolean_var_55 = 0; _g_boolean_var_55; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1177, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a, &b, &c})" "' should be FALSE"); } while (0); | ||||
1178 | g_assert_true(seq.collect_subparams(it, {&a}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_56 ; if (seq.collect_subparams(it, {&a})) _g_boolean_var_56 = 1; else _g_boolean_var_56 = 0; _g_boolean_var_56; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 1178 , ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a})" "' should be TRUE"); } while (0); | ||||
1179 | g_assert_true(seq.collect_subparams(it, {&a, &b}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_57 ; if (seq.collect_subparams(it, {&a, &b})) _g_boolean_var_57 = 1; else _g_boolean_var_57 = 0; _g_boolean_var_57; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1179, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a, &b})" "' should be TRUE"); } while (0); | ||||
1180 | g_assert_true(seq.collect_subparams(it, {&a, &b, &c}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_58 ; if (seq.collect_subparams(it, {&a, &b, &c})) _g_boolean_var_58 = 1; else _g_boolean_var_58 = 0; _g_boolean_var_58; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1180, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a, &b, &c})" "' should be TRUE"); } while (0); | ||||
1181 | g_assert_cmpint(a, ==, -1)do { gint64 __n1 = (a), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1181, ((const char*) (__PRETTY_FUNCTION__)), "a" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1182 | g_assert_cmpint(b, ==, 0)do { gint64 __n1 = (b), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1182, ((const char*) (__PRETTY_FUNCTION__)), "b" " " "==" " " "0", (long double) __n1 , "==", (long double) __n2, 'i'); } while (0); | ||||
1183 | g_assert_cmpint(c, ==, 1000)do { gint64 __n1 = (c), __n2 = (1000); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1183, ((const char*) (__PRETTY_FUNCTION__)), "c" " " "==" " " "1000", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1184 | g_assert_false(seq.collect_subparams(it, {&a, &b, &c, &d}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_59 ; if (!(seq.collect_subparams(it, {&a, &b, &c, & d}))) _g_boolean_var_59 = 1; else _g_boolean_var_59 = 0; _g_boolean_var_59 ; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1184, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a, &b, &c, &d})" "' should be FALSE"); } while (0); | ||||
1185 | |||||
1186 | it = seq.next(it); | ||||
1187 | g_assert_true(seq.collect(it, {&a}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_60 ; if (seq.collect(it, {&a})) _g_boolean_var_60 = 1; else _g_boolean_var_60 = 0; _g_boolean_var_60; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1187, ((const char*) ( __PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a})" "' should be TRUE" ); } while (0); | ||||
1188 | g_assert_true(seq.collect(it, {&a, &b}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_61 ; if (seq.collect(it, {&a, &b})) _g_boolean_var_61 = 1 ; else _g_boolean_var_61 = 0; _g_boolean_var_61; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 1188 , ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a, &b})" "' should be TRUE"); } while (0); | ||||
1189 | g_assert_true(seq.collect(it, {&a, &b, &c}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_62 ; if (seq.collect(it, {&a, &b, &c})) _g_boolean_var_62 = 1; else _g_boolean_var_62 = 0; _g_boolean_var_62; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1189, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a, &b, &c})" "' should be TRUE"); } while (0); | ||||
1190 | g_assert_cmpint(a, ==, 2)do { gint64 __n1 = (a), __n2 = (2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1190, ((const char*) (__PRETTY_FUNCTION__)), "a" " " "==" " " "2", (long double) __n1 , "==", (long double) __n2, 'i'); } while (0); | ||||
1191 | g_assert_cmpint(b, ==, 3)do { gint64 __n1 = (b), __n2 = (3); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1191, ((const char*) (__PRETTY_FUNCTION__)), "b" " " "==" " " "3", (long double) __n1 , "==", (long double) __n2, 'i'); } while (0); | ||||
1192 | g_assert_cmpint(c, ==, 4)do { gint64 __n1 = (c), __n2 = (4); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1192, ((const char*) (__PRETTY_FUNCTION__)), "c" " " "==" " " "4", (long double) __n1 , "==", (long double) __n2, 'i'); } while (0); | ||||
1193 | g_assert_false(seq.collect(it, {&a, &b, &c, &d}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_63 ; if (!(seq.collect(it, {&a, &b, &c, &d}))) _g_boolean_var_63 = 1; else _g_boolean_var_63 = 0; _g_boolean_var_63; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1193, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a, &b, &c, &d})" "' should be FALSE"); } while (0); | ||||
1194 | |||||
1195 | it = seq.next(it); | ||||
1196 | it = seq.next(it); | ||||
1197 | it = seq.next(it); | ||||
1198 | g_assert_false(seq.collect(it, {&a}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_64 ; if (!(seq.collect(it, {&a}))) _g_boolean_var_64 = 1; else _g_boolean_var_64 = 0; _g_boolean_var_64; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 1198, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a})" "' should be FALSE" ); } while (0); | ||||
1199 | g_assert_true(seq.collect_subparams(it, {&a}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_65 ; if (seq.collect_subparams(it, {&a})) _g_boolean_var_65 = 1; else _g_boolean_var_65 = 0; _g_boolean_var_65; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 1199 , ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a})" "' should be TRUE"); } while (0); | ||||
1200 | g_assert_true(seq.collect_subparams(it, {&a, &b}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_66 ; if (seq.collect_subparams(it, {&a, &b})) _g_boolean_var_66 = 1; else _g_boolean_var_66 = 0; _g_boolean_var_66; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1200, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a, &b})" "' should be TRUE"); } while (0); | ||||
1201 | g_assert_cmpint(a, ==, -1)do { gint64 __n1 = (a), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1201, ((const char*) (__PRETTY_FUNCTION__)), "a" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1202 | g_assert_cmpint(b, ==, -1)do { gint64 __n1 = (b), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1202, ((const char*) (__PRETTY_FUNCTION__)), "b" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1203 | g_assert_false(seq.collect_subparams(it, {&a, &b, &c}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_67 ; if (!(seq.collect_subparams(it, {&a, &b, &c}))) _g_boolean_var_67 = 1; else _g_boolean_var_67 = 0; _g_boolean_var_67 ; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1203, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect_subparams(it, {&a, &b, &c})" "' should be FALSE"); } while (0); | ||||
1204 | it = seq.next(it); | ||||
1205 | g_assert_true(seq.collect(it, {&a}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_68 ; if (seq.collect(it, {&a})) _g_boolean_var_68 = 1; else _g_boolean_var_68 = 0; _g_boolean_var_68; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1205, ((const char*) ( __PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a})" "' should be TRUE" ); } while (0); | ||||
1206 | g_assert_cmpint(a, ==, -1)do { gint64 __n1 = (a), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1206, ((const char*) (__PRETTY_FUNCTION__)), "a" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1207 | g_assert_true(seq.collect(it, {&a, &b}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_69 ; if (seq.collect(it, {&a, &b})) _g_boolean_var_69 = 1 ; else _g_boolean_var_69 = 0; _g_boolean_var_69; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 1207 , ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a, &b})" "' should be TRUE"); } while (0); /* past-the-end params are final and default */ | ||||
1208 | g_assert_cmpint(a, ==, -1)do { gint64 __n1 = (a), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1208, ((const char*) (__PRETTY_FUNCTION__)), "a" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1209 | g_assert_cmpint(b, ==, -1)do { gint64 __n1 = (b), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1209, ((const char*) (__PRETTY_FUNCTION__)), "b" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1210 | g_assert_true(seq.collect(it, {&a, &b, &c}))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_70 ; if (seq.collect(it, {&a, &b, &c})) _g_boolean_var_70 = 1; else _g_boolean_var_70 = 0; _g_boolean_var_70; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1210, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.collect(it, {&a, &b, &c})" "' should be TRUE"); } while (0); /* past-the-end params are final and default */ | ||||
1211 | g_assert_cmpint(a, ==, -1)do { gint64 __n1 = (a), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1211, ((const char*) (__PRETTY_FUNCTION__)), "a" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1212 | g_assert_cmpint(b, ==, -1)do { gint64 __n1 = (b), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1212, ((const char*) (__PRETTY_FUNCTION__)), "b" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1213 | g_assert_cmpint(c, ==, -1)do { gint64 __n1 = (c), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1213, ((const char*) (__PRETTY_FUNCTION__)), "c" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1214 | |||||
1215 | it = seq.cbegin(); | ||||
1216 | g_assert_cmpint(seq.collect1(it, -2), ==, -2)do { gint64 __n1 = (seq.collect1(it, -2)), __n2 = (-2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1216, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it, -2)" " " "==" " " "-2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1217 | it = seq.next(it); | ||||
1218 | g_assert_cmpint(seq.collect1(it), ==, 2)do { gint64 __n1 = (seq.collect1(it)), __n2 = (2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1218, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it)" " " "==" " " "2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1219 | g_assert_cmpint(seq.collect1(it), ==, 2)do { gint64 __n1 = (seq.collect1(it)), __n2 = (2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1219, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it)" " " "==" " " "2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1220 | it = seq.next(it); | ||||
1221 | g_assert_cmpint(seq.collect1(it), ==, 3)do { gint64 __n1 = (seq.collect1(it)), __n2 = (3); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1221, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it)" " " "==" " " "3", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1222 | it = seq.next(it); | ||||
1223 | g_assert_cmpint(seq.collect1(it), ==, 4)do { gint64 __n1 = (seq.collect1(it)), __n2 = (4); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1223, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it)" " " "==" " " "4", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1224 | it = seq.next(it); | ||||
1225 | g_assert_cmpint(seq.collect1(it, -3), ==, -3)do { gint64 __n1 = (seq.collect1(it, -3)), __n2 = (-3); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1225, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it, -3)" " " "==" " " "-3", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1226 | it = seq.next(it); | ||||
1227 | g_assert_cmpint(seq.collect1(it), ==, -1)do { gint64 __n1 = (seq.collect1(it)), __n2 = (-1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1227, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it)" " " "==" " " "-1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1228 | g_assert_cmpint(seq.collect1(it, 42), ==, 42)do { gint64 __n1 = (seq.collect1(it, 42)), __n2 = (42); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1228, ((const char*) (__PRETTY_FUNCTION__)), "seq.collect1(it, 42)" " " "==" " " "42", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1229 | g_assert_cmpint(seq.collect1(it, -1, 0, 100), ==, 0)do { gint64 __n1 = (seq.collect1(it, -1, 0, 100)), __n2 = (0) ; if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1229, ((const char*) (__PRETTY_FUNCTION__ )), "seq.collect1(it, -1, 0, 100)" " " "==" " " "0", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1230 | g_assert_cmpint(seq.collect1(it, 42, 0, 100), ==, 42)do { gint64 __n1 = (seq.collect1(it, 42, 0, 100)), __n2 = (42 ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1230, ((const char*) (__PRETTY_FUNCTION__ )), "seq.collect1(it, 42, 0, 100)" " " "==" " " "42", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1231 | g_assert_cmpint(seq.collect1(it, 42, 0, 10), ==, 10)do { gint64 __n1 = (seq.collect1(it, 42, 0, 10)), __n2 = (10) ; if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1231, ((const char*) (__PRETTY_FUNCTION__ )), "seq.collect1(it, 42, 0, 10)" " " "==" " " "10", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1232 | g_assert_cmpint(seq.collect1(it, 42, 100, 200), ==, 100)do { gint64 __n1 = (seq.collect1(it, 42, 100, 200)), __n2 = ( 100); if (__n1 == __n2) ; else g_assertion_message_cmpnum ((( gchar*) 0), "../src/parser-test.cc", 1232, ((const char*) (__PRETTY_FUNCTION__ )), "seq.collect1(it, 42, 100, 200)" " " "==" " " "100", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1233 | } | ||||
1234 | |||||
1235 | static int | ||||
1236 | feed_parser_st(bte_seq_builder& b, | ||||
1237 | bool c1 = false, | ||||
1238 | ssize_t max_arg_str_len = -1, | ||||
1239 | u32SequenceBuilder::Introducer introducer = u32SequenceBuilder::Introducer::DEFAULT, | ||||
1240 | u32SequenceBuilder::ST st = u32SequenceBuilder::ST::DEFAULT) | ||||
1241 | { | ||||
1242 | std::u32string s; | ||||
1243 | b.to_string(s, c1, max_arg_str_len, introducer, st); | ||||
1244 | |||||
1245 | auto rv = feed_parser(s); | ||||
1246 | if (rv != BTE_SEQ_OSC) | ||||
1247 | return rv; | ||||
1248 | |||||
1249 | switch (st) { | ||||
1250 | case u32SequenceBuilder::ST::NONE: | ||||
1251 | g_assert_cmpuint(seq.terminator(), ==, 0)do { guint64 __n1 = (seq.terminator()), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1251, ((const char*) (__PRETTY_FUNCTION__)), "seq.terminator()" " " "==" " " "0", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1252 | break; | ||||
1253 | case u32SequenceBuilder::ST::DEFAULT: | ||||
1254 | g_assert_cmpuint(seq.terminator(), ==, c1 ? 0x9c /* ST */ : 0x5c /* BACKSLASH */)do { guint64 __n1 = (seq.terminator()), __n2 = (c1 ? 0x9c : 0x5c ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-test.cc", 1254, ((const char*) (__PRETTY_FUNCTION__ )), "seq.terminator()" " " "==" " " "c1 ? 0x9c : 0x5c", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1255 | break; | ||||
1256 | case u32SequenceBuilder::ST::C0: | ||||
1257 | g_assert_cmpuint(seq.terminator(), ==, 0x5c /* BACKSLASH */)do { guint64 __n1 = (seq.terminator()), __n2 = (0x5c); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1257, ((const char*) (__PRETTY_FUNCTION__)), "seq.terminator()" " " "==" " " "0x5c", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1258 | break; | ||||
1259 | case u32SequenceBuilder::ST::C1: | ||||
1260 | g_assert_cmpuint(seq.terminator(), ==, 0x9c /* ST */)do { guint64 __n1 = (seq.terminator()), __n2 = (0x9c); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1260, ((const char*) (__PRETTY_FUNCTION__)), "seq.terminator()" " " "==" " " "0x9c", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1261 | break; | ||||
1262 | case u32SequenceBuilder::ST::BEL: | ||||
1263 | g_assert_cmpuint(seq.terminator(), ==, 0x7 /* BEL */)do { guint64 __n1 = (seq.terminator()), __n2 = (0x7); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1263, ((const char*) (__PRETTY_FUNCTION__)), "seq.terminator()" " " "==" " " "0x7", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1264 | break; | ||||
1265 | } | ||||
1266 | |||||
1267 | return rv; | ||||
1268 | } | ||||
1269 | |||||
1270 | static void | ||||
1271 | test_seq_osc(std::u32string const& str, | ||||
1272 | int expected_rv = BTE_SEQ_OSC, | ||||
1273 | bool c1 = true, | ||||
1274 | ssize_t max_arg_str_len = -1, | ||||
1275 | u32SequenceBuilder::Introducer introducer = u32SequenceBuilder::Introducer::DEFAULT, | ||||
1276 | u32SequenceBuilder::ST st = u32SequenceBuilder::ST::DEFAULT) | ||||
1277 | { | ||||
1278 | bte_seq_builder b{BTE_SEQ_OSC, str}; | ||||
1279 | |||||
1280 | parser.reset(); | ||||
1281 | auto rv = feed_parser_st(b, c1, max_arg_str_len, introducer, st); | ||||
1282 | g_assert_cmpint(rv, ==, expected_rv)do { gint64 __n1 = (rv), __n2 = (expected_rv); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1282, ((const char*) (__PRETTY_FUNCTION__)), "rv" " " "==" " " "expected_rv", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1283 | #if 0 | ||||
1284 | if (rv != BTE_SEQ_NONE) | ||||
1285 | b.assert_equal(seq); | ||||
1286 | #endif | ||||
1287 | |||||
1288 | if (expected_rv != BTE_SEQ_OSC) | ||||
1289 | return; | ||||
1290 | |||||
1291 | if (max_arg_str_len < 0 || size_t(max_arg_str_len) == str.size()) | ||||
1292 | g_assert_true(seq.string() == str)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_71 ; if (seq.string() == str) _g_boolean_var_71 = 1; else _g_boolean_var_71 = 0; _g_boolean_var_71; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1292, ((const char*) ( __PRETTY_FUNCTION__)), "'" "seq.string() == str" "' should be TRUE" ); } while (0); | ||||
1293 | else | ||||
1294 | g_assert_true(seq.string() == str.substr(0, max_arg_str_len))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_72 ; if (seq.string() == str.substr(0, max_arg_str_len)) _g_boolean_var_72 = 1; else _g_boolean_var_72 = 0; _g_boolean_var_72; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1294, ((const char*) (__PRETTY_FUNCTION__)), "'" "seq.string() == str.substr(0, max_arg_str_len)" "' should be TRUE"); } while (0); | ||||
1295 | } | ||||
1296 | |||||
1297 | static int | ||||
1298 | controls_match(bool c1, | ||||
1299 | u32SequenceBuilder::Introducer introducer, | ||||
1300 | u32SequenceBuilder::ST st, | ||||
1301 | bool allow_bel, | ||||
1302 | int expected_rv) | ||||
1303 | { | ||||
1304 | if (introducer == u32SequenceBuilder::Introducer::DEFAULT) | ||||
1305 | introducer = c1 ? u32SequenceBuilder::Introducer::C1 : u32SequenceBuilder::Introducer::C0; | ||||
1306 | if (st == u32SequenceBuilder::ST::DEFAULT) | ||||
1307 | st = c1 ? u32SequenceBuilder::ST::C1 : u32SequenceBuilder::ST::C0; | ||||
1308 | if ((introducer == u32SequenceBuilder::Introducer::C0 && | ||||
1309 | (st == u32SequenceBuilder::ST::C0 || (allow_bel && st == u32SequenceBuilder::ST::BEL))) || | ||||
1310 | (introducer == u32SequenceBuilder::Introducer::C1 && | ||||
1311 | st == u32SequenceBuilder::ST::C1)) | ||||
1312 | return expected_rv; | ||||
1313 | return BTE_SEQ_IGNORE; | ||||
1314 | } | ||||
1315 | |||||
1316 | static void | ||||
1317 | test_seq_osc(void) | ||||
1318 | { | ||||
1319 | /* Simple */ | ||||
1320 | test_seq_osc(U""s); | ||||
1321 | test_seq_osc(U"TEST"s); | ||||
1322 | |||||
1323 | /* String of any supported length */ | ||||
1324 | for (unsigned int len = 0; len < BTE_SEQ_STRING_MAX_CAPACITY(1 << 12); ++len) | ||||
1325 | test_seq_osc(std::u32string(len, 0x10000+len)); | ||||
1326 | |||||
1327 | /* Length exceeded */ | ||||
1328 | test_seq_osc(std::u32string(BTE_SEQ_STRING_MAX_CAPACITY(1 << 12) + 1, 0x100000), BTE_SEQ_IGNORE); | ||||
1329 | |||||
1330 | /* Test all introducer/ST combinations */ | ||||
1331 | for (auto introducer : { u32SequenceBuilder::Introducer::DEFAULT, | ||||
1332 | u32SequenceBuilder::Introducer::C0, | ||||
1333 | u32SequenceBuilder::Introducer::C1 }) { | ||||
1334 | for (auto st : {u32SequenceBuilder::ST::DEFAULT, | ||||
1335 | u32SequenceBuilder::ST::C0, | ||||
1336 | u32SequenceBuilder::ST::C1, | ||||
1337 | u32SequenceBuilder::ST::BEL }) { | ||||
1338 | for (auto c1 : { false, true }) { | ||||
1339 | int expected_rv = controls_match(c1, introducer, st, true, BTE_SEQ_OSC); | ||||
1340 | test_seq_osc(U"TEST"s, expected_rv, c1, -1, introducer, st); | ||||
1341 | } | ||||
1342 | } | ||||
1343 | } | ||||
1344 | } | ||||
1345 | |||||
1346 | static void | ||||
1347 | test_seq_glue_string(void) | ||||
1348 | { | ||||
1349 | std::u32string str{U"TEST"s}; | ||||
1350 | test_seq_osc(str); | ||||
1351 | |||||
1352 | g_assert_true(seq.string() == str)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_73 ; if (seq.string() == str) _g_boolean_var_73 = 1; else _g_boolean_var_73 = 0; _g_boolean_var_73; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1352, ((const char*) ( __PRETTY_FUNCTION__)), "'" "seq.string() == str" "' should be TRUE" ); } while (0); | ||||
1353 | } | ||||
1354 | |||||
1355 | static void | ||||
1356 | test_seq_glue_string_tokeniser(void) | ||||
1357 | { | ||||
1358 | std::string str{"a;1b:17:test::b:;3;5;def;17 a;ghi;"s}; | ||||
1359 | |||||
1360 | StringTokeniser tokeniser{str, ';'}; | ||||
1361 | |||||
1362 | auto start = tokeniser.cbegin(); | ||||
1363 | auto end = tokeniser.cend(); | ||||
1364 | |||||
1365 | auto pit = start; | ||||
1366 | for (auto it : {"a"s, "1b:17:test::b:"s, "3"s, "5"s, "def"s, "17 a"s, "ghi"s, ""s}) { | ||||
1367 | g_assert_true(it == *pit)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_74 ; if (it == *pit) _g_boolean_var_74 = 1; else _g_boolean_var_74 = 0; _g_boolean_var_74; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1367, ((const char*) ( __PRETTY_FUNCTION__)), "'" "it == *pit" "' should be TRUE"); } while (0); | ||||
1368 | |||||
1369 | /* Use std::find to see if the InputIterator implementation | ||||
1370 | * is complete and correct. | ||||
1371 | */ | ||||
1372 | auto fit = std::find(start, end, it); | ||||
1373 | g_assert_true(fit == pit)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_75 ; if (fit == pit) _g_boolean_var_75 = 1; else _g_boolean_var_75 = 0; _g_boolean_var_75; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1373, ((const char*) ( __PRETTY_FUNCTION__)), "'" "fit == pit" "' should be TRUE"); } while (0); | ||||
1374 | |||||
1375 | ++pit; | ||||
1376 | } | ||||
1377 | g_assert_true(pit == end)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_76 ; if (pit == end) _g_boolean_var_76 = 1; else _g_boolean_var_76 = 0; _g_boolean_var_76; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1377, ((const char*) ( __PRETTY_FUNCTION__)), "'" "pit == end" "' should be TRUE"); } while (0); | ||||
1378 | |||||
1379 | auto len = str.size(); | ||||
1380 | size_t pos = 0; | ||||
1381 | pit = start; | ||||
1382 | for (auto it : {1, 14, 1, 1, 3, 4, 3, 0}) { | ||||
1383 | g_assert_cmpuint(it, ==, pit.size())do { guint64 __n1 = (it), __n2 = (pit.size()); if (__n1 == __n2 ) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1383, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "pit.size()", (long double) __n1, "==", (long double) __n2, 'i' ); } while (0); | ||||
1384 | g_assert_cmpuint(len, ==, pit.size_remaining())do { guint64 __n1 = (len), __n2 = (pit.size_remaining()); if ( __n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0) , "../src/parser-test.cc", 1384, ((const char*) (__PRETTY_FUNCTION__ )), "len" " " "==" " " "pit.size_remaining()", (long double) __n1 , "==", (long double) __n2, 'i'); } while (0); | ||||
1385 | |||||
1386 | g_assert_true(pit.string_remaining() == str.substr(pos, std::string::npos))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_77 ; if (pit.string_remaining() == str.substr(pos, std::string:: npos)) _g_boolean_var_77 = 1; else _g_boolean_var_77 = 0; _g_boolean_var_77 ; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc" , 1386, ((const char*) (__PRETTY_FUNCTION__)), "'" "pit.string_remaining() == str.substr(pos, std::string::npos)" "' should be TRUE"); } while (0); | ||||
1387 | |||||
1388 | len -= it + 1; | ||||
1389 | pos += it + 1; | ||||
1390 | |||||
1391 | ++pit; | ||||
1392 | } | ||||
1393 | g_assert_cmpuint(len + 1, ==, 0)do { guint64 __n1 = (len + 1), __n2 = (0); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1393, ((const char*) (__PRETTY_FUNCTION__)), "len + 1" " " "==" " " "0", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1394 | g_assert_cmpuint(pos, ==, str.size() + 1)do { guint64 __n1 = (pos), __n2 = (str.size() + 1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1394, ((const char*) (__PRETTY_FUNCTION__)), "pos" " " "==" " " "str.size() + 1", (long double) __n1, "==", (long double ) __n2, 'i'); } while (0); | ||||
1395 | |||||
1396 | pit = start; | ||||
1397 | for (auto it : {-2, -2, 3, 5, -2, -2, -2, -1}) { | ||||
1398 | int num; | ||||
1399 | bool v = pit.number(num); | ||||
1400 | if (it == -2) | ||||
1401 | g_assert_false(v)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_78 ; if (!(v)) _g_boolean_var_78 = 1; else _g_boolean_var_78 = 0 ; _g_boolean_var_78; }), 1)) ; else g_assertion_message (((gchar *) 0), "../src/parser-test.cc", 1401, ((const char*) (__PRETTY_FUNCTION__ )), "'" "v" "' should be FALSE"); } while (0); | ||||
1402 | else | ||||
1403 | g_assert_cmpint(it, ==, num)do { gint64 __n1 = (it), __n2 = (num); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc" , 1403, ((const char*) (__PRETTY_FUNCTION__)), "it" " " "==" " " "num", (long double) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
1404 | |||||
1405 | ++pit; | ||||
1406 | } | ||||
1407 | |||||
1408 | /* Test range for */ | ||||
1409 | for (auto it : tokeniser) | ||||
1410 | ; | ||||
1411 | |||||
1412 | /* Test different separator */ | ||||
1413 | pit = start; | ||||
1414 | ++pit; | ||||
1415 | |||||
1416 | auto substr = *pit; | ||||
1417 | StringTokeniser subtokeniser{substr, ':'}; | ||||
1418 | |||||
1419 | auto subpit = subtokeniser.cbegin(); | ||||
1420 | for (auto it : {"1b"s, "17"s, "test"s, ""s, "b"s, ""s}) { | ||||
1421 | g_assert_true(it == *subpit)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_79 ; if (it == *subpit) _g_boolean_var_79 = 1; else _g_boolean_var_79 = 0; _g_boolean_var_79; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1421, ((const char*) ( __PRETTY_FUNCTION__)), "'" "it == *subpit" "' should be TRUE" ); } while (0); | ||||
1422 | |||||
1423 | ++subpit; | ||||
1424 | } | ||||
1425 | g_assert_true(subpit == subtokeniser.cend())do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_80 ; if (subpit == subtokeniser.cend()) _g_boolean_var_80 = 1; else _g_boolean_var_80 = 0; _g_boolean_var_80; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-test.cc", 1425, ((const char*) (__PRETTY_FUNCTION__)), "'" "subpit == subtokeniser.cend()" "' should be TRUE" ); } while (0); | ||||
1426 | |||||
1427 | /* Test another string, one that doesn't end with an empty token */ | ||||
1428 | std::string str2{"abc;defghi"s}; | ||||
1429 | StringTokeniser tokeniser2{str2, ';'}; | ||||
1430 | |||||
1431 | g_assert_cmpint(std::distance(tokeniser2.cbegin(), tokeniser2.cend()), ==, 2)do { gint64 __n1 = (std::distance(tokeniser2.cbegin(), tokeniser2 .cend())), __n2 = (2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1431, ((const char*) (__PRETTY_FUNCTION__)), "std::distance(tokeniser2.cbegin(), tokeniser2.cend())" " " "==" " " "2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1432 | auto pit2 = tokeniser2.cbegin(); | ||||
1433 | g_assert_true(*pit2 == "abc"s)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_81 ; if (*pit2 == "abc"s) _g_boolean_var_81 = 1; else _g_boolean_var_81 = 0; _g_boolean_var_81; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1433, ((const char*) ( __PRETTY_FUNCTION__)), "'" "*pit2 == \"abc\"s" "' should be TRUE" ); } while (0); | ||||
1434 | ++pit2; | ||||
1435 | g_assert_true(*pit2 == "defghi"s)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_82 ; if (*pit2 == "defghi"s) _g_boolean_var_82 = 1; else _g_boolean_var_82 = 0; _g_boolean_var_82; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1435, ((const char*) ( __PRETTY_FUNCTION__)), "'" "*pit2 == \"defghi\"s" "' should be TRUE" ); } while (0); | ||||
1436 | ++pit2; | ||||
1437 | g_assert_true(pit2 == tokeniser2.cend())do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_83 ; if (pit2 == tokeniser2.cend()) _g_boolean_var_83 = 1; else _g_boolean_var_83 = 0; _g_boolean_var_83; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1437, ((const char*) ( __PRETTY_FUNCTION__)), "'" "pit2 == tokeniser2.cend()" "' should be TRUE" ); } while (0); | ||||
1438 | |||||
1439 | /* Test another string, one that starts with an empty token */ | ||||
1440 | std::string str3{";abc"s}; | ||||
1441 | StringTokeniser tokeniser3{str3, ';'}; | ||||
1442 | |||||
1443 | g_assert_cmpint(std::distance(tokeniser3.cbegin(), tokeniser3.cend()), ==, 2)do { gint64 __n1 = (std::distance(tokeniser3.cbegin(), tokeniser3 .cend())), __n2 = (2); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1443, ((const char*) (__PRETTY_FUNCTION__)), "std::distance(tokeniser3.cbegin(), tokeniser3.cend())" " " "==" " " "2", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1444 | auto pit3 = tokeniser3.cbegin(); | ||||
1445 | g_assert_true(*pit3 == ""s)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_84 ; if (*pit3 == ""s) _g_boolean_var_84 = 1; else _g_boolean_var_84 = 0; _g_boolean_var_84; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1445, ((const char*) ( __PRETTY_FUNCTION__)), "'" "*pit3 == \"\"s" "' should be TRUE" ); } while (0); | ||||
1446 | ++pit3; | ||||
1447 | g_assert_true(*pit3 == "abc"s)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_85 ; if (*pit3 == "abc"s) _g_boolean_var_85 = 1; else _g_boolean_var_85 = 0; _g_boolean_var_85; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1447, ((const char*) ( __PRETTY_FUNCTION__)), "'" "*pit3 == \"abc\"s" "' should be TRUE" ); } while (0); | ||||
1448 | ++pit3; | ||||
1449 | g_assert_true(pit3 == tokeniser3.cend())do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_86 ; if (pit3 == tokeniser3.cend()) _g_boolean_var_86 = 1; else _g_boolean_var_86 = 0; _g_boolean_var_86; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1449, ((const char*) ( __PRETTY_FUNCTION__)), "'" "pit3 == tokeniser3.cend()" "' should be TRUE" ); } while (0); | ||||
1450 | |||||
1451 | /* And try an empty string, which should split into one empty token */ | ||||
1452 | std::string str4{""s}; | ||||
1453 | StringTokeniser tokeniser4{str4, ';'}; | ||||
1454 | |||||
1455 | g_assert_cmpint(std::distance(tokeniser4.cbegin(), tokeniser4.cend()), ==, 1)do { gint64 __n1 = (std::distance(tokeniser4.cbegin(), tokeniser4 .cend())), __n2 = (1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-test.cc", 1455, ((const char*) (__PRETTY_FUNCTION__)), "std::distance(tokeniser4.cbegin(), tokeniser4.cend())" " " "==" " " "1", (long double) __n1, "==", (long double) __n2 , 'i'); } while (0); | ||||
1456 | auto pit4 = tokeniser4.cbegin(); | ||||
1457 | g_assert_true(*pit4 == ""s)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_87 ; if (*pit4 == ""s) _g_boolean_var_87 = 1; else _g_boolean_var_87 = 0; _g_boolean_var_87; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1457, ((const char*) ( __PRETTY_FUNCTION__)), "'" "*pit4 == \"\"s" "' should be TRUE" ); } while (0); | ||||
1458 | ++pit4; | ||||
1459 | g_assert_true(pit4 == tokeniser4.cend())do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_88 ; if (pit4 == tokeniser4.cend()) _g_boolean_var_88 = 1; else _g_boolean_var_88 = 0; _g_boolean_var_88; }), 1)) ; else g_assertion_message ( ((gchar*) 0), "../src/parser-test.cc", 1459, ((const char*) ( __PRETTY_FUNCTION__)), "'" "pit4 == tokeniser4.cend()" "' should be TRUE" ); } while (0); | ||||
1460 | } | ||||
1461 | |||||
1462 | static void | ||||
1463 | test_seq_glue_sequence_builder(void) | ||||
1464 | { | ||||
1465 | /* This is sufficiently tested by being used in all the other tests, | ||||
1466 | * but if there's anything remaining to be tested, do it here. | ||||
1467 | */ | ||||
1468 | } | ||||
1469 | |||||
1470 | static void | ||||
1471 | test_seq_glue_reply_builder(void) | ||||
1472 | { | ||||
1473 | /* Nothing to test here; ReplyBuilder is just a constructor for | ||||
1474 | * SequenceBuilder. | ||||
1475 | */ | ||||
1476 | } | ||||
1477 | |||||
1478 | int | ||||
1479 | main(int argc, | ||||
1480 | char* argv[]) | ||||
1481 | { | ||||
1482 | g_test_init(&argc, &argv, nullptr); | ||||
1483 | |||||
1484 | g_test_add_func("/bte/parser/sequences/arg", test_seq_arg); | ||||
1485 | g_test_add_func("/bte/parser/sequences/string", test_seq_string); | ||||
1486 | g_test_add_func("/bte/parser/sequences/glue/arg", test_seq_glue_arg); | ||||
1487 | g_test_add_func("/bte/parser/sequences/glue/string", test_seq_glue_string); | ||||
1488 | g_test_add_func("/bte/parser/sequences/glue/string-tokeniser", test_seq_glue_string_tokeniser); | ||||
1489 | g_test_add_func("/bte/parser/sequences/glue/sequence-builder", test_seq_glue_sequence_builder); | ||||
1490 | g_test_add_func("/bte/parser/sequences/glue/reply-builder", test_seq_glue_reply_builder); | ||||
1491 | g_test_add_func("/bte/parser/sequences/control", test_seq_control); | ||||
1492 | g_test_add_func("/bte/parser/sequences/escape/invalid", test_seq_esc_invalid); | ||||
1493 | g_test_add_func("/bte/parser/sequences/escape/charset/94", test_seq_esc_charset_94); | ||||
1494 | g_test_add_func("/bte/parser/sequences/escape/charset/96", test_seq_esc_charset_96); | ||||
1495 | g_test_add_func("/bte/parser/sequences/escape/charset/94^n", test_seq_esc_charset_94_n); | ||||
1496 | g_test_add_func("/bte/parser/sequences/escape/charset/96^n", test_seq_esc_charset_96_n); | ||||
1497 | g_test_add_func("/bte/parser/sequences/escape/charset/control", test_seq_esc_charset_control); | ||||
1498 | g_test_add_func("/bte/parser/sequences/escape/charset/other", test_seq_esc_charset_other); | ||||
1499 | g_test_add_func("/bte/parser/sequences/escape/nF", test_seq_esc_nF); | ||||
1500 | g_test_add_func("/bte/parser/sequences/escape/F[pes]", test_seq_esc_Fpes); | ||||
1501 | g_test_add_func("/bte/parser/sequences/escape/known", test_seq_esc_known); | ||||
1502 | g_test_add_func("/bte/parser/sequences/csi", test_seq_csi); | ||||
1503 | g_test_add_func("/bte/parser/sequences/csi/known", test_seq_csi_known); | ||||
1504 | g_test_add_func("/bte/parser/sequences/csi/parameters", test_seq_csi_param); | ||||
1505 | g_test_add_func("/bte/parser/sequences/csi/clear", test_seq_csi_clear); | ||||
1506 | g_test_add_func("/bte/parser/sequences/csi/max", test_seq_csi_max); | ||||
1507 | g_test_add_func("/bte/parser/sequences/sci", test_seq_sci); | ||||
1508 | g_test_add_func("/bte/parser/sequences/sci/known", test_seq_sci_known); | ||||
1509 | g_test_add_func("/bte/parser/sequences/dcs", test_seq_dcs); | ||||
1510 | g_test_add_func("/bte/parser/sequences/dcs/known", test_seq_dcs_known); | ||||
1511 | g_test_add_func("/bte/parser/sequences/osc", test_seq_osc); | ||||
1512 | |||||
1513 | return g_test_run(); | ||||
1514 | } |
1 | /* | ||||
2 | * Copyright © 2017, 2018 Christian Persch | ||||
3 | * | ||||
4 | * This library is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU Lesser General Public | ||||
6 | * License as published by the Free Software Foundation; either | ||||
7 | * version 3 of the License, or (at your option) any later version. | ||||
8 | * | ||||
9 | * This library is distributed in the hope that it will be useful, | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
12 | * Lesser General Public License for more details. | ||||
13 | * | ||||
14 | * You should have received a copy of the GNU General Public License | ||||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
16 | */ | ||||
17 | |||||
18 | #pragma once | ||||
19 | |||||
20 | #include <cstdint> | ||||
21 | #include <algorithm> | ||||
22 | #include <string> | ||||
23 | |||||
24 | #include "parser.hh" | ||||
25 | |||||
26 | namespace bte { | ||||
27 | |||||
28 | namespace parser { | ||||
29 | |||||
30 | class Sequence; | ||||
31 | |||||
32 | class Parser { | ||||
33 | public: | ||||
34 | friend class Sequence; | ||||
35 | |||||
36 | Parser() noexcept | ||||
37 | { | ||||
38 | bte_parser_init(&m_parser); | ||||
39 | } | ||||
40 | Parser(Parser const&) = delete; | ||||
41 | Parser(Parser&&) = delete; | ||||
42 | |||||
43 | ~Parser() noexcept | ||||
44 | { | ||||
45 | bte_parser_deinit(&m_parser); | ||||
46 | } | ||||
47 | |||||
48 | Parser& operator=(Parser const&) = delete; | ||||
49 | Parser& operator=(Parser&&) = delete; | ||||
50 | |||||
51 | inline int feed(uint32_t raw) noexcept | ||||
52 | { | ||||
53 | return bte_parser_feed(&m_parser, raw); | ||||
54 | } | ||||
55 | |||||
56 | inline void reset() noexcept | ||||
57 | { | ||||
58 | bte_parser_reset(&m_parser); | ||||
59 | } | ||||
60 | |||||
61 | protected: | ||||
62 | bte_parser_t m_parser; | ||||
63 | }; // class Parser | ||||
64 | |||||
65 | class Sequence { | ||||
66 | public: | ||||
67 | |||||
68 | Sequence() = default; | ||||
69 | Sequence(Sequence const&) = delete; | ||||
70 | Sequence(Sequence&&) = delete; | ||||
71 | ~Sequence() = default; | ||||
72 | |||||
73 | Sequence(Parser& parser) | ||||
74 | { | ||||
75 | m_seq = &parser.m_parser.seq; | ||||
76 | } | ||||
77 | |||||
78 | typedef int number; | ||||
79 | |||||
80 | char* ucs4_to_utf8(gunichar const* str, | ||||
81 | ssize_t len = -1) const noexcept; | ||||
82 | |||||
83 | void print() const noexcept; | ||||
84 | |||||
85 | /* type: | ||||
86 | * | ||||
87 | * | ||||
88 | * Returns: the type of the sequence, a value from the BTE_SEQ_* enum | ||||
89 | */ | ||||
90 | inline constexpr unsigned int type() const noexcept | ||||
91 | { | ||||
92 | return m_seq->type; | ||||
93 | } | ||||
94 | |||||
95 | /* command: | ||||
96 | * | ||||
97 | * Returns: the command the sequence codes for, a value | ||||
98 | * from the BTE_CMD_* enum, or %BTE_CMD_NONE if the command is | ||||
99 | * unknown | ||||
100 | */ | ||||
101 | inline constexpr unsigned int command() const noexcept | ||||
102 | { | ||||
103 | return m_seq->command; | ||||
104 | } | ||||
105 | |||||
106 | /* charset: | ||||
107 | * | ||||
108 | * This is the charset to use in a %BTE_CMD_GnDm, %BTE_CMD_GnDMm, | ||||
109 | * %BTE_CMD_CnD or %BTE_CMD_DOCS command. | ||||
110 | * | ||||
111 | * Returns: the charset, a value from the BTE_CHARSET_* enum. | ||||
112 | */ | ||||
113 | inline constexpr unsigned int charset() const noexcept | ||||
114 | { | ||||
115 | return BTE_CHARSET_GET_CHARSET(m_seq->charset)((m_seq->charset) & ((1U << 16) - 1U)); | ||||
116 | } | ||||
117 | |||||
118 | /* slot: | ||||
119 | * | ||||
120 | * This is the slot in a %BTE_CMD_GnDm, %BTE_CMD_GnDMm, | ||||
121 | * or %BTE_CMD_CnD command. | ||||
122 | * | ||||
123 | * Returns: the slot, a value from the 0..3 for Gn*, or 0..1 for CnD | ||||
124 | */ | ||||
125 | inline constexpr unsigned int slot() const noexcept | ||||
126 | { | ||||
127 | return BTE_CHARSET_GET_SLOT(m_seq->charset)((m_seq->charset) >> (16)); | ||||
128 | } | ||||
129 | |||||
130 | /* introducer: | ||||
131 | * | ||||
132 | * This is the character introducing the sequence, if any. | ||||
133 | * | ||||
134 | * Returns: the introducing character | ||||
135 | */ | ||||
136 | inline constexpr uint32_t introducer() const noexcept | ||||
137 | { | ||||
138 | return m_seq->introducer; | ||||
139 | } | ||||
140 | |||||
141 | /* terminator: | ||||
142 | * | ||||
143 | * This is the character terminating the sequence, or, for a | ||||
144 | * %BTE_SEQ_GRAPHIC sequence, the graphic character. | ||||
145 | * | ||||
146 | * Returns: the terminating character | ||||
147 | */ | ||||
148 | inline constexpr uint32_t terminator() const noexcept | ||||
149 | { | ||||
150 | return m_seq->terminator; | ||||
151 | } | ||||
152 | |||||
153 | |||||
154 | /* is_c1: | ||||
155 | * | ||||
156 | * Whether the sequence was introduced with a C0 or C1 control. | ||||
157 | * | ||||
158 | * Returns: the introducing character | ||||
159 | */ | ||||
160 | inline constexpr bool is_c1() const noexcept | ||||
161 | { | ||||
162 | return (introducer() & 0x80) != 0; | ||||
163 | } | ||||
164 | |||||
165 | /* intermediates: | ||||
166 | * | ||||
167 | * This is the pintro and intermediate characters in the sequence, if any. | ||||
168 | * | ||||
169 | * Returns: the intermediates | ||||
170 | */ | ||||
171 | inline constexpr unsigned int intermediates() const noexcept | ||||
172 | { | ||||
173 | return m_seq->intermediates; | ||||
174 | } | ||||
175 | |||||
176 | // FIXMEchpe: upgrade to C++17 and use the u32string_view version below, instead | ||||
177 | /* | ||||
178 | * string: | ||||
179 | * | ||||
180 | * This is the string argument of a DCS or OSC sequence. | ||||
181 | * | ||||
182 | * Returns: the string argument | ||||
183 | */ | ||||
184 | inline std::u32string string() const noexcept | ||||
185 | { | ||||
186 | size_t len; | ||||
187 | auto buf = bte_seq_string_get(&m_seq->arg_str, &len); | ||||
188 | return std::u32string(reinterpret_cast<char32_t*>(buf), len); | ||||
189 | } | ||||
190 | |||||
191 | #if 0 | ||||
192 | /* | ||||
193 | * string: | ||||
194 | * | ||||
195 | * This is the string argument of a DCS or OSC sequence. | ||||
196 | * | ||||
197 | * Returns: the string argument | ||||
198 | */ | ||||
199 | inline constexpr std::u32string_view string() const noexcept | ||||
200 | { | ||||
201 | size_t len = 0; | ||||
202 | auto buf = bte_seq_string_get(&m_seq->arg_str, &len); | ||||
203 | return std::u32string_view(buf, len); | ||||
204 | } | ||||
205 | #endif | ||||
206 | |||||
207 | /* | ||||
208 | * string: | ||||
209 | * | ||||
210 | * This is the string argument of a DCS or OSC sequence. | ||||
211 | * | ||||
212 | * Returns: the string argument | ||||
213 | */ | ||||
214 | std::string string_utf8() const noexcept; | ||||
215 | |||||
216 | inline char* string_param() const noexcept | ||||
217 | { | ||||
218 | size_t len = 0; | ||||
219 | auto buf = bte_seq_string_get(&m_seq->arg_str, &len); | ||||
220 | return ucs4_to_utf8(buf, len); | ||||
221 | } | ||||
222 | |||||
223 | /* size: | ||||
224 | * | ||||
225 | * Returns: the number of parameters | ||||
226 | */ | ||||
227 | inline constexpr unsigned int size() const noexcept | ||||
228 | { | ||||
229 | return m_seq->n_args; | ||||
230 | } | ||||
231 | |||||
232 | |||||
233 | /* size: | ||||
234 | * | ||||
235 | * Returns: the number of parameter blocks, counting runs of subparameters | ||||
236 | * as only one parameter | ||||
237 | */ | ||||
238 | inline constexpr unsigned int size_final() const noexcept | ||||
239 | { | ||||
240 | return m_seq->n_final_args; | ||||
241 | } | ||||
242 | |||||
243 | /* capacity: | ||||
244 | * | ||||
245 | * Returns: the number of parameter blocks, counting runs of subparameters | ||||
246 | * as only one parameter | ||||
247 | */ | ||||
248 | inline constexpr unsigned int capacity() const noexcept | ||||
249 | { | ||||
250 | return G_N_ELEMENTS(m_seq->args)(sizeof (m_seq->args) / sizeof ((m_seq->args)[0])); | ||||
251 | } | ||||
252 | |||||
253 | /* param: | ||||
254 | * @idx: | ||||
255 | * @default_v: the value to use for default parameters | ||||
256 | * | ||||
257 | * Returns: the value of the parameter at index @idx, or @default_v if | ||||
258 | * the parameter at this index has default value, or the index | ||||
259 | * is out of bounds | ||||
260 | */ | ||||
261 | inline constexpr int param(unsigned int idx, | ||||
262 | int default_v = -1) const noexcept | ||||
263 | { | ||||
264 | return __builtin_expect(idx < size(), 1) ? bte_seq_arg_value(m_seq->args[idx], default_v) : default_v; | ||||
265 | } | ||||
266 | |||||
267 | /* param: | ||||
268 | * @idx: | ||||
269 | * @default_v: the value to use for default parameters | ||||
270 | * @min_v: the minimum value | ||||
271 | * @max_v: the maximum value | ||||
272 | * | ||||
273 | * Returns: the value of the parameter at index @idx, or @default_v if | ||||
274 | * the parameter at this index has default value, or the index | ||||
275 | * is out of bounds. The returned value is clamped to the | ||||
276 | * range @min_v..@max_v (or returns min_v, if min_v > max_v). | ||||
277 | */ | ||||
278 | inline constexpr int param(unsigned int idx, | ||||
279 | int default_v, | ||||
280 | int min_v, | ||||
281 | int max_v) const noexcept | ||||
282 | { | ||||
283 | auto v = param(idx, default_v); | ||||
284 | // not using std::clamp() since it's not guaranteed that min_v <= max_v | ||||
285 | return std::max(std::min(v, max_v), min_v); | ||||
286 | } | ||||
287 | |||||
288 | /* param_nonfinal: | ||||
289 | * @idx: | ||||
290 | * | ||||
291 | * Returns: whether the parameter at @idx is nonfinal, i.e. | ||||
292 | * there are more subparameters after it. | ||||
293 | */ | ||||
294 | inline constexpr bool param_nonfinal(unsigned int idx) const noexcept | ||||
295 | { | ||||
296 | return __builtin_expect(idx < size(), 1) ? bte_seq_arg_nonfinal(m_seq->args[idx]) : false; | ||||
297 | } | ||||
298 | |||||
299 | /* param_default: | ||||
300 | * @idx: | ||||
301 | * | ||||
302 | * Returns: whether the parameter at @idx has default value | ||||
303 | */ | ||||
304 | inline constexpr bool param_default(unsigned int idx) const noexcept | ||||
305 | { | ||||
306 | return __builtin_expect(idx < size(), 1) ? bte_seq_arg_default(m_seq->args[idx]) : true; | ||||
307 | } | ||||
308 | |||||
309 | /* next: | ||||
310 | * @idx: | ||||
311 | * | ||||
312 | * Returns: the index of the next parameter block | ||||
313 | */ | ||||
314 | inline constexpr unsigned int next(unsigned int idx) const noexcept | ||||
315 | { | ||||
316 | /* Find the final parameter */ | ||||
317 | while (param_nonfinal(idx)) | ||||
318 | ++idx; | ||||
319 | /* And return the index after that one */ | ||||
320 | return ++idx; | ||||
321 | } | ||||
322 | |||||
323 | inline constexpr unsigned int cbegin() const noexcept | ||||
324 | { | ||||
325 | return 0; | ||||
326 | } | ||||
327 | |||||
328 | inline constexpr unsigned int cend() const noexcept | ||||
329 | { | ||||
330 | return size(); | ||||
331 | } | ||||
332 | |||||
333 | /* collect: | ||||
334 | * | ||||
335 | * Collects some final parameters. | ||||
336 | * | ||||
337 | * Returns: %true if the sequence parameter list begins with | ||||
338 | * a run of final parameters that were collected. | ||||
339 | */ | ||||
340 | inline constexpr bool collect(unsigned int start_idx, | ||||
341 | std::initializer_list<int*> params, | ||||
342 | int default_v = -1) const noexcept | ||||
343 | { | ||||
344 | unsigned int idx = start_idx; | ||||
345 | for (auto i : params) { | ||||
346 | *i = param(idx, default_v); | ||||
347 | idx = next(idx); | ||||
348 | } | ||||
349 | |||||
350 | return (idx - start_idx) == params.size(); | ||||
351 | } | ||||
352 | |||||
353 | /* collect1: | ||||
354 | * @idx: | ||||
355 | * @default_v: | ||||
356 | * | ||||
357 | * Collects one final parameter. | ||||
358 | * | ||||
359 | * Returns: the parameter value, or @default_v if the parameter has | ||||
360 | * default value or is not a final parameter | ||||
361 | */ | ||||
362 | inline constexpr int collect1(unsigned int idx, | ||||
363 | int default_v = -1) const noexcept | ||||
364 | { | ||||
365 | return __builtin_expect(idx < size(), 1) ? bte_seq_arg_value_final(m_seq->args[idx], default_v) : default_v; | ||||
366 | } | ||||
367 | |||||
368 | /* collect1: | ||||
369 | * @idx: | ||||
370 | * @default_v: | ||||
371 | * @min_v: | ||||
372 | * @max_v | ||||
373 | * | ||||
374 | * Collects one final parameter. | ||||
375 | * | ||||
376 | * Returns: the parameter value clamped to the @min_v .. @max_v range (or @min_v, | ||||
377 | * if min_v > max_v), | ||||
378 | * or @default_v if the parameter has default value or is not a final parameter | ||||
379 | */ | ||||
380 | inline constexpr int collect1(unsigned int idx, | ||||
381 | int default_v, | ||||
382 | int min_v, | ||||
383 | int max_v) const noexcept | ||||
384 | { | ||||
385 | int v = __builtin_expect(idx < size(), 1) ? bte_seq_arg_value_final(m_seq->args[idx], default_v) : default_v; | ||||
386 | // not using std::clamp() since it's not guaranteed that min_v <= max_v | ||||
387 | return std::max(std::min(v, max_v), min_v); | ||||
388 | } | ||||
389 | |||||
390 | /* collect_subparams: | ||||
391 | * | ||||
392 | * Collects some subparameters. | ||||
393 | * | ||||
394 | * Returns: %true if the sequence parameter list contains enough | ||||
395 | * subparams at @start_idx | ||||
396 | */ | ||||
397 | inline constexpr bool collect_subparams(unsigned int start_idx, | ||||
398 | std::initializer_list<int*> params, | ||||
399 | int default_v = -1) const noexcept | ||||
400 | { | ||||
401 | unsigned int idx = start_idx; | ||||
402 | for (auto i : params) { | ||||
403 | *i = param(idx++, default_v); | ||||
404 | } | ||||
405 | |||||
406 | return idx <= next(start_idx); | ||||
407 | } | ||||
408 | |||||
409 | inline explicit operator bool() const { return m_seq != nullptr; } | ||||
410 | |||||
411 | /* This is only used in the test suite */ | ||||
412 | bte_seq_t** seq_ptr() { return &m_seq; } | ||||
413 | |||||
414 | private: | ||||
415 | bte_seq_t* m_seq{nullptr}; | ||||
416 | |||||
417 | char const* type_string() const; | ||||
418 | char const* command_string() const; | ||||
419 | }; // class Sequence | ||||
420 | |||||
421 | /* Helper classes to unify UTF-32 and UTF-8 versions of SequenceBuilder. | ||||
422 | * ::put will only be called with C1 controls, so it's ok to simplify | ||||
423 | * the UTF-8 version to simply prepend 0xc2. | ||||
424 | */ | ||||
425 | template<typename C> | ||||
426 | class DirectEncoder { | ||||
427 | public: | ||||
428 | using string_type = std::basic_string<C>; | ||||
429 | inline void put(string_type& s, C const c) const noexcept | ||||
430 | { | ||||
431 | s.push_back(c); | ||||
432 | } | ||||
433 | }; // class DirectEncoder | ||||
434 | |||||
435 | class UTF8Encoder { | ||||
436 | public: | ||||
437 | using string_type = std::basic_string<char>; | ||||
438 | inline void put(string_type& s, unsigned char const c) const noexcept | ||||
439 | { | ||||
440 | s.push_back(0xc2); | ||||
441 | s.push_back(c); | ||||
442 | } | ||||
443 | }; // class UTF8Encoder | ||||
444 | |||||
445 | template<class S, class E = DirectEncoder<typename S::value_type>> | ||||
446 | class SequenceBuilder { | ||||
447 | public: | ||||
448 | using string_type = S; | ||||
449 | using encoder_type = E; | ||||
450 | |||||
451 | private: | ||||
452 | bte_seq_t m_seq; | ||||
453 | string_type m_arg_str; | ||||
454 | unsigned char m_intermediates[4]; | ||||
455 | unsigned char m_n_intermediates{0}; | ||||
456 | unsigned char m_param_intro{0}; | ||||
457 | encoder_type m_encoder; | ||||
458 | |||||
459 | public: | ||||
460 | SequenceBuilder(unsigned int type = BTE_SEQ_NONE) | ||||
461 | { | ||||
462 | memset(&m_seq, 0, sizeof(m_seq)); | ||||
463 | set_type(type); | ||||
464 | } | ||||
465 | |||||
466 | SequenceBuilder(unsigned int type, | ||||
467 | uint32_t f) | ||||
468 | : SequenceBuilder(type) | ||||
469 | { | ||||
470 | set_final(f); | ||||
471 | } | ||||
472 | |||||
473 | SequenceBuilder(unsigned int type, | ||||
474 | string_type const& str) | ||||
475 | : SequenceBuilder(type) | ||||
476 | { | ||||
477 | set_string(str); | ||||
478 | } | ||||
479 | |||||
480 | SequenceBuilder(unsigned int type, | ||||
481 | string_type&& str) | ||||
482 | : SequenceBuilder(type) | ||||
483 | { | ||||
484 | set_string(str); | ||||
485 | } | ||||
486 | |||||
487 | SequenceBuilder(SequenceBuilder const&) = delete; | ||||
488 | SequenceBuilder(SequenceBuilder&&) = delete; | ||||
489 | ~SequenceBuilder() = default; | ||||
490 | |||||
491 | SequenceBuilder& operator= (SequenceBuilder const&) = delete; | ||||
492 | SequenceBuilder& operator= (SequenceBuilder&&) = delete; | ||||
493 | |||||
494 | inline constexpr unsigned int type() const noexcept { return m_seq.type; } | ||||
495 | |||||
496 | inline void set_type(unsigned int type) noexcept | ||||
497 | { | ||||
498 | m_seq.type = type; | ||||
499 | } | ||||
500 | |||||
501 | inline void set_final(uint32_t t) noexcept | ||||
502 | { | ||||
503 | m_seq.terminator = t; | ||||
504 | } | ||||
505 | |||||
506 | inline void append_intermediate(unsigned char i) noexcept | ||||
507 | { | ||||
508 | assert(unsigned(m_n_intermediates + 1) <= (sizeof(m_intermediates)/sizeof(m_intermediates[0])))(static_cast <bool> (unsigned(m_n_intermediates + 1) <= (sizeof(m_intermediates)/sizeof(m_intermediates[0]))) ? void (0) : __assert_fail ("unsigned(m_n_intermediates + 1) <= (sizeof(m_intermediates)/sizeof(m_intermediates[0]))" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||
509 | |||||
510 | m_intermediates[m_n_intermediates++] = i; | ||||
511 | } | ||||
512 | |||||
513 | inline void append_intermediates(std::initializer_list<unsigned char> l) noexcept | ||||
514 | { | ||||
515 | assert(m_n_intermediates + l.size() <= (sizeof(m_intermediates)/sizeof(m_intermediates[0])))(static_cast <bool> (m_n_intermediates + l.size() <= (sizeof(m_intermediates)/sizeof(m_intermediates[0]))) ? void (0) : __assert_fail ("m_n_intermediates + l.size() <= (sizeof(m_intermediates)/sizeof(m_intermediates[0]))" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||
516 | |||||
517 | for (uint32_t i : l) { | ||||
518 | m_intermediates[m_n_intermediates++] = i; | ||||
519 | } | ||||
520 | } | ||||
521 | |||||
522 | inline void set_param_intro(unsigned char p) noexcept | ||||
523 | { | ||||
524 | m_param_intro = p; | ||||
525 | } | ||||
526 | |||||
527 | inline void append_param(int p) noexcept | ||||
528 | { | ||||
529 | assert(m_seq.n_args + 1 <= (sizeof(m_seq.args) / sizeof(m_seq.args[0])))(static_cast <bool> (m_seq.n_args + 1 <= (sizeof(m_seq .args) / sizeof(m_seq.args[0]))) ? void (0) : __assert_fail ( "m_seq.n_args + 1 <= (sizeof(m_seq.args) / sizeof(m_seq.args[0]))" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||
530 | m_seq.args[m_seq.n_args++] = bte_seq_arg_init(std::min(p, 0xffff)); | ||||
531 | } | ||||
532 | |||||
533 | inline void append_params(std::initializer_list<int> params) noexcept | ||||
534 | { | ||||
535 | assert(m_seq.n_args + params.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0])))(static_cast <bool> (m_seq.n_args + params.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0]))) ? void (0) : __assert_fail ("m_seq.n_args + params.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0]))" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||
536 | for (int p : params) | ||||
537 | m_seq.args[m_seq.n_args++] = bte_seq_arg_init(std::min(p, 0xffff)); | ||||
538 | } | ||||
539 | |||||
540 | inline void append_subparams(std::initializer_list<int> subparams) noexcept | ||||
541 | { | ||||
542 | assert(m_seq.n_args + subparams.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0])))(static_cast <bool> (m_seq.n_args + subparams.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0]))) ? void (0) : __assert_fail ("m_seq.n_args + subparams.size() <= (sizeof(m_seq.args) / sizeof(m_seq.args[0]))" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||
543 | for (int p : subparams) { | ||||
544 | int* arg = &m_seq.args[m_seq.n_args++]; | ||||
545 | *arg = bte_seq_arg_init(std::min(p, 0xffff)); | ||||
546 | bte_seq_arg_finish(arg, false); | ||||
547 | } | ||||
548 | bte_seq_arg_refinish(&m_seq.args[m_seq.n_args - 1], true); | ||||
549 | } | ||||
550 | |||||
551 | inline void set_string(string_type const& str) noexcept | ||||
552 | { | ||||
553 | m_arg_str = str; | ||||
554 | } | ||||
555 | |||||
556 | inline void set_string(string_type&& str) noexcept | ||||
557 | { | ||||
558 | m_arg_str = str; | ||||
559 | } | ||||
560 | |||||
561 | enum class Introducer { | ||||
562 | NONE, | ||||
563 | DEFAULT, | ||||
564 | C0, | ||||
565 | C1 | ||||
566 | }; | ||||
567 | |||||
568 | enum class ST { | ||||
569 | NONE, | ||||
570 | DEFAULT, | ||||
571 | C0, | ||||
572 | C1, | ||||
573 | BEL | ||||
574 | }; | ||||
575 | |||||
576 | |||||
577 | private: | ||||
578 | void append_introducer_(string_type& s, | ||||
579 | bool c1 = true) const noexcept | ||||
580 | { | ||||
581 | /* Introducer */ | ||||
582 | if (c1) { | ||||
583 | switch (m_seq.type) { | ||||
584 | case BTE_SEQ_ESCAPE: m_encoder.put(s, 0x1b); break; // ESC | ||||
585 | case BTE_SEQ_CSI: m_encoder.put(s, 0x9b); break; // CSI | ||||
586 | case BTE_SEQ_DCS: m_encoder.put(s, 0x90); break; // DCS | ||||
587 | case BTE_SEQ_OSC: m_encoder.put(s, 0x9d); break; // OSC | ||||
588 | case BTE_SEQ_APC: m_encoder.put(s, 0x9f); break; // APC | ||||
589 | case BTE_SEQ_PM: m_encoder.put(s, 0x9e); break; // PM | ||||
590 | case BTE_SEQ_SOS: m_encoder.put(s, 0x98); break; // SOS | ||||
591 | case BTE_SEQ_SCI: m_encoder.put(s, 0x9a); break; // SCI | ||||
592 | default: return; | ||||
593 | } | ||||
594 | } else { | ||||
595 | s.push_back(0x1B); // ESC | ||||
596 | switch (m_seq.type) { | ||||
597 | case BTE_SEQ_ESCAPE: break; // nothing more | ||||
598 | case BTE_SEQ_CSI: s.push_back(0x5b); break; // [ | ||||
599 | case BTE_SEQ_DCS: s.push_back(0x50); break; // P | ||||
600 | case BTE_SEQ_OSC: s.push_back(0x5d); break; // ] | ||||
601 | case BTE_SEQ_APC: s.push_back(0x5f); break; // _ | ||||
602 | case BTE_SEQ_PM: s.push_back(0x5e); break; // ^ | ||||
603 | case BTE_SEQ_SOS: s.push_back(0x58); break; // X | ||||
604 | case BTE_SEQ_SCI: s.push_back(0x5a); break; // Z | ||||
605 | default: return; | ||||
606 | } | ||||
607 | } | ||||
608 | } | ||||
609 | |||||
610 | void append_introducer(string_type& s, | ||||
611 | bool c1 = true, | ||||
612 | Introducer introducer = Introducer::DEFAULT) const noexcept | ||||
613 | { | ||||
614 | switch (introducer) { | ||||
615 | case Introducer::NONE: | ||||
616 | break; | ||||
617 | case Introducer::DEFAULT: | ||||
618 | append_introducer_(s, c1); | ||||
619 | break; | ||||
620 | case Introducer::C0: | ||||
621 | append_introducer_(s, false); | ||||
622 | break; | ||||
623 | case Introducer::C1: | ||||
624 | append_introducer_(s, true); | ||||
625 | } | ||||
626 | } | ||||
627 | |||||
628 | void append_params(string_type& s) const noexcept | ||||
629 | { | ||||
630 | /* Parameters */ | ||||
631 | switch (m_seq.type) { | ||||
632 | case BTE_SEQ_CSI: | ||||
633 | case BTE_SEQ_DCS: { | ||||
634 | |||||
635 | if (m_param_intro != 0) | ||||
636 | s.push_back(m_param_intro); | ||||
637 | auto n_args = m_seq.n_args; | ||||
638 | for (unsigned int n = 0; n < n_args; n++) { | ||||
639 | auto arg = bte_seq_arg_value(m_seq.args[n]); | ||||
640 | if (n > 0) { | ||||
641 | s.push_back(";:"[bte_seq_arg_nonfinal(m_seq.args[n])]); | ||||
642 | } | ||||
643 | if (arg >= 0) { | ||||
644 | char buf[16]; | ||||
645 | int l = g_snprintf(buf, sizeof(buf), "%d", arg); | ||||
646 | for (int j = 0; j < l; j++) | ||||
647 | s.push_back(buf[j]); | ||||
648 | } | ||||
649 | } | ||||
650 | break; | ||||
651 | } | ||||
652 | default: | ||||
653 | break; | ||||
654 | } | ||||
655 | } | ||||
656 | |||||
657 | void append_intermediates_and_final(string_type& s) const noexcept | ||||
658 | { | ||||
659 | /* Intermediates and Final */ | ||||
660 | switch (m_seq.type) { | ||||
661 | case BTE_SEQ_ESCAPE: | ||||
662 | case BTE_SEQ_CSI: | ||||
663 | case BTE_SEQ_DCS: | ||||
664 | for (unsigned char n = 0; n < m_n_intermediates; n++) | ||||
665 | s.push_back(m_intermediates[n]); | ||||
666 | [[fallthrough]]; | ||||
667 | case BTE_SEQ_SCI: | ||||
668 | if (m_seq.terminator != 0) | ||||
669 | s.push_back(m_seq.terminator); | ||||
670 | break; | ||||
671 | default: | ||||
672 | break; | ||||
673 | } | ||||
674 | } | ||||
675 | |||||
676 | void append_arg_string(string_type& s, | ||||
677 | bool c1 = false, | ||||
678 | ssize_t max_arg_str_len = -1, | ||||
679 | ST st = ST::DEFAULT) const noexcept | ||||
680 | { | ||||
681 | /* String and ST */ | ||||
682 | switch (m_seq.type) { | ||||
683 | case BTE_SEQ_DCS: | ||||
684 | case BTE_SEQ_OSC: | ||||
685 | |||||
686 | if (max_arg_str_len < 0) | ||||
687 | s.append(m_arg_str, 0, max_arg_str_len); | ||||
688 | else | ||||
689 | s.append(m_arg_str); | ||||
690 | |||||
691 | switch (st) { | ||||
692 | case ST::NONE: | ||||
693 | // omit ST | ||||
694 | break; | ||||
695 | case ST::DEFAULT: | ||||
696 | if (c1) { | ||||
697 | m_encoder.put(s, 0x9c); // ST | ||||
698 | } else { | ||||
699 | s.push_back(0x1b); // ESC | ||||
700 | s.push_back(0x5c); // BACKSLASH | ||||
701 | } | ||||
702 | break; | ||||
703 | case ST::C0: | ||||
704 | s.push_back(0x1b); // ESC | ||||
705 | s.push_back(0x5c); // BACKSLASH | ||||
706 | break; | ||||
707 | case ST::C1: | ||||
708 | m_encoder.put(s, 0x9c); // ST | ||||
709 | break; | ||||
710 | case ST::BEL: | ||||
711 | s.push_back(0x7); // BEL | ||||
712 | break; | ||||
713 | default: | ||||
714 | break; | ||||
715 | } | ||||
716 | } | ||||
717 | } | ||||
718 | |||||
719 | public: | ||||
720 | void to_string(string_type& s, | ||||
721 | bool c1 = false, | ||||
722 | ssize_t max_arg_str_len = -1, | ||||
723 | Introducer introducer = Introducer::DEFAULT, | ||||
724 | ST st = ST::DEFAULT) const noexcept | ||||
725 | { | ||||
726 | append_introducer(s, c1, introducer); | ||||
727 | append_params(s); | ||||
728 | append_intermediates_and_final(s); | ||||
729 | append_arg_string(s, c1, max_arg_str_len, st); | ||||
730 | } | ||||
731 | |||||
732 | /* The following are only used in the test suite */ | ||||
733 | void reset_params() noexcept | ||||
734 | { | ||||
735 | m_seq.n_args = 0; | ||||
736 | } | ||||
737 | |||||
738 | void assert_equal(Sequence const& seq) const noexcept | ||||
739 | { | ||||
740 | g_assert_cmpuint(seq.type(), ==, m_seq.type)do { guint64 __n1 = (seq.type()), __n2 = (m_seq.type); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-glue.hh" , 740, ((const char*) (__PRETTY_FUNCTION__)), "seq.type()" " " "==" " " "m_seq.type", (long double) __n1, "==", (long double ) __n2, 'i'); } while (0); | ||||
741 | g_assert_cmphex(seq.terminator(), ==, m_seq.terminator)do { guint64 __n1 = (seq.terminator()), __n2 = (m_seq.terminator ); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar *) 0), "../src/parser-glue.hh", 741, ((const char*) (__PRETTY_FUNCTION__ )), "seq.terminator()" " " "==" " " "m_seq.terminator", (long double) __n1, "==", (long double) __n2, 'x'); } while (0); | ||||
742 | } | ||||
743 | |||||
744 | void assert_equal_full(Sequence const& seq) const noexcept | ||||
745 | { | ||||
746 | assert_equal(seq); | ||||
747 | |||||
748 | auto type = seq.type(); | ||||
749 | if (type
| ||||
750 | type == BTE_SEQ_DCS) { | ||||
751 | /* We may get one arg less back, if it's at default */ | ||||
752 | if (m_seq.n_args != seq.size()) { | ||||
753 | g_assert_cmpuint(m_seq.n_args, ==, seq.size() + 1)do { guint64 __n1 = (m_seq.n_args), __n2 = (seq.size() + 1); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0 ), "../src/parser-glue.hh", 753, ((const char*) (__PRETTY_FUNCTION__ )), "m_seq.n_args" " " "==" " " "seq.size() + 1", (long double ) __n1, "==", (long double) __n2, 'i'); } while (0); | ||||
754 | g_assert_true(bte_seq_arg_default(m_seq.args[m_seq.n_args - 1]))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_89 ; if (bte_seq_arg_default(m_seq.args[m_seq.n_args - 1])) _g_boolean_var_89 = 1; else _g_boolean_var_89 = 0; _g_boolean_var_89; }), 1)) ; else g_assertion_message (((gchar*) 0), "../src/parser-glue.hh" , 754, ((const char*) (__PRETTY_FUNCTION__)), "'" "bte_seq_arg_default(m_seq.args[m_seq.n_args - 1])" "' should be TRUE"); } while (0); | ||||
| |||||
755 | } | ||||
756 | for (unsigned int n = 0; n < seq.size(); n++) | ||||
757 | g_assert_cmpint(bte_seq_arg_value(m_seq.args[n]), ==, seq.param(n))do { gint64 __n1 = (bte_seq_arg_value(m_seq.args[n])), __n2 = (seq.param(n)); if (__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0), "../src/parser-glue.hh", 757, ((const char*) ( __PRETTY_FUNCTION__)), "bte_seq_arg_value(m_seq.args[n])" " " "==" " " "seq.param(n)", (long double) __n1, "==", (long double ) __n2, 'i'); } while (0); | ||||
758 | } | ||||
759 | } | ||||
760 | }; // class SequenceBuilder | ||||
761 | |||||
762 | using u8SequenceBuilder = SequenceBuilder<std::string, UTF8Encoder>; | ||||
763 | using u32SequenceBuilder = SequenceBuilder<std::u32string>; | ||||
764 | |||||
765 | class ReplyBuilder : public u8SequenceBuilder { | ||||
766 | public: | ||||
767 | ReplyBuilder(unsigned int reply, | ||||
768 | std::initializer_list<int> params) | ||||
769 | { | ||||
770 | switch (reply) { | ||||
771 | #define _BTE_REPLY_PARAMS(params) append_params(params); | ||||
772 | #define _BTE_REPLY_STRING(str) set_string(str); | ||||
773 | #define _BTE_REPLY(cmd,type,final,pintro,intermediate,code) \ | ||||
774 | case BTE_REPLY_##cmd: \ | ||||
775 | set_type(BTE_SEQ_##type); \ | ||||
776 | set_final(final); \ | ||||
777 | set_param_intro(BTE_SEQ_PARAMETER_CHAR_##pintro); \ | ||||
778 | if (BTE_SEQ_INTERMEDIATE_CHAR_##intermediate != BTE_SEQ_INTERMEDIATE_CHAR_NONE) \ | ||||
779 | append_intermediate(BTE_SEQ_INTERMEDIATE_CHAR_##intermediate); \ | ||||
780 | code \ | ||||
781 | break; | ||||
782 | #include "parser-reply.hh" | ||||
783 | #undef _BTE_REPLY | ||||
784 | #undef _BTE_REPLY_PARAMS | ||||
785 | #undef _BTE_REPLY_STRING | ||||
786 | default: | ||||
787 | assert(false)(static_cast <bool> (false) ? void (0) : __assert_fail ( "false", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); | ||||
788 | break; | ||||
789 | } | ||||
790 | append_params(params); | ||||
791 | } | ||||
792 | |||||
793 | }; // class ReplyBuilder | ||||
794 | |||||
795 | class StringTokeniser { | ||||
796 | public: | ||||
797 | using string_type = std::string; | ||||
798 | using char_type = std::string::value_type; | ||||
799 | |||||
800 | private: | ||||
801 | string_type const& m_string; | ||||
802 | char_type m_separator{';'}; | ||||
803 | |||||
804 | public: | ||||
805 | StringTokeniser(string_type& s, | ||||
806 | char_type separator = ';') | ||||
807 | : m_string{s}, | ||||
808 | m_separator{separator} | ||||
809 | { | ||||
810 | } | ||||
811 | |||||
812 | StringTokeniser(string_type&& s, | ||||
813 | char_type separator = ';') | ||||
814 | : m_string{s}, | ||||
815 | m_separator{separator} | ||||
816 | { | ||||
817 | } | ||||
818 | |||||
819 | StringTokeniser(StringTokeniser const&) = delete; | ||||
820 | StringTokeniser(StringTokeniser&&) = delete; | ||||
821 | ~StringTokeniser() = default; | ||||
822 | |||||
823 | StringTokeniser& operator=(StringTokeniser const&) = delete; | ||||
824 | StringTokeniser& operator=(StringTokeniser&&) = delete; | ||||
825 | |||||
826 | /* | ||||
827 | * const_iterator: | ||||
828 | * | ||||
829 | * InputIterator for string tokens. | ||||
830 | */ | ||||
831 | class const_iterator { | ||||
832 | public: | ||||
833 | using difference_type = ptrdiff_t; | ||||
834 | using value_type = string_type; | ||||
835 | using pointer = string_type; | ||||
836 | using reference = string_type; | ||||
837 | using iterator_category = std::input_iterator_tag; | ||||
838 | using size_type = string_type::size_type; | ||||
839 | |||||
840 | private: | ||||
841 | string_type const* m_string; | ||||
842 | char_type m_separator{';'}; | ||||
843 | string_type::size_type m_position; | ||||
844 | string_type::size_type m_next_separator; | ||||
845 | |||||
846 | public: | ||||
847 | const_iterator(string_type const* str, | ||||
848 | char_type separator, | ||||
849 | size_type position) | ||||
850 | : m_string{str}, | ||||
851 | m_separator{separator}, | ||||
852 | m_position{position}, | ||||
853 | m_next_separator{m_string->find(m_separator, m_position)} | ||||
854 | { | ||||
855 | } | ||||
856 | |||||
857 | const_iterator(string_type const* str, | ||||
858 | char_type separator) | ||||
859 | : m_string{str}, | ||||
860 | m_separator{separator}, | ||||
861 | m_position{string_type::npos}, | ||||
862 | m_next_separator{string_type::npos} | ||||
863 | { | ||||
864 | } | ||||
865 | |||||
866 | const_iterator(const_iterator const&) = default; | ||||
867 | const_iterator(const_iterator&& o) | ||||
868 | : m_string{o.m_string}, | ||||
869 | m_separator{o.m_separator}, | ||||
870 | m_position{o.m_position}, | ||||
871 | m_next_separator{o.m_next_separator} | ||||
872 | { | ||||
873 | } | ||||
874 | |||||
875 | ~const_iterator() = default; | ||||
876 | |||||
877 | const_iterator& operator=(const_iterator const& o) | ||||
878 | { | ||||
879 | m_string = o.m_string; | ||||
880 | m_separator = o.m_separator; | ||||
881 | m_position = o.m_position; | ||||
882 | m_next_separator = o.m_next_separator; | ||||
883 | return *this; | ||||
884 | } | ||||
885 | |||||
886 | const_iterator& operator=(const_iterator&& o) | ||||
887 | { | ||||
888 | m_string = std::move(o.m_string); | ||||
889 | m_separator = o.m_separator; | ||||
890 | m_position = o.m_position; | ||||
891 | m_next_separator = o.m_next_separator; | ||||
892 | return *this; | ||||
893 | } | ||||
894 | |||||
895 | inline bool operator==(const_iterator const& o) const noexcept | ||||
896 | { | ||||
897 | return m_position == o.m_position; | ||||
898 | } | ||||
899 | |||||
900 | inline bool operator!=(const_iterator const& o) const noexcept | ||||
901 | { | ||||
902 | return m_position != o.m_position; | ||||
903 | } | ||||
904 | |||||
905 | inline const_iterator& operator++() noexcept | ||||
906 | { | ||||
907 | if (m_next_separator != string_type::npos) { | ||||
908 | m_position = ++m_next_separator; | ||||
909 | m_next_separator = m_string->find(m_separator, m_position); | ||||
910 | } else | ||||
911 | m_position = string_type::npos; | ||||
912 | |||||
913 | return *this; | ||||
914 | } | ||||
915 | |||||
916 | /* | ||||
917 | * number: | ||||
918 | * | ||||
919 | * Returns the value of the iterator as a number, or -1 | ||||
920 | * if the string could not be parsed as a number, or | ||||
921 | * the parsed values exceeds the uint16_t range. | ||||
922 | * | ||||
923 | * Returns: true if a number was parsed | ||||
924 | */ | ||||
925 | bool number(int& v) const noexcept | ||||
926 | { | ||||
927 | auto const s = size(); | ||||
928 | if (s == 0) { | ||||
929 | v = -1; | ||||
930 | return true; | ||||
931 | } | ||||
932 | |||||
933 | v = 0; | ||||
934 | size_type i; | ||||
935 | for (i = 0; i < s; ++i) { | ||||
936 | char_type c = (*m_string)[m_position + i]; | ||||
937 | if (c < '0' || c > '9') | ||||
938 | return false; | ||||
939 | |||||
940 | v = v * 10 + (c - '0'); | ||||
941 | if (v > 0xffff) | ||||
942 | return false; | ||||
943 | } | ||||
944 | |||||
945 | /* All consumed? */ | ||||
946 | return i == s; | ||||
947 | } | ||||
948 | |||||
949 | inline size_type size() const noexcept | ||||
950 | { | ||||
951 | if (m_next_separator != string_type::npos) | ||||
952 | return m_next_separator - m_position; | ||||
953 | else | ||||
954 | return m_string->size() - m_position; | ||||
955 | } | ||||
956 | |||||
957 | inline size_type size_remaining() const noexcept | ||||
958 | { | ||||
959 | return m_string->size() - m_position; | ||||
960 | } | ||||
961 | |||||
962 | inline string_type operator*() const noexcept | ||||
963 | { | ||||
964 | return m_string->substr(m_position, size()); | ||||
965 | } | ||||
966 | |||||
967 | /* | ||||
968 | * string_remaining: | ||||
969 | * | ||||
970 | * Returns the whole string left, including possibly more separators. | ||||
971 | */ | ||||
972 | inline string_type string_remaining() const noexcept | ||||
973 | { | ||||
974 | return m_string->substr(m_position); | ||||
975 | } | ||||
976 | |||||
977 | inline void append(string_type& str) const noexcept | ||||
978 | { | ||||
979 | str.append(m_string->substr(m_position, size())); | ||||
980 | } | ||||
981 | |||||
982 | inline void append_remaining(string_type& str) const noexcept | ||||
983 | { | ||||
984 | str.append(m_string->substr(m_position)); | ||||
985 | } | ||||
986 | |||||
987 | }; // class const_iterator | ||||
988 | |||||
989 | inline const_iterator cbegin(char_type c = ';') const noexcept | ||||
990 | { | ||||
991 | return const_iterator(&m_string, m_separator, 0); | ||||
992 | } | ||||
993 | |||||
994 | inline const_iterator cend() const noexcept | ||||
995 | { | ||||
996 | return const_iterator(&m_string, m_separator); | ||||
997 | } | ||||
998 | |||||
999 | inline const_iterator begin(char_type c = ';') const noexcept | ||||
1000 | { | ||||
1001 | return cbegin(); | ||||
1002 | } | ||||
1003 | |||||
1004 | inline const_iterator end() const noexcept | ||||
1005 | { | ||||
1006 | return cend(); | ||||
1007 | } | ||||
1008 | |||||
1009 | }; // class StringTokeniser | ||||
1010 | |||||
1011 | } // namespace parser | ||||
1012 | |||||
1013 | } // namespace bte |