19b8e2351Sbluhm /*
29b8e2351Sbluhm __ __ _
39b8e2351Sbluhm ___\ \/ /_ __ __ _| |_
49b8e2351Sbluhm / _ \\ /| '_ \ / _` | __|
59b8e2351Sbluhm | __// \| |_) | (_| | |_
69b8e2351Sbluhm \___/_/\_\ .__/ \__,_|\__|
79b8e2351Sbluhm |_| XML parser
89b8e2351Sbluhm
908819b41Sbluhm Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
10*bd8f1dc3Sbluhm Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
11*bd8f1dc3Sbluhm Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
129b8e2351Sbluhm Licensed under the MIT license:
139b8e2351Sbluhm
149b8e2351Sbluhm Permission is hereby granted, free of charge, to any person obtaining
159b8e2351Sbluhm a copy of this software and associated documentation files (the
169b8e2351Sbluhm "Software"), to deal in the Software without restriction, including
179b8e2351Sbluhm without limitation the rights to use, copy, modify, merge, publish,
189b8e2351Sbluhm distribute, sublicense, and/or sell copies of the Software, and to permit
199b8e2351Sbluhm persons to whom the Software is furnished to do so, subject to the
209b8e2351Sbluhm following conditions:
219b8e2351Sbluhm
229b8e2351Sbluhm The above copyright notice and this permission notice shall be included
239b8e2351Sbluhm in all copies or substantial portions of the Software.
249b8e2351Sbluhm
259b8e2351Sbluhm THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
269b8e2351Sbluhm EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
279b8e2351Sbluhm MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
289b8e2351Sbluhm NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
299b8e2351Sbluhm DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
309b8e2351Sbluhm OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
319b8e2351Sbluhm USE OR OTHER DEALINGS IN THE SOFTWARE.
329b8e2351Sbluhm */
339b8e2351Sbluhm
34*bd8f1dc3Sbluhm #if defined(NDEBUG)
35*bd8f1dc3Sbluhm # undef NDEBUG /* because test suite relies on assert(...) at the moment */
36*bd8f1dc3Sbluhm #endif
37*bd8f1dc3Sbluhm
389b8e2351Sbluhm #include "expat_config.h"
399b8e2351Sbluhm
409b8e2351Sbluhm #include <assert.h>
419b8e2351Sbluhm #include <stdlib.h>
429b8e2351Sbluhm #include <stdio.h>
439b8e2351Sbluhm #include <string.h>
449b8e2351Sbluhm
459b8e2351Sbluhm #include "structdata.h"
469b8e2351Sbluhm #include "minicheck.h"
479b8e2351Sbluhm
489b8e2351Sbluhm #define STRUCT_EXTENSION_COUNT 8
499b8e2351Sbluhm
509b8e2351Sbluhm #ifdef XML_UNICODE_WCHAR_T
519b8e2351Sbluhm # include <wchar.h>
529b8e2351Sbluhm # define XML_FMT_STR "ls"
539b8e2351Sbluhm # define xcstrlen(s) wcslen(s)
549b8e2351Sbluhm # define xcstrcmp(s, t) wcscmp((s), (t))
559b8e2351Sbluhm #else
569b8e2351Sbluhm # define XML_FMT_STR "s"
579b8e2351Sbluhm # define xcstrlen(s) strlen(s)
589b8e2351Sbluhm # define xcstrcmp(s, t) strcmp((s), (t))
599b8e2351Sbluhm #endif
609b8e2351Sbluhm
619b8e2351Sbluhm static XML_Char *
xmlstrdup(const XML_Char * s)6228ce3119Sbluhm xmlstrdup(const XML_Char *s) {
63797786e5Sbluhm size_t byte_count = (xcstrlen(s) + 1) * sizeof(XML_Char);
64*bd8f1dc3Sbluhm XML_Char *const dup = (XML_Char *)malloc(byte_count);
659b8e2351Sbluhm
669b8e2351Sbluhm assert(dup != NULL);
679b8e2351Sbluhm memcpy(dup, s, byte_count);
689b8e2351Sbluhm return dup;
699b8e2351Sbluhm }
709b8e2351Sbluhm
719b8e2351Sbluhm void
StructData_Init(StructData * storage)7228ce3119Sbluhm StructData_Init(StructData *storage) {
739b8e2351Sbluhm assert(storage != NULL);
749b8e2351Sbluhm storage->count = 0;
759b8e2351Sbluhm storage->max_count = 0;
769b8e2351Sbluhm storage->entries = NULL;
779b8e2351Sbluhm }
789b8e2351Sbluhm
799b8e2351Sbluhm void
StructData_AddItem(StructData * storage,const XML_Char * s,int data0,int data1,int data2)8028ce3119Sbluhm StructData_AddItem(StructData *storage, const XML_Char *s, int data0, int data1,
8128ce3119Sbluhm int data2) {
829b8e2351Sbluhm StructDataEntry *entry;
839b8e2351Sbluhm
849b8e2351Sbluhm assert(storage != NULL);
859b8e2351Sbluhm assert(s != NULL);
869b8e2351Sbluhm if (storage->count == storage->max_count) {
87*bd8f1dc3Sbluhm StructDataEntry *new_entries;
889b8e2351Sbluhm
899b8e2351Sbluhm storage->max_count += STRUCT_EXTENSION_COUNT;
90*bd8f1dc3Sbluhm new_entries = (StructDataEntry *)realloc(
91*bd8f1dc3Sbluhm storage->entries, storage->max_count * sizeof(StructDataEntry));
92*bd8f1dc3Sbluhm assert(new_entries != NULL);
93*bd8f1dc3Sbluhm storage->entries = new_entries;
949b8e2351Sbluhm }
959b8e2351Sbluhm
969b8e2351Sbluhm entry = &storage->entries[storage->count];
979b8e2351Sbluhm entry->str = xmlstrdup(s);
989b8e2351Sbluhm entry->data0 = data0;
999b8e2351Sbluhm entry->data1 = data1;
1009b8e2351Sbluhm entry->data2 = data2;
1019b8e2351Sbluhm storage->count++;
1029b8e2351Sbluhm }
1039b8e2351Sbluhm
1049b8e2351Sbluhm /* 'fail()' aborts the function via a longjmp, so there is no point
1059b8e2351Sbluhm * in returning a value from this function.
1069b8e2351Sbluhm */
1079b8e2351Sbluhm void
StructData_CheckItems(StructData * storage,const StructDataEntry * expected,int count)10828ce3119Sbluhm StructData_CheckItems(StructData *storage, const StructDataEntry *expected,
10928ce3119Sbluhm int count) {
1109b8e2351Sbluhm char buffer[1024];
1119b8e2351Sbluhm
1129b8e2351Sbluhm assert(storage != NULL);
1139b8e2351Sbluhm assert(expected != NULL);
1149b8e2351Sbluhm if (count != storage->count) {
115*bd8f1dc3Sbluhm snprintf(buffer, sizeof(buffer),
116*bd8f1dc3Sbluhm "wrong number of entries: got %d, expected %d", storage->count,
117*bd8f1dc3Sbluhm count);
1189b8e2351Sbluhm StructData_Dispose(storage);
1199b8e2351Sbluhm fail(buffer);
12028ce3119Sbluhm } else {
121*bd8f1dc3Sbluhm for (int i = 0; i < count; i++) {
1229b8e2351Sbluhm const StructDataEntry *got = &storage->entries[i];
1239b8e2351Sbluhm const StructDataEntry *want = &expected[i];
1249b8e2351Sbluhm
12528ce3119Sbluhm assert(got != NULL);
12628ce3119Sbluhm assert(want != NULL);
12728ce3119Sbluhm
1289b8e2351Sbluhm if (xcstrcmp(got->str, want->str) != 0) {
1299b8e2351Sbluhm StructData_Dispose(storage);
1309b8e2351Sbluhm fail("structure got bad string");
13128ce3119Sbluhm } else {
13228ce3119Sbluhm if (got->data0 != want->data0 || got->data1 != want->data1
13328ce3119Sbluhm || got->data2 != want->data2) {
134*bd8f1dc3Sbluhm snprintf(buffer, sizeof(buffer),
1359b8e2351Sbluhm "struct '%" XML_FMT_STR
1369b8e2351Sbluhm "' expected (%d,%d,%d), got (%d,%d,%d)",
13728ce3119Sbluhm got->str, want->data0, want->data1, want->data2, got->data0,
13828ce3119Sbluhm got->data1, got->data2);
1399b8e2351Sbluhm StructData_Dispose(storage);
1409b8e2351Sbluhm fail(buffer);
1419b8e2351Sbluhm }
1429b8e2351Sbluhm }
1439b8e2351Sbluhm }
14428ce3119Sbluhm }
14528ce3119Sbluhm }
1469b8e2351Sbluhm
1479b8e2351Sbluhm void
StructData_Dispose(StructData * storage)14828ce3119Sbluhm StructData_Dispose(StructData *storage) {
1499b8e2351Sbluhm int i;
1509b8e2351Sbluhm
1519b8e2351Sbluhm assert(storage != NULL);
1529b8e2351Sbluhm for (i = 0; i < storage->count; i++)
1539b8e2351Sbluhm free((void *)storage->entries[i].str);
1549b8e2351Sbluhm free(storage->entries);
15528ce3119Sbluhm
15628ce3119Sbluhm storage->count = 0;
15728ce3119Sbluhm storage->entries = NULL;
1589b8e2351Sbluhm }
159