1340084Svangyzen/*
2340084Svangyzen                            __  __            _
3340084Svangyzen                         ___\ \/ /_ __   __ _| |_
4340084Svangyzen                        / _ \\  /| '_ \ / _` | __|
5340084Svangyzen                       |  __//  \| |_) | (_| | |_
6340084Svangyzen                        \___/_/\_\ .__/ \__,_|\__|
7340084Svangyzen                                 |_| XML parser
8340084Svangyzen
9340084Svangyzen   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10340084Svangyzen   Copyright (c) 2000-2017 Expat development team
11340084Svangyzen   Licensed under the MIT license:
12340084Svangyzen
13340084Svangyzen   Permission is  hereby granted,  free of charge,  to any  person obtaining
14340084Svangyzen   a  copy  of  this  software   and  associated  documentation  files  (the
15340084Svangyzen   "Software"),  to  deal in  the  Software  without restriction,  including
16340084Svangyzen   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
17340084Svangyzen   distribute, sublicense, and/or sell copies of the Software, and to permit
18340084Svangyzen   persons  to whom  the Software  is  furnished to  do so,  subject to  the
19340084Svangyzen   following conditions:
20340084Svangyzen
21340084Svangyzen   The above copyright  notice and this permission notice  shall be included
22340084Svangyzen   in all copies or substantial portions of the Software.
23340084Svangyzen
24340084Svangyzen   THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
25340084Svangyzen   EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
26340084Svangyzen   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27340084Svangyzen   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28340084Svangyzen   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
29340084Svangyzen   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30340084Svangyzen   USE OR OTHER DEALINGS IN THE SOFTWARE.
31340084Svangyzen*/
32340084Svangyzen
33340084Svangyzen#ifdef HAVE_EXPAT_CONFIG_H
34355604Sdelphij#  include "expat_config.h"
35340084Svangyzen#endif
36340084Svangyzen
37340084Svangyzen#include <assert.h>
38340084Svangyzen#include <stdlib.h>
39340084Svangyzen#include <stdio.h>
40340084Svangyzen#include <string.h>
41340084Svangyzen
42340084Svangyzen#include "structdata.h"
43340084Svangyzen#include "minicheck.h"
44340084Svangyzen
45340084Svangyzen#define STRUCT_EXTENSION_COUNT 8
46340084Svangyzen
47340084Svangyzen#ifdef XML_UNICODE_WCHAR_T
48355604Sdelphij#  include <wchar.h>
49355604Sdelphij#  define XML_FMT_STR "ls"
50355604Sdelphij#  define xcstrlen(s) wcslen(s)
51355604Sdelphij#  define xcstrcmp(s, t) wcscmp((s), (t))
52340084Svangyzen#else
53355604Sdelphij#  define XML_FMT_STR "s"
54355604Sdelphij#  define xcstrlen(s) strlen(s)
55355604Sdelphij#  define xcstrcmp(s, t) strcmp((s), (t))
56340084Svangyzen#endif
57340084Svangyzen
58340084Svangyzenstatic XML_Char *
59355604Sdelphijxmlstrdup(const XML_Char *s) {
60355604Sdelphij  size_t byte_count = (xcstrlen(s) + 1) * sizeof(XML_Char);
61355604Sdelphij  XML_Char *dup = malloc(byte_count);
62340084Svangyzen
63355604Sdelphij  assert(dup != NULL);
64355604Sdelphij  memcpy(dup, s, byte_count);
65355604Sdelphij  return dup;
66340084Svangyzen}
67340084Svangyzen
68340084Svangyzenvoid
69355604SdelphijStructData_Init(StructData *storage) {
70355604Sdelphij  assert(storage != NULL);
71355604Sdelphij  storage->count = 0;
72355604Sdelphij  storage->max_count = 0;
73355604Sdelphij  storage->entries = NULL;
74340084Svangyzen}
75340084Svangyzen
76340084Svangyzenvoid
77355604SdelphijStructData_AddItem(StructData *storage, const XML_Char *s, int data0, int data1,
78355604Sdelphij                   int data2) {
79355604Sdelphij  StructDataEntry *entry;
80340084Svangyzen
81355604Sdelphij  assert(storage != NULL);
82355604Sdelphij  assert(s != NULL);
83355604Sdelphij  if (storage->count == storage->max_count) {
84355604Sdelphij    StructDataEntry *new;
85340084Svangyzen
86355604Sdelphij    storage->max_count += STRUCT_EXTENSION_COUNT;
87355604Sdelphij    new = realloc(storage->entries,
88355604Sdelphij                  storage->max_count * sizeof(StructDataEntry));
89355604Sdelphij    assert(new != NULL);
90355604Sdelphij    storage->entries = new;
91355604Sdelphij  }
92340084Svangyzen
93355604Sdelphij  entry = &storage->entries[storage->count];
94355604Sdelphij  entry->str = xmlstrdup(s);
95355604Sdelphij  entry->data0 = data0;
96355604Sdelphij  entry->data1 = data1;
97355604Sdelphij  entry->data2 = data2;
98355604Sdelphij  storage->count++;
99340084Svangyzen}
100340084Svangyzen
101340084Svangyzen/* 'fail()' aborts the function via a longjmp, so there is no point
102340084Svangyzen * in returning a value from this function.
103340084Svangyzen */
104340084Svangyzenvoid
105355604SdelphijStructData_CheckItems(StructData *storage, const StructDataEntry *expected,
106355604Sdelphij                      int count) {
107355604Sdelphij  char buffer[1024];
108355604Sdelphij  int i;
109340084Svangyzen
110355604Sdelphij  assert(storage != NULL);
111355604Sdelphij  assert(expected != NULL);
112355604Sdelphij  if (count != storage->count) {
113355604Sdelphij    sprintf(buffer, "wrong number of entries: got %d, expected %d",
114355604Sdelphij            storage->count, count);
115355604Sdelphij    StructData_Dispose(storage);
116355604Sdelphij    fail(buffer);
117355604Sdelphij  } else {
118355604Sdelphij    for (i = 0; i < count; i++) {
119355604Sdelphij      const StructDataEntry *got = &storage->entries[i];
120355604Sdelphij      const StructDataEntry *want = &expected[i];
121355604Sdelphij
122355604Sdelphij      assert(got != NULL);
123355604Sdelphij      assert(want != NULL);
124355604Sdelphij
125355604Sdelphij      if (xcstrcmp(got->str, want->str) != 0) {
126340084Svangyzen        StructData_Dispose(storage);
127355604Sdelphij        fail("structure got bad string");
128355604Sdelphij      } else {
129355604Sdelphij        if (got->data0 != want->data0 || got->data1 != want->data1
130355604Sdelphij            || got->data2 != want->data2) {
131355604Sdelphij          sprintf(buffer,
132355604Sdelphij                  "struct '%" XML_FMT_STR
133355604Sdelphij                  "' expected (%d,%d,%d), got (%d,%d,%d)",
134355604Sdelphij                  got->str, want->data0, want->data1, want->data2, got->data0,
135355604Sdelphij                  got->data1, got->data2);
136355604Sdelphij          StructData_Dispose(storage);
137355604Sdelphij          fail(buffer);
138340084Svangyzen        }
139355604Sdelphij      }
140340084Svangyzen    }
141355604Sdelphij  }
142340084Svangyzen}
143340084Svangyzen
144340084Svangyzenvoid
145355604SdelphijStructData_Dispose(StructData *storage) {
146355604Sdelphij  int i;
147340084Svangyzen
148355604Sdelphij  assert(storage != NULL);
149355604Sdelphij  for (i = 0; i < storage->count; i++)
150355604Sdelphij    free((void *)storage->entries[i].str);
151355604Sdelphij  free(storage->entries);
152355604Sdelphij
153355604Sdelphij  storage->count = 0;
154355604Sdelphij  storage->entries = NULL;
155340084Svangyzen}
156