1 /*
2  * Hunt - A xml library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.xml.Internal;
13 
14 import hunt.xml.Common;
15 
16 // dfmt off
17 
18 ubyte[256] lookup_whitespace = [
19  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
20     0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
21     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
22     1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
23     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
24     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
25     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
26     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
27     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
28     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
29     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
30     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
31     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
32     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
33     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
34     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
35     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
36 ];              // Whitespace table
37 
38 ubyte[256] lookup_node_name = [
39 // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
40     0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
41     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
42     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
43     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
44     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
45     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
46     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
47     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
48     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
49     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
50     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
51     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
52     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
53     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
54     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
55     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
56 ];           // Node name table
57 
58 ubyte[256] lookup_element_name = [
59 // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
60     0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
61     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
62     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
63     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  0,  0,  // 3
64     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
65     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
66     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
67     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
68     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
69     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
70     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
71     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
72     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
73     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
74     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
75     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
76 ];          // Element name table
77 
78 ubyte[256] lookup_text =  [
79 // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
80     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
81     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
82     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
83     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
84     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
85     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
86     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
87     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
88     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
89     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
90     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
91     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
92     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
93     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
94     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
95     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
96 ];
97                     // Text table
98 ubyte[256] lookup_text_pure_no_ws =  [
99 // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
100     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
101     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
102     1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
103     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
104     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
105     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
106     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
107     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
108     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
109     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
110     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
111     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
112     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
113     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
114     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
115     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
116 ];
117          // Text table
118 ubyte[256] lookup_text_pure_with_ws =  [
119 // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
120     0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
121     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
122     0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
123     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
124     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
125     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
126     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
127     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
128     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
129     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
130     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
131     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
132     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
133     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
134     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
135     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
136 ];
137 
138 // Text table
139 ubyte[256] lookup_attribute_name  = [
140   // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
141     0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
142     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
143     0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
144     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
145     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
146     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
147     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
148     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
149     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
150     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
151     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
152     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
153     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
154     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
155     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
156     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
157 ];
158 
159 // Attribute name table
160 ubyte[256] lookup_attribute_data_1 = [
161 // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
162     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
163     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
164     1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
165     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
166     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
167     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
168     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
169     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
170     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
171     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
172     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
173     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
174     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
175     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
176     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
177     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
178 ];
179 
180 // Attribute data table with single quote
181 ubyte[256] lookup_attribute_data_1_pure =  [
182  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
183     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
184     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
185     1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
186     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
187     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
188     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
189     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
190     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
191     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
192     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
193     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
194     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
195     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
196     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
197     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
198     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
199 ];
200 
201 // Attribute data table with single quote
202 ubyte[256] lookup_attribute_data_2 =  [
203  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
204     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
205     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
206     1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
207     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
208     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
209     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
210     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
211     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
212     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
213     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
214     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
215     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
216     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
217     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
218     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
219     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
220 ];
221 
222 // Attribute data table with double quotes
223 ubyte[256] lookup_attribute_data_2_pure = [
224  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
225     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
226     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
227     1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
228     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
229     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
230     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
231     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
232     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
233     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
234     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
235     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
236     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
237     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
238     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
239     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
240     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
241 ];
242 
243 // Attribute data table with double quotes
244 
245 ubyte[256] lookup_digits =  [
246  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
247     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
248     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
249     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
250     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3
251     255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
252     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
253     255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
254     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
255     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
256     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
257     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
258     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
259     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
260     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
261     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
262     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
263 ];
264 
265 // Digits
266 
267 ubyte[256] lookup_upcase =  [
268  // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
269     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
270     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
271     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
272     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
273     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
274     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
275     96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
276     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127,  // 7
277     128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,  // 8
278     144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,  // 9
279     160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,  // A
280     176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,  // B
281     192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,  // C
282     208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,  // D
283     224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,  // E
284     240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255   // F
285 ]; 
286 
287 // dfmt on
288 
289 void insertCodedCharacter(int Flags)(ref char[] text,  ulong code)
290 {
291     if (Flags & ParsingFlags.NoUtf8)
292     {
293         // Insert 8-bit ASCII character
294         // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
295         text[0] = (code);
296         text = text[ 1 .. $ - 1];
297     }
298     else
299     {
300         // Insert UTF8 sequence
301         if (code < 0x80)    // 1 byte sequence
302         {
303             text[0] = (code);
304             text = text[1 .. $ - 1];
305         }
306         else if (code < 0x800)  // 2 byte sequence
307         {
308             text[1] = ((code | 0x80) & 0xBF); code >>= 6;
309             text[0] = (code | 0xC0);
310             text = text[ 2 .. $ - 1];
311         }
312         else if (code < 0x10000)    // 3 byte sequence
313         {
314             text[2] = ((code | 0x80) & 0xBF); code >>= 6;
315             text[1] = ((code | 0x80) & 0xBF); code >>= 6;
316             text[0] = (code | 0xE0);
317             text = text[3 .. $ - 1];
318         }
319         else if (code < 0x110000)   // 4 byte sequence
320         {
321             text[3] = ((code | 0x80) & 0xBF); code >>= 6;
322             text[2] = ((code | 0x80) & 0xBF); code >>= 6;
323             text[1] = ((code | 0x80) & 0xBF); code >>= 6;
324             text[0] = (code | 0xF0);
325             text = text[4 .. $ - 1];
326         }
327         else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
328         {
329             throw new XmlParsingException("invalid numeric character entity", text);
330         }
331     }
332 }
333 
334 // Skip characters until predicate evaluates to true while doing the following:
335 // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
336 // - condensing whitespace sequences to single space character
337 
338 static  char[] skipAndExpandCharacterRefs(T , TP , int Flags)(ref char[] text)
339 {
340     // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
341     if (Flags & ParsingFlags.EntityTranslation &&
342         !(Flags & ParsingFlags.NormalizeWhitespace) &&
343         !(Flags & ParsingFlags.TrimWhitespace))
344     {
345         skip!(T)(text);
346         return text;
347     }
348 
349     // Use simple skip until first modification is detected
350     skip!(TP)(text);
351     // Use translation skip
352     char[] src = text;
353     char[] dest = src.dup;
354     long index = 0;
355     while (T.test(src[0]))
356     {
357         // If entity translation is enabled
358         if (!(Flags & ParsingFlags.EntityTranslation))
359         {
360             // Test if replacement is needed
361             if (src[0] == ('&'))
362             {
363                 switch (src[1])
364                 {
365 
366                 // &amp; &apos;
367                 case ('a'):
368                     if (src[2] == ('m') && src[3] == ('p') && src[4] == (';'))
369                     {
370                         dest[index] = ('&');
371                         ++index;
372                         src=src[5..$-1];
373                         continue;
374                     }
375                     if (src[2] == ('p') && src[3] == ('o') && src[4] == ('s') && src[5] == (';'))
376                     {
377                         dest[index] = ('\'');
378                         ++index;
379                         src = src[6 .. $-1];
380                         continue;
381                     }
382                     break;
383 
384                 // &quot;
385                 case ('q'):
386                     if (src[2] == ('u') && src[3] == ('o') && src[4] == ('t') && src[5] == (';'))
387                     {
388                         dest[index] = ('"');
389                         ++index;
390                         src = src[6 .. $ - 1];
391                         continue;
392                     }
393                     break;
394 
395                 // &gt;
396                 case ('g'):
397                     if (src[2] == ('t') && src[3] == (';'))
398                     {
399                         dest[index] = ('>');
400                         ++index;
401                         src = src[4 .. $ - 1];
402                         continue;
403                     }
404                     break;
405 
406                 // &lt;
407                 case ('l'):
408                     if (src[2] == ('t') && src[3] == (';'))
409                     {
410                         dest[index] = ('<');
411                         ++index;
412                         src = src[ 4 .. $ - 1];
413                         continue;
414                     }
415                     break;
416 
417                 // &#...; - assumes ASCII
418                 case ('#'):
419                     if (src[2] == ('x'))
420                     {
421                             ulong code = 0;
422                         src = src[3 .. $ - 1];   // Skip &#x
423                         while (1)
424                         {
425                             ubyte digit = lookup_digits[src[0]];
426                             if (digit == 0xFF)
427                                 break;
428                             code = code * 16 + digit;
429                             src = src[1 .. $ - 1];
430                         }
431                         //   insertCodedCharacter!Flags(dest, code);    // Put character in output
432                     }
433                     else
434                     {
435                         ulong code = 0;
436                         src = src[2 .. $ - 1];   // Skip &#
437                         while (1)
438                         {
439                             ubyte digit = lookup_digits[src[0]];
440                             if (digit == 0xFF)
441                                 break;
442                             code = code * 10 + digit;
443                             src=src[1 .. $ - 1];
444                         }
445                     //      insertCodedCharacter!Flags(dest, code);    // Put character in output
446                     }
447                     if (src[0] == (';'))
448                         src=src[1..$ - 1];
449                     else
450                         throw new XmlParsingException("expected ;", src);
451                     continue;
452 
453                 // Something else
454                 default:
455                     // Ignore, just copy '&' verbatim
456                     break;
457 
458                 }
459             }
460         }
461 
462         // If whitespace condensing is enabled
463         if (Flags & ParsingFlags.NormalizeWhitespace)
464         {
465             // Test if condensing is needed
466             if (WhitespacePred.test(src[0]))
467             {
468                 dest[index] = (' '); ++index;    // Put single space in dest
469                 src = src[1 .. $ - 1];                      // Skip first whitespace char
470                 // Skip remaining whitespace chars
471                 while (WhitespacePred.test(src[0]))
472                     src = src[1 .. $ - 1];
473                 continue;
474             }
475         }
476 
477         // No replacement, only copy character
478         dest[index] = src[0];
479         ++index;
480         src = src[1 .. $ - 1];
481 
482     }
483 
484     // Return new end
485     text = src;
486     return dest;
487 
488 }
489 
490     // private static void skip(T )(ref char[] text)
491     // {
492 
493     //     char[] tmp = text;
494     //     while(tmp.length > 0 && T.test(tmp[0]))
495     //     {
496     //         tmp = tmp[1 .. $];    
497     //     }
498     //     text = tmp;
499     // }
500 
501 
502 void skip(T)(ref char[] text)
503 {
504     int index = 0;
505     int length = cast(int)text.length;
506     while(index < text.length && T.test(text[index]))
507         index++;
508     text = text[index .. $];
509 }
510 
511 struct WhitespacePred
512 {
513     static ubyte test(ubyte ch)
514     {
515         return lookup_whitespace[ch];
516     }
517 }
518 
519 // Detect node name character
520 struct NodeNamePred
521 {
522     static ubyte test(ubyte ch)
523     {
524         return lookup_node_name[ch];
525     }
526 }
527 
528 // Detect element name character
529 struct ElementNamePred
530 {
531     static ubyte test(ubyte ch)
532     {
533         return lookup_element_name[ch];
534     }
535 }
536 
537 // Detect attribute name character
538 struct AttributeNamePred
539 {
540     static ubyte test(ubyte ch)
541     {
542         return lookup_attribute_name[ch];
543     }
544 }
545 
546 // Detect text character (PCDATA)
547 struct TextPred
548 {
549     static ubyte test(ubyte ch)
550     {
551         return lookup_text[ch];
552     }
553 }
554 
555 // Detect text character (PCDATA) that does not require processing
556 struct TextPureNoWsPred
557 {
558     static ubyte test(ubyte ch)
559     {
560         return lookup_text_pure_no_ws[ch];
561     }
562 }
563 
564 // Detect text character (PCDATA) that does not require processing
565 struct TextPureWithWsPred
566 {
567     static  ubyte test(ubyte ch)
568     {
569         return lookup_text_pure_with_ws[ch];
570     }
571 }
572 
573 // Detect attribute value character
574 
575 struct AttributeValuePred(alias Quote)
576 {
577     static ubyte test(ubyte ch)
578     {
579         if (Quote == '\'')
580             return lookup_attribute_data_1[ch];
581         else if (Quote == '"')
582             return lookup_attribute_data_2[ch];
583         else
584             return 0;       // Should never be executed, to avoid warnings on Comeau
585     }
586 }
587 
588 // Detect attribute value character
589 struct AttributeValuePurePred(alias Quote)
590 {
591     static ubyte test(ubyte ch)
592     {
593         if (Quote == '\'')
594             return lookup_attribute_data_1_pure[ch];
595         else if (Quote == ('"'))
596             return lookup_attribute_data_2_pure[ch];
597         else
598             return 0;       // Should never be executed, to avoid warnings on Comeau
599     }
600 }