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 9*cc68614dSXin LI Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk> 10*cc68614dSXin LI Copyright (c) 2017-2021 Sebastian Pipping <sebastian@pipping.org> 110a48773fSEric van Gyzen Licensed under the MIT license: 120a48773fSEric van Gyzen 130a48773fSEric van Gyzen Permission is hereby granted, free of charge, to any person obtaining 140a48773fSEric van Gyzen a copy of this software and associated documentation files (the 150a48773fSEric van Gyzen "Software"), to deal in the Software without restriction, including 160a48773fSEric van Gyzen without limitation the rights to use, copy, modify, merge, publish, 170a48773fSEric van Gyzen distribute, sublicense, and/or sell copies of the Software, and to permit 180a48773fSEric van Gyzen persons to whom the Software is furnished to do so, subject to the 190a48773fSEric van Gyzen following conditions: 200a48773fSEric van Gyzen 210a48773fSEric van Gyzen The above copyright notice and this permission notice shall be included 220a48773fSEric van Gyzen in all copies or substantial portions of the Software. 230a48773fSEric van Gyzen 240a48773fSEric van Gyzen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 250a48773fSEric van Gyzen EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 260a48773fSEric van Gyzen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 270a48773fSEric van Gyzen NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 280a48773fSEric van Gyzen DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 290a48773fSEric van Gyzen OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 300a48773fSEric van Gyzen USE OR OTHER DEALINGS IN THE SOFTWARE. 310a48773fSEric van Gyzen */ 320a48773fSEric van Gyzen 330a48773fSEric van Gyzen #include "expat_config.h" 340a48773fSEric van Gyzen 350a48773fSEric van Gyzen #include <assert.h> 360a48773fSEric van Gyzen #include <stdlib.h> 370a48773fSEric van Gyzen #include <stdio.h> 380a48773fSEric van Gyzen #include <string.h> 390a48773fSEric van Gyzen 400a48773fSEric van Gyzen #include "structdata.h" 410a48773fSEric van Gyzen #include "minicheck.h" 420a48773fSEric van Gyzen 430a48773fSEric van Gyzen #define STRUCT_EXTENSION_COUNT 8 440a48773fSEric van Gyzen 450a48773fSEric van Gyzen #ifdef XML_UNICODE_WCHAR_T 460a48773fSEric van Gyzen # include <wchar.h> 470a48773fSEric van Gyzen # define XML_FMT_STR "ls" 480a48773fSEric van Gyzen # define xcstrlen(s) wcslen(s) 490a48773fSEric van Gyzen # define xcstrcmp(s, t) wcscmp((s), (t)) 500a48773fSEric van Gyzen #else 510a48773fSEric van Gyzen # define XML_FMT_STR "s" 520a48773fSEric van Gyzen # define xcstrlen(s) strlen(s) 530a48773fSEric van Gyzen # define xcstrcmp(s, t) strcmp((s), (t)) 540a48773fSEric van Gyzen #endif 550a48773fSEric van Gyzen 560a48773fSEric van Gyzen static XML_Char * 576b2c1e49SXin LI xmlstrdup(const XML_Char *s) { 580a48773fSEric van Gyzen size_t byte_count = (xcstrlen(s) + 1) * sizeof(XML_Char); 590a48773fSEric van Gyzen XML_Char *dup = malloc(byte_count); 600a48773fSEric van Gyzen 610a48773fSEric van Gyzen assert(dup != NULL); 620a48773fSEric van Gyzen memcpy(dup, s, byte_count); 630a48773fSEric van Gyzen return dup; 640a48773fSEric van Gyzen } 650a48773fSEric van Gyzen 660a48773fSEric van Gyzen void 676b2c1e49SXin LI StructData_Init(StructData *storage) { 680a48773fSEric van Gyzen assert(storage != NULL); 690a48773fSEric van Gyzen storage->count = 0; 700a48773fSEric van Gyzen storage->max_count = 0; 710a48773fSEric van Gyzen storage->entries = NULL; 720a48773fSEric van Gyzen } 730a48773fSEric van Gyzen 740a48773fSEric van Gyzen void 756b2c1e49SXin LI StructData_AddItem(StructData *storage, const XML_Char *s, int data0, int data1, 766b2c1e49SXin LI int data2) { 770a48773fSEric van Gyzen StructDataEntry *entry; 780a48773fSEric van Gyzen 790a48773fSEric van Gyzen assert(storage != NULL); 800a48773fSEric van Gyzen assert(s != NULL); 810a48773fSEric van Gyzen if (storage->count == storage->max_count) { 820a48773fSEric van Gyzen StructDataEntry *new; 830a48773fSEric van Gyzen 840a48773fSEric van Gyzen storage->max_count += STRUCT_EXTENSION_COUNT; 850a48773fSEric van Gyzen new = realloc(storage->entries, 860a48773fSEric van Gyzen storage->max_count * sizeof(StructDataEntry)); 870a48773fSEric van Gyzen assert(new != NULL); 880a48773fSEric van Gyzen storage->entries = new; 890a48773fSEric van Gyzen } 900a48773fSEric van Gyzen 910a48773fSEric van Gyzen entry = &storage->entries[storage->count]; 920a48773fSEric van Gyzen entry->str = xmlstrdup(s); 930a48773fSEric van Gyzen entry->data0 = data0; 940a48773fSEric van Gyzen entry->data1 = data1; 950a48773fSEric van Gyzen entry->data2 = data2; 960a48773fSEric van Gyzen storage->count++; 970a48773fSEric van Gyzen } 980a48773fSEric van Gyzen 990a48773fSEric van Gyzen /* 'fail()' aborts the function via a longjmp, so there is no point 1000a48773fSEric van Gyzen * in returning a value from this function. 1010a48773fSEric van Gyzen */ 1020a48773fSEric van Gyzen void 1036b2c1e49SXin LI StructData_CheckItems(StructData *storage, const StructDataEntry *expected, 1046b2c1e49SXin LI int count) { 1050a48773fSEric van Gyzen char buffer[1024]; 1060a48773fSEric van Gyzen int i; 1070a48773fSEric van Gyzen 1080a48773fSEric van Gyzen assert(storage != NULL); 1090a48773fSEric van Gyzen assert(expected != NULL); 1100a48773fSEric van Gyzen if (count != storage->count) { 1110a48773fSEric van Gyzen sprintf(buffer, "wrong number of entries: got %d, expected %d", 1120a48773fSEric van Gyzen storage->count, count); 1130a48773fSEric van Gyzen StructData_Dispose(storage); 1140a48773fSEric van Gyzen fail(buffer); 1156b2c1e49SXin LI } else { 1166b2c1e49SXin LI for (i = 0; i < count; i++) { 1170a48773fSEric van Gyzen const StructDataEntry *got = &storage->entries[i]; 1180a48773fSEric van Gyzen const StructDataEntry *want = &expected[i]; 1190a48773fSEric van Gyzen 1206b2c1e49SXin LI assert(got != NULL); 1216b2c1e49SXin LI assert(want != NULL); 1226b2c1e49SXin LI 1230a48773fSEric van Gyzen if (xcstrcmp(got->str, want->str) != 0) { 1240a48773fSEric van Gyzen StructData_Dispose(storage); 1250a48773fSEric van Gyzen fail("structure got bad string"); 1266b2c1e49SXin LI } else { 1276b2c1e49SXin LI if (got->data0 != want->data0 || got->data1 != want->data1 1286b2c1e49SXin LI || got->data2 != want->data2) { 1290a48773fSEric van Gyzen sprintf(buffer, 1300a48773fSEric van Gyzen "struct '%" XML_FMT_STR 1310a48773fSEric van Gyzen "' expected (%d,%d,%d), got (%d,%d,%d)", 1326b2c1e49SXin LI got->str, want->data0, want->data1, want->data2, got->data0, 1336b2c1e49SXin LI got->data1, got->data2); 1340a48773fSEric van Gyzen StructData_Dispose(storage); 1350a48773fSEric van Gyzen fail(buffer); 1360a48773fSEric van Gyzen } 1370a48773fSEric van Gyzen } 1380a48773fSEric van Gyzen } 1396b2c1e49SXin LI } 1406b2c1e49SXin LI } 1410a48773fSEric van Gyzen 1420a48773fSEric van Gyzen void 1436b2c1e49SXin LI StructData_Dispose(StructData *storage) { 1440a48773fSEric van Gyzen int i; 1450a48773fSEric van Gyzen 1460a48773fSEric van Gyzen assert(storage != NULL); 1470a48773fSEric van Gyzen for (i = 0; i < storage->count; i++) 1480a48773fSEric van Gyzen free((void *)storage->entries[i].str); 1490a48773fSEric van Gyzen free(storage->entries); 1506b2c1e49SXin LI 1516b2c1e49SXin LI storage->count = 0; 1526b2c1e49SXin LI storage->entries = NULL; 1530a48773fSEric van Gyzen } 154