all repos — mgba @ fa884d071ecaa3e05ff20b45a67bf9500dd3d6b6

mGBA Game Boy Advance Emulator

src/util/test/text-codec.c (view raw)

  1/* Copyright (c) 2013-2016 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "util/test/suite.h"
  7
  8#include <mgba-util/text-codec.h>
  9#include <mgba-util/vfs.h>
 10
 11M_TEST_DEFINE(emptyCodec) {
 12	struct VFile* vf = VFileMemChunk(NULL, 0);
 13	struct TextCodec codec;
 14	assert_true(TextCodecLoadTBL(&codec, vf, true));
 15	TextCodecDeinit(&codec);
 16	vf->close(vf);
 17}
 18
 19M_TEST_DEFINE(singleEntry) {
 20	static const char file[] = "41=B";
 21	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
 22	struct TextCodec codec;
 23	assert_true(TextCodecLoadTBL(&codec, vf, false));
 24	struct TextCodecIterator iter;
 25	uint8_t output[16] = {};
 26	size_t len;
 27
 28	len = 0;
 29	TextCodecStartDecode(&codec, &iter);
 30	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 31	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 32	assert_int_equal(len, 1);
 33	assert_memory_equal(output, "B", 1);
 34
 35	len = 0;
 36	TextCodecStartDecode(&codec, &iter);
 37	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 38	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 39	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 40	assert_int_equal(len, 2);
 41	assert_memory_equal(output, "BB", 2);
 42
 43	len = 0;
 44	TextCodecStartDecode(&codec, &iter);
 45	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
 46	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 47	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 48	assert_int_equal(len, 1);
 49	assert_memory_equal(output, "B", 1);
 50
 51	len = 0;
 52	TextCodecStartDecode(&codec, &iter);
 53	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 54	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
 55	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 56	assert_int_equal(len, 1);
 57	assert_memory_equal(output, "B", 1);
 58
 59	len = 0;
 60	TextCodecStartDecode(&codec, &iter);
 61	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 62	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
 63	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
 64	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 65	assert_int_equal(len, 2);
 66	assert_memory_equal(output, "BB", 2);
 67
 68	TextCodecDeinit(&codec);
 69	vf->close(vf);
 70}
 71
 72M_TEST_DEFINE(singleEntryReverse) {
 73	static const char file[] = "41=B";
 74	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
 75	struct TextCodec codec;
 76	assert_true(TextCodecLoadTBL(&codec, vf, true));
 77	struct TextCodecIterator iter;
 78	uint8_t output[16] = {};
 79	size_t len;
 80
 81	len = 0;
 82	TextCodecStartEncode(&codec, &iter);
 83	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
 84	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 85	assert_int_equal(len, 1);
 86	assert_memory_equal(output, "A", 1);
 87
 88	len = 0;
 89	TextCodecStartEncode(&codec, &iter);
 90	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
 91	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
 92	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
 93	assert_int_equal(len, 2);
 94	assert_memory_equal(output, "AA", 2);
 95
 96	len = 0;
 97	TextCodecStartEncode(&codec, &iter);
 98	assert_int_equal(TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len), -1);
 99	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
100	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
101	assert_int_equal(len, 1);
102	assert_memory_equal(output, "A", 1);
103
104	len = 0;
105	TextCodecStartEncode(&codec, &iter);
106	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
107	assert_int_equal(TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len), -1);
108	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
109	assert_int_equal(len, 1);
110	assert_memory_equal(output, "A", 1);
111
112	len = 0;
113	TextCodecStartEncode(&codec, &iter);
114	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
115	assert_int_equal(TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len), -1);
116	len += TextCodecAdvance(&iter, 'B', output + len, sizeof(output) - len);
117	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
118	assert_int_equal(len, 2);
119	assert_memory_equal(output, "AA", 2);
120
121	TextCodecDeinit(&codec);
122	vf->close(vf);
123}
124
125M_TEST_DEFINE(twoEntry) {
126	static const char file[] =
127		"41=B\n"
128		"43=D";
129	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
130	struct TextCodec codec;
131	assert_true(TextCodecLoadTBL(&codec, vf, false));
132	struct TextCodecIterator iter;
133	uint8_t output[16] = {};
134	size_t len;
135
136	len = 0;
137	TextCodecStartDecode(&codec, &iter);
138	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
139	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
140	assert_int_equal(len, 1);
141	assert_memory_equal(output, "B", 1);
142
143	len = 0;
144	TextCodecStartDecode(&codec, &iter);
145	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
146	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
147	assert_int_equal(len, 1);
148	assert_memory_equal(output, "D", 1);
149
150	len = 0;
151	TextCodecStartDecode(&codec, &iter);
152	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
153	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
154	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
155	assert_int_equal(len, 2);
156	assert_memory_equal(output, "BB", 2);
157
158	len = 0;
159	TextCodecStartDecode(&codec, &iter);
160	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
161	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
162	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
163	assert_int_equal(len, 2);
164	assert_memory_equal(output, "DD", 2);
165
166	len = 0;
167	TextCodecStartDecode(&codec, &iter);
168	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
169	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
170	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
171	assert_int_equal(len, 2);
172	assert_memory_equal(output, "BD", 2);
173
174	len = 0;
175	TextCodecStartDecode(&codec, &iter);
176	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
177	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
178	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
179	assert_int_equal(len, 2);
180	assert_memory_equal(output, "DB", 2);
181
182	len = 0;
183	TextCodecStartDecode(&codec, &iter);
184	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
185	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
186	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
187	assert_int_equal(len, 1);
188	assert_memory_equal(output, "B", 1);
189
190	len = 0;
191	TextCodecStartDecode(&codec, &iter);
192	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
193	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
194	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
195	assert_int_equal(len, 1);
196	assert_memory_equal(output, "D", 1);
197
198	len = 0;
199	TextCodecStartDecode(&codec, &iter);
200	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
201	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
202	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
203	assert_int_equal(len, 1);
204	assert_memory_equal(output, "B", 1);
205
206	len = 0;
207	TextCodecStartDecode(&codec, &iter);
208	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
209	assert_int_equal(TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len), -1);
210	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
211	assert_int_equal(len, 1);
212	assert_memory_equal(output, "D", 1);
213
214	TextCodecDeinit(&codec);
215	vf->close(vf);
216}
217
218M_TEST_DEFINE(longEntry) {
219	static const char file[] =
220		"01=Ab\n"
221		"02=cd";
222	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
223	struct TextCodec codec;
224	assert_true(TextCodecLoadTBL(&codec, vf, false));
225	struct TextCodecIterator iter;
226	uint8_t output[16] = {};
227	size_t len;
228
229	len = 0;
230	TextCodecStartDecode(&codec, &iter);
231	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
232	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
233	assert_int_equal(len, 2);
234	assert_memory_equal(output, "Ab", 2);
235
236	len = 0;
237	TextCodecStartDecode(&codec, &iter);
238	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
239	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
240	assert_int_equal(len, 2);
241	assert_memory_equal(output, "cd", 2);
242
243	len = 0;
244	TextCodecStartDecode(&codec, &iter);
245	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
246	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
247	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
248	assert_int_equal(len, 4);
249	assert_memory_equal(output, "AbAb", 4);
250
251	len = 0;
252	TextCodecStartDecode(&codec, &iter);
253	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
254	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
255	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
256	assert_int_equal(len, 4);
257	assert_memory_equal(output, "cdcd", 4);
258
259	len = 0;
260	TextCodecStartDecode(&codec, &iter);
261	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
262	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
263	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
264	assert_int_equal(len, 4);
265	assert_memory_equal(output, "Abcd", 4);
266
267	len = 0;
268	TextCodecStartDecode(&codec, &iter);
269	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
270	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
271	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
272	assert_int_equal(len, 4);
273	assert_memory_equal(output, "cdAb", 4);
274
275	len = 0;
276	TextCodecStartDecode(&codec, &iter);
277	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
278	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
279	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
280	assert_int_equal(len, 2);
281	assert_memory_equal(output, "Ab", 2);
282
283	len = 0;
284	TextCodecStartDecode(&codec, &iter);
285	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
286	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
287	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
288	assert_int_equal(len, 2);
289	assert_memory_equal(output, "cd", 2);
290
291	len = 0;
292	TextCodecStartDecode(&codec, &iter);
293	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
294	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
295	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
296	assert_int_equal(len, 2);
297	assert_memory_equal(output, "Ab", 2);
298
299	len = 0;
300	TextCodecStartDecode(&codec, &iter);
301	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
302	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
303	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
304	assert_int_equal(len, 2);
305	assert_memory_equal(output, "cd", 2);
306
307	TextCodecDeinit(&codec);
308	vf->close(vf);
309}
310
311M_TEST_DEFINE(longEntryReverse) {
312	static const char file[] =
313		"01=Ab\n"
314		"02=cd";
315	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
316	struct TextCodec codec;
317	assert_true(TextCodecLoadTBL(&codec, vf, true));
318	struct TextCodecIterator iter;
319	uint8_t output[16] = {};
320	size_t len;
321
322	len = 0;
323	TextCodecStartEncode(&codec, &iter);
324	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
325	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
326	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
327	assert_int_equal(len, 1);
328	assert_memory_equal(output, "\1", 1);
329
330	len = 0;
331	TextCodecStartEncode(&codec, &iter);
332	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
333	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
334	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
335	assert_int_equal(len, 1);
336	assert_memory_equal(output, "\2", 1);
337
338	len = 0;
339	TextCodecStartEncode(&codec, &iter);
340	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
341	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
342	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
343	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
344	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
345	assert_int_equal(len, 2);
346	assert_memory_equal(output, "\1\1", 2);
347
348	len = 0;
349	TextCodecStartEncode(&codec, &iter);
350	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
351	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
352	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
353	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
354	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
355	assert_int_equal(len, 2);
356	assert_memory_equal(output, "\2\2", 2);
357
358	len = 0;
359	TextCodecStartEncode(&codec, &iter);
360	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
361	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
362	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
363	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
364	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
365	assert_int_equal(len, 2);
366	assert_memory_equal(output, "\1\2", 2);
367
368	len = 0;
369	TextCodecStartEncode(&codec, &iter);
370	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
371	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
372	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
373	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
374	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
375	assert_int_equal(len, 2);
376	assert_memory_equal(output, "\2\1", 2);
377
378	len = 0;
379	TextCodecStartEncode(&codec, &iter);
380	assert_int_equal(TextCodecAdvance(&iter, 'e', output + len, sizeof(output) - len), -1);
381	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
382	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
383	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
384	assert_int_equal(len, 1);
385	assert_memory_equal(output, "\1", 1);
386
387	len = 0;
388	TextCodecStartEncode(&codec, &iter);
389	assert_int_equal(TextCodecAdvance(&iter, 'e', output + len, sizeof(output) - len), -1);
390	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
391	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
392	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
393	assert_int_equal(len, 1);
394	assert_memory_equal(output, "\2", 1);
395
396	len = 0;
397	TextCodecStartEncode(&codec, &iter);
398	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
399	assert_int_equal(TextCodecAdvance(&iter, 'e', output + len, sizeof(output) - len), -1);
400	assert_int_equal(TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len), -1);
401	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
402	assert_int_equal(len, 0);
403
404	len = 0;
405	TextCodecStartEncode(&codec, &iter);
406	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
407	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
408	assert_int_equal(TextCodecAdvance(&iter, 'e', output + len, sizeof(output) - len), -1);
409	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
410	assert_int_equal(len, 1);
411	assert_memory_equal(output, "\1", 1);
412
413	len = 0;
414	TextCodecStartEncode(&codec, &iter);
415	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
416	assert_int_equal(TextCodecAdvance(&iter, 'e', output + len, sizeof(output) - len), -1);
417	assert_int_equal(TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len), -1);
418	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
419	assert_int_equal(len, 0);
420
421	len = 0;
422	TextCodecStartEncode(&codec, &iter);
423	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
424	len += TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len);
425	assert_int_equal(TextCodecAdvance(&iter, 'e', output + len, sizeof(output) - len), -1);
426	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
427	assert_int_equal(len, 1);
428	assert_memory_equal(output, "\2", 1);
429
430	TextCodecDeinit(&codec);
431	vf->close(vf);
432}
433
434M_TEST_DEFINE(overlappingEntry) {
435	static const char file[] =
436		"FF01=Ab\n"
437		"FF02=Ac";
438	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
439	struct TextCodec codec;
440	assert_true(TextCodecLoadTBL(&codec, vf, false));
441	struct TextCodecIterator iter;
442	uint8_t output[16] = {};
443	size_t len;
444
445	len = 0;
446	TextCodecStartDecode(&codec, &iter);
447	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
448	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
449	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
450	assert_int_equal(len, 2);
451	assert_memory_equal(output, "Ab", 2);
452
453	len = 0;
454	TextCodecStartDecode(&codec, &iter);
455	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
456	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
457	assert_int_equal(TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len), -1);
458	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
459	assert_int_equal(len, 2);
460	assert_memory_equal(output, "Ab", 2);
461
462	len = 0;
463	TextCodecStartDecode(&codec, &iter);
464	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
465	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
466	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
467	assert_int_equal(len, 2);
468	assert_memory_equal(output, "Ac", 2);
469
470	len = 0;
471	TextCodecStartDecode(&codec, &iter);
472	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
473	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
474	assert_int_equal(TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len), -1);
475	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
476	assert_int_equal(len, 2);
477	assert_memory_equal(output, "Ac", 2);
478
479	len = 0;
480	TextCodecStartDecode(&codec, &iter);
481	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
482	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
483	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
484	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
485	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
486	assert_int_equal(len, 4);
487	assert_memory_equal(output, "AbAb", 4);
488
489	len = 0;
490	TextCodecStartDecode(&codec, &iter);
491	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
492	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
493	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
494	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
495	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
496	assert_int_equal(len, 4);
497	assert_memory_equal(output, "AcAc", 4);
498
499	len = 0;
500	TextCodecStartDecode(&codec, &iter);
501	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
502	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
503	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
504	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
505	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
506	assert_int_equal(len, 4);
507	assert_memory_equal(output, "AbAc", 4);
508
509	len = 0;
510	TextCodecStartDecode(&codec, &iter);
511	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
512	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
513	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
514	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
515	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
516	assert_int_equal(len, 4);
517	assert_memory_equal(output, "AcAb", 4);
518
519	len = 0;
520	TextCodecStartDecode(&codec, &iter);
521	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
522	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
523	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
524	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
525	assert_int_equal(len, 2);
526	assert_memory_equal(output, "Ab", 2);
527
528	len = 0;
529	TextCodecStartDecode(&codec, &iter);
530	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
531	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
532	assert_int_equal(TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len), -1);
533	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
534	assert_int_equal(len, 0);
535
536	len = 0;
537	TextCodecStartDecode(&codec, &iter);
538	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
539	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
540	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
541	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
542	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
543	assert_int_equal(len, 2);
544	assert_memory_equal(output, "Ab", 2);
545
546	len = 0;
547	TextCodecStartDecode(&codec, &iter);
548	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
549	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
550	len += TextCodecAdvance(&iter, 0xFF, output + len, sizeof(output) - len);
551	assert_int_equal(TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len), -1);
552	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
553	assert_int_equal(len, 2);
554	assert_memory_equal(output, "Ab", 2);
555
556	TextCodecDeinit(&codec);
557	vf->close(vf);
558}
559
560M_TEST_DEFINE(overlappingEntryReverse) {
561	static const char file[] =
562		"FF01=Ab\n"
563		"FF02=Ac";
564	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
565	struct TextCodec codec;
566	assert_true(TextCodecLoadTBL(&codec, vf, true));
567	struct TextCodecIterator iter;
568	uint8_t output[16] = {};
569	size_t len;
570
571	len = 0;
572	TextCodecStartEncode(&codec, &iter);
573	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
574	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
575	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
576	assert_int_equal(len, 2);
577	assert_memory_equal(output, "\xFF\1", 2);
578
579	len = 0;
580	TextCodecStartEncode(&codec, &iter);
581	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
582	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
583	assert_int_equal(TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len), -1);
584	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
585	assert_int_equal(len, 2);
586	assert_memory_equal(output, "\xFF\1", 2);
587
588	len = 0;
589	TextCodecStartEncode(&codec, &iter);
590	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
591	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
592	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
593	assert_int_equal(len, 2);
594	assert_memory_equal(output, "\xFF\2", 2);
595
596	len = 0;
597	TextCodecStartEncode(&codec, &iter);
598	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
599	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
600	assert_int_equal(TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len), -1);
601	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
602	assert_int_equal(len, 2);
603	assert_memory_equal(output, "\xFF\2", 2);
604
605	len = 0;
606	TextCodecStartEncode(&codec, &iter);
607	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
608	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
609	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
610	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
611	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
612	assert_int_equal(len, 4);
613	assert_memory_equal(output, "\xFF\1\xFF\1", 4);
614
615	len = 0;
616	TextCodecStartEncode(&codec, &iter);
617	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
618	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
619	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
620	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
621	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
622	assert_int_equal(len, 4);
623	assert_memory_equal(output, "\xFF\2\xFF\2", 4);
624
625	len = 0;
626	TextCodecStartEncode(&codec, &iter);
627	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
628	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
629	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
630	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
631	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
632	assert_int_equal(len, 4);
633	assert_memory_equal(output, "\xFF\1\xFF\2", 4);
634
635	len = 0;
636	TextCodecStartEncode(&codec, &iter);
637	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
638	len += TextCodecAdvance(&iter, 'c', output + len, sizeof(output) - len);
639	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
640	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
641	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
642	assert_int_equal(len, 4);
643	assert_memory_equal(output, "\xFF\2\xFF\1", 4);
644
645	len = 0;
646	TextCodecStartEncode(&codec, &iter);
647	assert_int_equal(TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len), -1);
648	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
649	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
650	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
651	assert_int_equal(len, 2);
652	assert_memory_equal(output, "\xFF\1", 2);
653
654	len = 0;
655	TextCodecStartEncode(&codec, &iter);
656	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
657	assert_int_equal(TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len), -1);
658	assert_int_equal(TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len), -1);
659	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
660	assert_int_equal(len, 0);
661
662	len = 0;
663	TextCodecStartEncode(&codec, &iter);
664	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
665	assert_int_equal(TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len), -1);
666	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
667	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
668	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
669	assert_int_equal(len, 2);
670	assert_memory_equal(output, "\xFF\1", 2);
671
672	len = 0;
673	TextCodecStartEncode(&codec, &iter);
674	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
675	len += TextCodecAdvance(&iter, 'b', output + len, sizeof(output) - len);
676	len += TextCodecAdvance(&iter, 'A', output + len, sizeof(output) - len);
677	assert_int_equal(TextCodecAdvance(&iter, 'd', output + len, sizeof(output) - len), -1);
678	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
679	assert_int_equal(len, 2);
680	assert_memory_equal(output, "\xFF\1", 2);
681
682	TextCodecDeinit(&codec);
683	vf->close(vf);
684}
685
686M_TEST_DEFINE(raggedEntry) {
687	static const char file[] =
688		"4142=bc\n"
689		"41=B\n"
690		"42=C";
691	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
692	struct TextCodec codec;
693	assert_true(TextCodecLoadTBL(&codec, vf, false));
694	struct TextCodecIterator iter;
695	uint8_t output[16] = {};
696	size_t len;
697
698	len = 0;
699	TextCodecStartDecode(&codec, &iter);
700	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
701	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
702	assert_int_equal(len, 1);
703	assert_memory_equal(output, "B", 1);
704
705	len = 0;
706	TextCodecStartDecode(&codec, &iter);
707	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
708	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
709	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
710	assert_int_equal(len, 2);
711	assert_memory_equal(output, "BB", 2);
712
713	len = 0;
714	TextCodecStartDecode(&codec, &iter);
715	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
716	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
717	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
718	assert_int_equal(len, 2);
719	assert_memory_equal(output, "CB", 2);
720
721	len = 0;
722	TextCodecStartDecode(&codec, &iter);
723	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
724	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
725	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
726	assert_int_equal(len, 2);
727	assert_memory_equal(output, "bc", 2);
728
729	len = 0;
730	TextCodecStartDecode(&codec, &iter);
731	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
732	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
733	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
734	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
735	assert_int_equal(len, 3);
736	assert_memory_equal(output, "bcB", 3);
737
738	len = 0;
739	TextCodecStartDecode(&codec, &iter);
740	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
741	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
742	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
743	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
744	assert_int_equal(len, 3);
745	assert_memory_equal(output, "Bbc", 3);
746
747	len = 0;
748	TextCodecStartDecode(&codec, &iter);
749	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
750	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
751	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
752	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
753	assert_int_equal(len, 3);
754	assert_memory_equal(output, "bcC", 3);
755
756	len = 0;
757	TextCodecStartDecode(&codec, &iter);
758	len += TextCodecAdvance(&iter, 0x41, output + len, sizeof(output) - len);
759	len += TextCodecAdvance(&iter, 0x43, output + len, sizeof(output) - len);
760	len += TextCodecAdvance(&iter, 0x42, output + len, sizeof(output) - len);
761	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
762	assert_int_equal(len, 2);
763	assert_memory_equal(output, "BC", 2);
764
765	TextCodecDeinit(&codec);
766	vf->close(vf);
767}
768
769M_TEST_DEFINE(controlCodes) {
770	static const char file[] =
771		"*=01\n"
772		"/=02\n"
773		"\\=03";
774	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
775	struct TextCodec codec;
776	assert_true(TextCodecLoadTBL(&codec, vf, true));
777	struct TextCodecIterator iter;
778	uint8_t output[16] = {};
779	size_t len;
780
781	len = 0;
782	TextCodecStartDecode(&codec, &iter);
783	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
784	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
785	assert_int_equal(len, 1);
786	assert_memory_equal(output, "\n", 1);
787
788	len = 0;
789	TextCodecStartDecode(&codec, &iter);
790	len += TextCodecAdvance(&iter, 2, output + len, sizeof(output) - len);
791	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
792	assert_int_equal(len, 1);
793	assert_memory_equal(output, "\x1F", 1);
794
795	len = 0;
796	TextCodecStartDecode(&codec, &iter);
797	len += TextCodecAdvance(&iter, 3, output + len, sizeof(output) - len);
798	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
799	assert_int_equal(len, 1);
800	assert_memory_equal(output, "\x1E", 1);
801
802	len = 0;
803	TextCodecStartEncode(&codec, &iter);
804	len += TextCodecAdvance(&iter, '\n', output + len, sizeof(output) - len);
805	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
806	assert_int_equal(len, 1);
807	assert_memory_equal(output, "\1", 1);
808
809	len = 0;
810	TextCodecStartEncode(&codec, &iter);
811	len += TextCodecAdvance(&iter, '\x1F', output + len, sizeof(output) - len);
812	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
813	assert_int_equal(len, 1);
814	assert_memory_equal(output, "\2", 1);
815
816	len = 0;
817	TextCodecStartEncode(&codec, &iter);
818	len += TextCodecAdvance(&iter, '\x1E', output + len, sizeof(output) - len);
819	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
820	assert_int_equal(len, 1);
821	assert_memory_equal(output, "\3", 1);
822
823	TextCodecDeinit(&codec);
824	vf->close(vf);
825}
826
827M_TEST_DEFINE(nullBytes) {
828	static const char file[] =
829		"00=A\n"
830		"0000=a\n"
831		"0001=b\n"
832		"01=B\n"
833		"0100=c";
834	struct VFile* vf = VFileFromConstMemory(file, sizeof(file) - 1);
835	struct TextCodec codec;
836	assert_true(TextCodecLoadTBL(&codec, vf, false));
837	struct TextCodecIterator iter;
838	uint8_t output[16] = {};
839	size_t len;
840
841	len = 0;
842	TextCodecStartDecode(&codec, &iter);
843	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
844	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
845	assert_int_equal(len, 1);
846	assert_memory_equal(output, "A", 1);
847
848	len = 0;
849	TextCodecStartDecode(&codec, &iter);
850	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
851	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
852	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
853	assert_int_equal(len, 1);
854	assert_memory_equal(output, "a", 1);
855
856	len = 0;
857	TextCodecStartDecode(&codec, &iter);
858	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
859	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
860	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
861	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
862	assert_int_equal(len, 2);
863	assert_memory_equal(output, "aA", 2);
864
865	len = 0;
866	TextCodecStartDecode(&codec, &iter);
867	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
868	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
869	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
870	assert_int_equal(len, 1);
871	assert_memory_equal(output, "b", 1);
872
873	len = 0;
874	TextCodecStartDecode(&codec, &iter);
875	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
876	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
877	assert_int_equal(len, 1);
878	assert_memory_equal(output, "B", 1);
879
880	len = 0;
881	TextCodecStartDecode(&codec, &iter);
882	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
883	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
884	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
885	assert_int_equal(len, 1);
886	assert_memory_equal(output, "c", 1);
887
888	len = 0;
889	TextCodecStartDecode(&codec, &iter);
890	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
891	len += TextCodecAdvance(&iter, 0, output + len, sizeof(output) - len);
892	len += TextCodecAdvance(&iter, 1, output + len, sizeof(output) - len);
893	len += TextCodecFinish(&iter, output + len, sizeof(output) - len);
894	assert_int_equal(len, 2);
895	assert_memory_equal(output, "cB", 2);
896
897	TextCodecDeinit(&codec);
898	vf->close(vf);
899}
900
901M_TEST_SUITE_DEFINE(TextCodec,
902	cmocka_unit_test(emptyCodec),
903	cmocka_unit_test(singleEntry),
904	cmocka_unit_test(singleEntryReverse),
905	cmocka_unit_test(twoEntry),
906	cmocka_unit_test(longEntry),
907	cmocka_unit_test(longEntryReverse),
908	cmocka_unit_test(overlappingEntry),
909	cmocka_unit_test(overlappingEntryReverse),
910	cmocka_unit_test(raggedEntry),
911	cmocka_unit_test(controlCodes),
912	cmocka_unit_test(nullBytes))