1/*
2                            __  __            _
3                         ___\ \/ /_ __   __ _| |_
4                        / _ \\  /| '_ \ / _` | __|
5                       |  __//  \| |_) | (_| | |_
6                        \___/_/\_\ .__/ \__,_|\__|
7                                 |_| XML parser
8
9   Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net>
10   Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
11   Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
12   Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
13   Licensed under the MIT license:
14
15   Permission is  hereby granted,  free of charge,  to any  person obtaining
16   a  copy  of  this  software   and  associated  documentation  files  (the
17   "Software"),  to  deal in  the  Software  without restriction,  including
18   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
19   distribute, sublicense, and/or sell copies of the Software, and to permit
20   persons  to whom  the Software  is  furnished to  do so,  subject to  the
21   following conditions:
22
23   The above copyright  notice and this permission notice  shall be included
24   in all copies or substantial portions of the Software.
25
26   THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
27   EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
28   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
29   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
30   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
31   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
32   USE OR OTHER DEALINGS IN THE SOFTWARE.
33*/
34
35#include <sys/stat.h>
36#include <assert.h>
37#include <stddef.h> // ptrdiff_t
38#include <stdlib.h>
39#include <stdio.h>
40#include <time.h>
41#include "expat.h"
42
43#ifdef XML_LARGE_SIZE
44#  define XML_FMT_INT_MOD "ll"
45#else
46#  define XML_FMT_INT_MOD "l"
47#endif
48
49#ifdef XML_UNICODE_WCHAR_T
50#  define XML_FMT_STR "ls"
51#else
52#  define XML_FMT_STR "s"
53#endif
54
55static void
56usage(const char *prog, int rc) {
57  fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
58  exit(rc);
59}
60
61int
62main(int argc, char *argv[]) {
63  XML_Parser parser;
64  char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
65  FILE *fd;
66  struct stat fileAttr;
67  int nrOfLoops, bufferSize, i, isFinal;
68  size_t fileSize;
69  int j = 0, ns = 0;
70  clock_t tstart, tend;
71  double cpuTime = 0.0;
72
73  if (argc > 1) {
74    if (argv[1][0] == '-') {
75      if (argv[1][1] == 'n' && argv[1][2] == '\0') {
76        ns = 1;
77        j = 1;
78      } else
79        usage(argv[0], 1);
80    }
81  }
82
83  if (argc != j + 4)
84    usage(argv[0], 1);
85
86  if (stat(argv[j + 1], &fileAttr) != 0) {
87    fprintf(stderr, "could not access file '%s'\n", argv[j + 1]);
88    return 2;
89  }
90
91  fd = fopen(argv[j + 1], "r");
92  if (! fd) {
93    fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
94    exit(2);
95  }
96
97  bufferSize = atoi(argv[j + 2]);
98  nrOfLoops = atoi(argv[j + 3]);
99  if (bufferSize <= 0 || nrOfLoops <= 0) {
100    fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
101    exit(3);
102  }
103
104  XMLBuf = malloc(fileAttr.st_size);
105  fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd);
106  fclose(fd);
107
108  if (ns)
109    parser = XML_ParserCreateNS(NULL, '!');
110  else
111    parser = XML_ParserCreate(NULL);
112
113  i = 0;
114  XMLBufEnd = XMLBuf + fileSize;
115  while (i < nrOfLoops) {
116    XMLBufPtr = XMLBuf;
117    isFinal = 0;
118    tstart = clock();
119    do {
120      ptrdiff_t parseBufferSize = XMLBufEnd - XMLBufPtr;
121      if (parseBufferSize <= (ptrdiff_t)bufferSize)
122        isFinal = 1;
123      else
124        parseBufferSize = bufferSize;
125      assert(parseBufferSize <= (ptrdiff_t)bufferSize);
126      if (! XML_Parse(parser, XMLBufPtr, (int)parseBufferSize, isFinal)) {
127        fprintf(stderr,
128                "error '%" XML_FMT_STR "' at line %" XML_FMT_INT_MOD
129                "u character %" XML_FMT_INT_MOD "u\n",
130                XML_ErrorString(XML_GetErrorCode(parser)),
131                XML_GetCurrentLineNumber(parser),
132                XML_GetCurrentColumnNumber(parser));
133        free(XMLBuf);
134        XML_ParserFree(parser);
135        exit(4);
136      }
137      XMLBufPtr += bufferSize;
138    } while (! isFinal);
139    tend = clock();
140    cpuTime += ((double)(tend - tstart)) / CLOCKS_PER_SEC;
141    XML_ParserReset(parser, NULL);
142    i++;
143  }
144
145  XML_ParserFree(parser);
146  free(XMLBuf);
147
148  printf("%d loops, with buffer size %d. Average time per loop: %f\n",
149         nrOfLoops, bufferSize, cpuTime / (double)nrOfLoops);
150  return 0;
151}
152