summaryrefslogtreecommitdiff
path: root/yxml.h
blob: 70308ef9f676dc060d88f842d82cdf47c245f59a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* Copyright (c) 2013 Yoran Heling

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be included
  in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include <stdint.h>
#include <stddef.h>

#define YXML_MAX_ATTRNAME 126
#define YXML_MAX_REF 7 /* Must be >=7 in order for the hack in yxml_refend() to work */


typedef enum {
	YXML_EREF    = -5, /* Invalid character or entity reference (&whatever;) */
	YXML_ECLOSE  = -4, /* Close tag does not match open tag (<Tag> .. </OtherTag>) */
	YXML_ESTACK  = -3, /* Stack overflow (too deeply nested tags or too long element name) */
	YXML_EATTR   = -2, /* Too long attribute name                    */
	YXML_ESYN    = -1, /* Syntax error (unexpected byte)             */
	YXML_OK      =  0, /* Character consumed, no new token present   */
	YXML_OPEN    =  1, /* Start of an element:   '<Tag ..'           */
	YXML_CLOSE   =  2, /* End of an element:     '.. />' or '</Tag>' */
	YXML_ATTR    =  4, /* Attribute:             'Name=..'           */
	YXML_DATA    =  8, /* Attribute value or element contents        */
	YXML_EOA     = 16, /* End of attributes:     '.. />' or '.. >'   */
	YXML_EOD     = 32  /* End of XML document                        */
} yxml_ret_t;

/* When, exactly, are tokens returned?
 *
 * <TagName
 *   '>' OPEN | EOA
 *   '/' OPEN | EOA, '>' CLOSE (| EOD)
 *   ' ' OPEN
 *     '>' EOA
 *     '/' EOA, '>' CLOSE (| EOD)
 *     Attr
 *       '=' ATTR
 *         "X DATA
 *           'Y'  DATA
 *             'Z'  DATA
 *               "> EOA
 *               "/ EOA, '>' CLOSE (| EOD)
 *
 * </TagName
 *   '>' CLOSE (| EOD)
 */


typedef struct {
	/* PUBLIC (read-only) */

	/* Name of the current element, zero-length if not in any element. Changed
	 * after YXML_OPEN or YXML_CLOSE. */
	char *elem;

	/* The last read character of an attribute value or element data. Changed
	 * after YXML_DATA. */
	char data;

	/* Currently opened attribute name, zero-length if not in an attribute.
	 * Changed after YXML_ATTR. */
	char attr[YXML_MAX_ATTRNAME+1];

	/* Line number, byte offset within that line, and total bytes read. These
	 * values refer to the position _after_ the last byte given to
	 * yxml_parse(). These are useful for debugging and error reporting. */
	uint64_t byte;
	uint64_t total;
	uint32_t line;


	/* PRIVATE */
	int state;
	unsigned char *stack; /* Stack of element names, separated by \0. Also starts with a \0. */
	size_t stacksize, stacklen;
	size_t attrlen;
	unsigned quote;
	int reflen;
	int stringstate;
	unsigned char ref[YXML_MAX_REF+1];
	unsigned char *string;
} yxml_t;


void yxml_init(yxml_t *x, char *stack, size_t stacksize);


yxml_ret_t yxml_parse(yxml_t *x, int ch);


/* vim: set noet sw=4 ts=4: */