10a48773fSEric van Gyzen /*
20a48773fSEric van Gyzen __ __ _
30a48773fSEric van Gyzen ___\ \/ /_ __ __ _| |_
40a48773fSEric van Gyzen / _ \\ /| '_ \ / _` | __|
50a48773fSEric van Gyzen | __// \| |_) | (_| | |_
60a48773fSEric van Gyzen \___/_/\_\ .__/ \__,_|\__|
70a48773fSEric van Gyzen |_| XML parser
80a48773fSEric van Gyzen
9cc68614dSXin LI Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
10*4543ef51SXin LI Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
11*4543ef51SXin LI Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
120a48773fSEric van Gyzen Licensed under the MIT license:
130a48773fSEric van Gyzen
140a48773fSEric van Gyzen Permission is hereby granted, free of charge, to any person obtaining
150a48773fSEric van Gyzen a copy of this software and associated documentation files (the
160a48773fSEric van Gyzen "Software"), to deal in the Software without restriction, including
170a48773fSEric van Gyzen without limitation the rights to use, copy, modify, merge, publish,
180a48773fSEric van Gyzen distribute, sublicense, and/or sell copies of the Software, and to permit
190a48773fSEric van Gyzen persons to whom the Software is furnished to do so, subject to the
200a48773fSEric van Gyzen following conditions:
210a48773fSEric van Gyzen
220a48773fSEric van Gyzen The above copyright notice and this permission notice shall be included
230a48773fSEric van Gyzen in all copies or substantial portions of the Software.
240a48773fSEric van Gyzen
250a48773fSEric van Gyzen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
260a48773fSEric van Gyzen EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
270a48773fSEric van Gyzen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
280a48773fSEric van Gyzen NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
290a48773fSEric van Gyzen DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
300a48773fSEric van Gyzen OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
310a48773fSEric van Gyzen USE OR OTHER DEALINGS IN THE SOFTWARE.
320a48773fSEric van Gyzen */
330a48773fSEric van Gyzen
34*4543ef51SXin LI #if defined(NDEBUG)
35*4543ef51SXin LI # undef NDEBUG /* because test suite relies on assert(...) at the moment */
36*4543ef51SXin LI #endif
37*4543ef51SXin LI
380a48773fSEric van Gyzen #include "expat_config.h"
390a48773fSEric van Gyzen
400a48773fSEric van Gyzen #include <assert.h>
410a48773fSEric van Gyzen #include <stdlib.h>
420a48773fSEric van Gyzen #include <stdio.h>
430a48773fSEric van Gyzen #include <string.h>
440a48773fSEric van Gyzen
450a48773fSEric van Gyzen #include "structdata.h"
460a48773fSEric van Gyzen #include "minicheck.h"
470a48773fSEric van Gyzen
480a48773fSEric van Gyzen #define STRUCT_EXTENSION_COUNT 8
490a48773fSEric van Gyzen
500a48773fSEric van Gyzen #ifdef XML_UNICODE_WCHAR_T
510a48773fSEric van Gyzen # include <wchar.h>
520a48773fSEric van Gyzen # define XML_FMT_STR "ls"
530a48773fSEric van Gyzen # define xcstrlen(s) wcslen(s)
540a48773fSEric van Gyzen # define xcstrcmp(s, t) wcscmp((s), (t))
550a48773fSEric van Gyzen #else
560a48773fSEric van Gyzen # define XML_FMT_STR "s"
570a48773fSEric van Gyzen # define xcstrlen(s) strlen(s)
580a48773fSEric van Gyzen # define xcstrcmp(s, t) strcmp((s), (t))
590a48773fSEric van Gyzen #endif
600a48773fSEric van Gyzen
610a48773fSEric van Gyzen static XML_Char *
xmlstrdup(const XML_Char * s)626b2c1e49SXin LI xmlstrdup(const XML_Char *s) {
630a48773fSEric van Gyzen size_t byte_count = (xcstrlen(s) + 1) * sizeof(XML_Char);
64*4543ef51SXin LI XML_Char *const dup = (XML_Char *)malloc(byte_count);
650a48773fSEric van Gyzen
660a48773fSEric van Gyzen assert(dup != NULL);
670a48773fSEric van Gyzen memcpy(dup, s, byte_count);
680a48773fSEric van Gyzen return dup;
690a48773fSEric van Gyzen }
700a48773fSEric van Gyzen
710a48773fSEric van Gyzen void
StructData_Init(StructData * storage)726b2c1e49SXin LI StructData_Init(StructData *storage) {
730a48773fSEric van Gyzen assert(storage != NULL);
740a48773fSEric van Gyzen storage->count = 0;
750a48773fSEric van Gyzen storage->max_count = 0;
760a48773fSEric van Gyzen storage->entries = NULL;
770a48773fSEric van Gyzen }
780a48773fSEric van Gyzen
790a48773fSEric van Gyzen void
StructData_AddItem(StructData * storage,const XML_Char * s,int data0,int data1,int data2)806b2c1e49SXin LI StructData_AddItem(StructData *storage, const XML_Char *s, int data0, int data1,
816b2c1e49SXin LI int data2) {
820a48773fSEric van Gyzen StructDataEntry *entry;
830a48773fSEric van Gyzen
840a48773fSEric van Gyzen assert(storage != NULL);
850a48773fSEric van Gyzen assert(s != NULL);
860a48773fSEric van Gyzen if (storage->count == storage->max_count) {
87*4543ef51SXin LI StructDataEntry *new_entries;
880a48773fSEric van Gyzen
890a48773fSEric van Gyzen storage->max_count += STRUCT_EXTENSION_COUNT;
90*4543ef51SXin LI new_entries = (StructDataEntry *)realloc(
91*4543ef51SXin LI storage->entries, storage->max_count * sizeof(StructDataEntry));
92*4543ef51SXin LI assert(new_entries != NULL);
93*4543ef51SXin LI storage->entries = new_entries;
940a48773fSEric van Gyzen }
950a48773fSEric van Gyzen
960a48773fSEric van Gyzen entry = &storage->entries[storage->count];
970a48773fSEric van Gyzen entry->str = xmlstrdup(s);
980a48773fSEric van Gyzen entry->data0 = data0;
990a48773fSEric van Gyzen entry->data1 = data1;
1000a48773fSEric van Gyzen entry->data2 = data2;
1010a48773fSEric van Gyzen storage->count++;
1020a48773fSEric van Gyzen }
1030a48773fSEric van Gyzen
1040a48773fSEric van Gyzen /* 'fail()' aborts the function via a longjmp, so there is no point
1050a48773fSEric van Gyzen * in returning a value from this function.
1060a48773fSEric van Gyzen */
1070a48773fSEric van Gyzen void
StructData_CheckItems(StructData * storage,const StructDataEntry * expected,int count)1086b2c1e49SXin LI StructData_CheckItems(StructData *storage, const StructDataEntry *expected,
1096b2c1e49SXin LI int count) {
1100a48773fSEric van Gyzen char buffer[1024];
1110a48773fSEric van Gyzen
1120a48773fSEric van Gyzen assert(storage != NULL);
1130a48773fSEric van Gyzen assert(expected != NULL);
1140a48773fSEric van Gyzen if (count != storage->count) {
115*4543ef51SXin LI snprintf(buffer, sizeof(buffer),
116*4543ef51SXin LI "wrong number of entries: got %d, expected %d", storage->count,
117*4543ef51SXin LI count);
1180a48773fSEric van Gyzen StructData_Dispose(storage);
1190a48773fSEric van Gyzen fail(buffer);
1206b2c1e49SXin LI } else {
121*4543ef51SXin LI for (int i = 0; i < count; i++) {
1220a48773fSEric van Gyzen const StructDataEntry *got = &storage->entries[i];
1230a48773fSEric van Gyzen const StructDataEntry *want = &expected[i];
1240a48773fSEric van Gyzen
1256b2c1e49SXin LI assert(got != NULL);
1266b2c1e49SXin LI assert(want != NULL);
1276b2c1e49SXin LI
1280a48773fSEric van Gyzen if (xcstrcmp(got->str, want->str) != 0) {
1290a48773fSEric van Gyzen StructData_Dispose(storage);
1300a48773fSEric van Gyzen fail("structure got bad string");
1316b2c1e49SXin LI } else {
1326b2c1e49SXin LI if (got->data0 != want->data0 || got->data1 != want->data1
1336b2c1e49SXin LI || got->data2 != want->data2) {
134*4543ef51SXin LI snprintf(buffer, sizeof(buffer),
1350a48773fSEric van Gyzen "struct '%" XML_FMT_STR
1360a48773fSEric van Gyzen "' expected (%d,%d,%d), got (%d,%d,%d)",
1376b2c1e49SXin LI got->str, want->data0, want->data1, want->data2, got->data0,
1386b2c1e49SXin LI got->data1, got->data2);
1390a48773fSEric van Gyzen StructData_Dispose(storage);
1400a48773fSEric van Gyzen fail(buffer);
1410a48773fSEric van Gyzen }
1420a48773fSEric van Gyzen }
1430a48773fSEric van Gyzen }
1446b2c1e49SXin LI }
1456b2c1e49SXin LI }
1460a48773fSEric van Gyzen
1470a48773fSEric van Gyzen void
StructData_Dispose(StructData * storage)1486b2c1e49SXin LI StructData_Dispose(StructData *storage) {
1490a48773fSEric van Gyzen int i;
1500a48773fSEric van Gyzen
1510a48773fSEric van Gyzen assert(storage != NULL);
1520a48773fSEric van Gyzen for (i = 0; i < storage->count; i++)
1530a48773fSEric van Gyzen free((void *)storage->entries[i].str);
1540a48773fSEric van Gyzen free(storage->entries);
1556b2c1e49SXin LI
1566b2c1e49SXin LI storage->count = 0;
1576b2c1e49SXin LI storage->entries = NULL;
1580a48773fSEric van Gyzen }
159