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) 2003-2006 Karl Waclawek <karl@waclawek.net>
10ac69e5d4SEric van Gyzen    Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
114543ef51SXin LI    Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
12cc68614dSXin LI    Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
130a48773fSEric van Gyzen    Licensed under the MIT license:
140a48773fSEric van Gyzen 
150a48773fSEric van Gyzen    Permission is  hereby granted,  free of charge,  to any  person obtaining
160a48773fSEric van Gyzen    a  copy  of  this  software   and  associated  documentation  files  (the
170a48773fSEric van Gyzen    "Software"),  to  deal in  the  Software  without restriction,  including
180a48773fSEric van Gyzen    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
190a48773fSEric van Gyzen    distribute, sublicense, and/or sell copies of the Software, and to permit
200a48773fSEric van Gyzen    persons  to whom  the Software  is  furnished to  do so,  subject to  the
210a48773fSEric van Gyzen    following conditions:
220a48773fSEric van Gyzen 
230a48773fSEric van Gyzen    The above copyright  notice and this permission notice  shall be included
240a48773fSEric van Gyzen    in all copies or substantial portions of the Software.
250a48773fSEric van Gyzen 
260a48773fSEric van Gyzen    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
270a48773fSEric van Gyzen    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
280a48773fSEric van Gyzen    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
290a48773fSEric van Gyzen    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
300a48773fSEric van Gyzen    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
310a48773fSEric van Gyzen    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
320a48773fSEric van Gyzen    USE OR OTHER DEALINGS IN THE SOFTWARE.
330a48773fSEric van Gyzen */
340a48773fSEric van Gyzen 
35220ed979SColeman Kane #include <sys/stat.h>
364543ef51SXin LI #include <assert.h>
374543ef51SXin LI #include <stddef.h> // ptrdiff_t
38220ed979SColeman Kane #include <stdlib.h>
39220ed979SColeman Kane #include <stdio.h>
40220ed979SColeman Kane #include <time.h>
41220ed979SColeman Kane #include "expat.h"
42220ed979SColeman Kane 
43220ed979SColeman Kane #ifdef XML_LARGE_SIZE
44220ed979SColeman Kane #  define XML_FMT_INT_MOD "ll"
45220ed979SColeman Kane #else
46220ed979SColeman Kane #  define XML_FMT_INT_MOD "l"
47220ed979SColeman Kane #endif
48220ed979SColeman Kane 
490a48773fSEric van Gyzen #ifdef XML_UNICODE_WCHAR_T
500a48773fSEric van Gyzen #  define XML_FMT_STR "ls"
510a48773fSEric van Gyzen #else
520a48773fSEric van Gyzen #  define XML_FMT_STR "s"
530a48773fSEric van Gyzen #endif
540a48773fSEric van Gyzen 
55220ed979SColeman Kane static void
usage(const char * prog,int rc)566b2c1e49SXin LI usage(const char *prog, int rc) {
576b2c1e49SXin LI   fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
58220ed979SColeman Kane   exit(rc);
59220ed979SColeman Kane }
60220ed979SColeman Kane 
616b2c1e49SXin LI int
main(int argc,char * argv[])626b2c1e49SXin LI main(int argc, char *argv[]) {
63220ed979SColeman Kane   XML_Parser parser;
64220ed979SColeman Kane   char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
65220ed979SColeman Kane   FILE *fd;
66220ed979SColeman Kane   struct stat fileAttr;
674543ef51SXin LI   int nrOfLoops, bufferSize, i, isFinal;
684543ef51SXin LI   size_t fileSize;
69220ed979SColeman Kane   int j = 0, ns = 0;
70220ed979SColeman Kane   clock_t tstart, tend;
71220ed979SColeman Kane   double cpuTime = 0.0;
72220ed979SColeman Kane 
73220ed979SColeman Kane   if (argc > 1) {
74220ed979SColeman Kane     if (argv[1][0] == '-') {
75220ed979SColeman Kane       if (argv[1][1] == 'n' && argv[1][2] == '\0') {
76220ed979SColeman Kane         ns = 1;
77220ed979SColeman Kane         j = 1;
786b2c1e49SXin LI       } else
79220ed979SColeman Kane         usage(argv[0], 1);
80220ed979SColeman Kane     }
81220ed979SColeman Kane   }
82220ed979SColeman Kane 
83220ed979SColeman Kane   if (argc != j + 4)
84220ed979SColeman Kane     usage(argv[0], 1);
85220ed979SColeman Kane 
86220ed979SColeman Kane   if (stat(argv[j + 1], &fileAttr) != 0) {
87220ed979SColeman Kane     fprintf(stderr, "could not access file '%s'\n", argv[j + 1]);
88220ed979SColeman Kane     return 2;
89220ed979SColeman Kane   }
90220ed979SColeman Kane 
91220ed979SColeman Kane   fd = fopen(argv[j + 1], "r");
92220ed979SColeman Kane   if (! fd) {
93220ed979SColeman Kane     fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
94220ed979SColeman Kane     exit(2);
95220ed979SColeman Kane   }
96220ed979SColeman Kane 
97220ed979SColeman Kane   bufferSize = atoi(argv[j + 2]);
98220ed979SColeman Kane   nrOfLoops = atoi(argv[j + 3]);
99220ed979SColeman Kane   if (bufferSize <= 0 || nrOfLoops <= 0) {
1006b2c1e49SXin LI     fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
101220ed979SColeman Kane     exit(3);
102220ed979SColeman Kane   }
103220ed979SColeman Kane 
104220ed979SColeman Kane   XMLBuf = malloc(fileAttr.st_size);
105220ed979SColeman Kane   fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd);
106220ed979SColeman Kane   fclose(fd);
107220ed979SColeman Kane 
108220ed979SColeman Kane   if (ns)
109220ed979SColeman Kane     parser = XML_ParserCreateNS(NULL, '!');
110220ed979SColeman Kane   else
111220ed979SColeman Kane     parser = XML_ParserCreate(NULL);
112220ed979SColeman Kane 
113220ed979SColeman Kane   i = 0;
114220ed979SColeman Kane   XMLBufEnd = XMLBuf + fileSize;
115220ed979SColeman Kane   while (i < nrOfLoops) {
116220ed979SColeman Kane     XMLBufPtr = XMLBuf;
117220ed979SColeman Kane     isFinal = 0;
118220ed979SColeman Kane     tstart = clock();
119220ed979SColeman Kane     do {
1204543ef51SXin LI       ptrdiff_t parseBufferSize = XMLBufEnd - XMLBufPtr;
1214543ef51SXin LI       if (parseBufferSize <= (ptrdiff_t)bufferSize)
122220ed979SColeman Kane         isFinal = 1;
123220ed979SColeman Kane       else
124220ed979SColeman Kane         parseBufferSize = bufferSize;
1254543ef51SXin LI       assert(parseBufferSize <= (ptrdiff_t)bufferSize);
1264543ef51SXin LI       if (! XML_Parse(parser, XMLBufPtr, (int)parseBufferSize, isFinal)) {
1270a48773fSEric van Gyzen         fprintf(stderr,
1286b2c1e49SXin LI                 "error '%" XML_FMT_STR "' at line %" XML_FMT_INT_MOD
129220ed979SColeman Kane                 "u character %" XML_FMT_INT_MOD "u\n",
130220ed979SColeman Kane                 XML_ErrorString(XML_GetErrorCode(parser)),
131220ed979SColeman Kane                 XML_GetCurrentLineNumber(parser),
132220ed979SColeman Kane                 XML_GetCurrentColumnNumber(parser));
133220ed979SColeman Kane         free(XMLBuf);
134220ed979SColeman Kane         XML_ParserFree(parser);
135220ed979SColeman Kane         exit(4);
136220ed979SColeman Kane       }
137220ed979SColeman Kane       XMLBufPtr += bufferSize;
138220ed979SColeman Kane     } while (! isFinal);
139220ed979SColeman Kane     tend = clock();
140220ed979SColeman Kane     cpuTime += ((double)(tend - tstart)) / CLOCKS_PER_SEC;
141220ed979SColeman Kane     XML_ParserReset(parser, NULL);
142220ed979SColeman Kane     i++;
143220ed979SColeman Kane   }
144220ed979SColeman Kane 
145220ed979SColeman Kane   XML_ParserFree(parser);
146220ed979SColeman Kane   free(XMLBuf);
147220ed979SColeman Kane 
148220ed979SColeman Kane   printf("%d loops, with buffer size %d. Average time per loop: %f\n",
149220ed979SColeman Kane          nrOfLoops, bufferSize, cpuTime / (double)nrOfLoops);
150220ed979SColeman Kane   return 0;
151220ed979SColeman Kane }
152