source: trunk/src/bytelex.h @ 155

Last change on this file since 155 was 125, checked in by lindanl, 11 years ago

Character references: calculation and error detection.

File size: 15.2 KB
Line 
1/*  bytelex.h - XML lexical recognizers for pseudo-ASCII or
2    EBCDIC-family byte streams
3    Copyright (c) 2008, Robert D. Cameron.
4    Licensed to the public under the Open Software License 3.0.
5    Licensed to International Characters, Inc., under the Academic
6    Free License 3.0.
7*/
8#ifndef BYTELEX_H
9#define BYTELEX_H
10
11#include "xmlmodel.h"
12#include "multiliteral.h"
13
14template<CodeUnit_Base C, unsigned char c>
15inline bool AtChar(unsigned char x8data[]) {
16  return x8data[0] == Ord<C, c>::value;
17}
18
19template<CodeUnit_Base C>
20inline bool AtQuote(unsigned char x8data[]) {
21  return (x8data[0] == Ord<C, '"'>::value) | (x8data[0] == Ord<C, '\''>::value);
22}
23
24/* In both ASCII and EBCDIC, digits are in a contiguous range
25   from 0 through 9 */
26template<CodeUnit_Base C>
27inline bool at_Digit(unsigned char x8data[]) {
28  return (x8data[0] >= Ord<C, '0'>::value) & (x8data[0] <= Ord<C, '9'>::value);
29}
30
31template<CodeUnit_Base C>
32inline unsigned int DigitVal(unsigned char d) {
33  return d - Ord<C, '0'>::value;
34}
35
36/* In both ASCII and EBCDIC, digits are in a contiguous range
37   from 0 through 9.  Similarly the hex characters A through F
38   and a through f are also in contiguous ranges that differ in
39   only one bit position (Ord<C, 'a'>::value ^ Ord<C, 'A'>::value).*/
40template<CodeUnit_Base C>
41inline bool at_HexDigit(unsigned char x8data[]) {
42  const unsigned char case_bit = Ord<C, 'a'>::value ^ Ord<C, 'A'>::value;
43  const unsigned char canon_A =  Ord<C, 'a'>::value | case_bit;
44  const unsigned char canon_F =  Ord<C, 'f'>::value | case_bit;
45  unsigned char ch = x8data[0];
46  unsigned char canon_ch = ch | case_bit;
47  return ((ch >= Ord<C, '0'>::value) & (ch <= Ord<C, '9'>::value)) |
48         ((canon_ch >= canon_A) & (canon_ch <= canon_F));
49}
50
51template<CodeUnit_Base C>
52inline unsigned int HexVal(unsigned char ch) {
53  const unsigned char case_bit = Ord<C, 'a'>::value ^ Ord<C, 'A'>::value;
54  const unsigned char canon_A =  Ord<C, 'a'>::value | case_bit;
55  unsigned char canon_ch = ch | case_bit;
56  if ((ch >= Ord<C, '0'>::value) & (ch <= Ord<C, '9'>::value)) return ch - Ord<C, '0'>::value;
57  else return (ch | case_bit) - canon_A + 10;
58}
59
60// Whitespace recognition.  This varies between XML 1.0 and
61// XML 1.1, but only the XML 1.0 version is needed.
62// Specific ASCII/EBCDIC versions are hard-coded here, because
63// the Ord metafunction currently only works for printable characters.
64// Could be improved. 
65template<XML_version, CodeUnit_Base C>
66inline bool at_WhiteSpace(unsigned char x8data[]);
67
68// Workaround because we lack function partial specialization.
69template<CodeUnit_Base C>
70inline bool at_WhiteSpace_10(unsigned char x8data[]) {
71  unsigned char ch = x8data[0];
72  return (ch == Ord<C, ' '>::value) || 
73         (ch == LF<C>::value) || (ch == LF<C>::value) || (ch == HT<C>::value);
74}
75
76template<>
77inline bool at_WhiteSpace<XML_1_0, ASCII>(unsigned char x8data[]) {
78        return at_WhiteSpace_10<ASCII>(x8data);
79}
80
81template<>
82inline bool at_WhiteSpace<XML_1_0, EBCDIC>(unsigned char x8data[]) {
83        return at_WhiteSpace_10<EBCDIC>(x8data);
84}
85
86template<CodeUnit_Base C>
87inline bool at_EndTag_Start(unsigned char x8data[]) {
88  return s2int16(x8data) == c2int16<C, '<', '/'>::value;
89}
90
91template<CodeUnit_Base C>
92inline bool at_Comment_Start(unsigned char x8data[]) {
93  return s4int32(x8data) == c4int32<C, '<', '!', '-', '-'>::value;
94}
95
96template<CodeUnit_Base C>
97inline bool at_DoubleHyphen(unsigned char x8data[]) {
98  return s2int16(x8data) == c2int16<C, '-', '-'>::value;
99}
100
101template<CodeUnit_Base C>
102inline bool at_Comment_End(unsigned char x8data[]) {
103  return s3int32(x8data) == c3int32<C, '-', '-', '>'>::value;
104}
105
106template<CodeUnit_Base C>
107inline bool at_CDATA_Start(unsigned char x8data[]) {
108  return s8int64(x8data) == 
109         c8int64<C, '<', '!', '[', 'C', 'D', 'A', 'T', 'A'>::value;
110}
111
112template<CodeUnit_Base C>
113inline bool at_CDATA_End(unsigned char x8data[]) {
114  return s3int32(x8data) == c3int32<C, ']', ']', '>'>::value;
115}
116
117template<CodeUnit_Base C>
118inline bool at_PI_Start(unsigned char x8data[]) {
119  return s2int16(x8data) == c2int16<C, '<', '?'>::value;
120}
121
122template<CodeUnit_Base C>
123inline bool at_PI_End(unsigned char x8data[]) {
124  return s2int16(x8data) == c2int16<C, '?', '>'>::value;
125}
126
127template<CodeUnit_Base C>
128inline bool at_CharRef_Start(unsigned char x8data[]) {
129  return s2int16(x8data) == c2int16<C, '&', '#'>::value;
130}
131
132
133template<CodeUnit_Base C>
134inline bool at_EqualsQuote(unsigned char x8data[]) {
135  uint16_t EQ = s2int16(x8data);
136  return (EQ == c2int16<C, '=', '"'>::value) | (EQ == c2int16<C, '=', '\''>::value);
137}
138
139template<CodeUnit_Base C>
140inline bool at_xmlns(unsigned char x8data[]) {
141  return s5int64(x8data) == c5int64<C, 'x', 'm', 'l', 'n', 's'>::value; 
142}
143
144template<CodeUnit_Base C>
145inline bool at_EmptyElementDelim(unsigned char x8data[]) {
146  return s2int16(x8data) == c2int16<C, '/', '>'>::value;
147}
148
149template<CodeUnit_Base C>
150inline bool at_XmlDecl_start(unsigned char x8data[]) {
151  return (s5int64(x8data) == c5int64<C, '<', '?', 'x', 'm', 'l'>::value) &&
152         at_WhiteSpace<XML_1_0, C>(&x8data[5]);
153}
154
155template<CodeUnit_Base C>
156inline bool at_version(unsigned char x8data[]) {
157  return s7int64(x8data) == c7int64<C, 'v', 'e', 'r', 's', 'i', 'o', 'n'>::value;
158}
159
160template<CodeUnit_Base C>
161inline bool at_1_0(unsigned char x8data[]) {
162  return (s5int64(x8data) == c5int64<C, '"', '1', '.', '0', '"'>::value) ||
163         (s5int64(x8data) == c5int64<C, '\'', '1', '.', '0', '\''>::value);
164}
165
166template<CodeUnit_Base C>
167inline bool at_1_1(unsigned char x8data[]) {
168  return (s5int64(x8data) == c5int64<C, '"', '1', '.', '1', '"'>::value) ||
169         (s5int64(x8data) == c5int64<C, '\'', '1', '.', '1', '\''>::value);
170}
171
172template<CodeUnit_Base C>
173inline bool at_encoding(unsigned char x8data[]) {
174  return s8int64(x8data) == c8int64<C, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g'>::value;
175}
176
177template<CodeUnit_Base C>
178inline bool at_standalone(unsigned char x8data[]) {
179  return (s8int64(x8data) == c8int64<C, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o'>::value) &
180         (s2int16(&x8data[8]) == c2int16<C, 'n', 'e'>::value);
181}
182
183template<CodeUnit_Base C>
184inline bool at_yes(unsigned char x8data[]) {
185  return (s5int64(x8data) == c5int64<C, '"', 'y', 'e', 's', '"'>::value) |
186         (s5int64(x8data) == c5int64<C, '\'', 'y', 'e', 's', '\''>::value);
187}
188
189template<CodeUnit_Base C>
190inline bool at_no(unsigned char x8data[]) {
191  return (s4int32(x8data) == c4int32<C, '"', 'n', 'o', '"'>::value) |
192         (s4int32(x8data) == c4int32<C, '\'', 'n', 'o', '\''>::value);
193}
194
195template<CodeUnit_Base C>
196inline bool at_XxMmLll(unsigned char x8data[]) {
197  return caseless_comp<C, 'x', 'm', 'l'>(x8data);
198}
199
200/* The at_ElementTag_Start recognizer rules out '<!', '<?', '</'
201   combinations while returning true for '<' followed by any NameStrt
202   character.
203*/
204template<CodeUnit_Base C>
205inline bool at_ElementTag_Start(unsigned char x8data[]) {
206  return (x8data[0] == Ord<C, '<'>::value) & (x8data[1] != Ord<C, '!'>::value) &
207         (x8data[1] != Ord<C, '?'>::value) & (x8data[1] != Ord<C, '/'>::value);
208}
209
210/* The following ugly hack optimizes for ASCII. */
211template<>
212inline bool at_ElementTag_Start<ASCII>(unsigned char x8data[]) {
213  return (x8data[0] == Ord<ASCII, '<'>::value) &
214         ((x8data[1] & 0xE1) != 0x21);
215}
216
217
218inline bool at_UTF_8(unsigned char x8data[]) {
219  return caseless_comp<ASCII, 'u', 't', 'f', '-', '8'>(x8data);
220}
221
222inline bool at_UCS_2(unsigned char x8data[]) {
223  return caseless_comp<ASCII, 'u', 'c', 's', '-', '2'>(x8data);
224}
225
226inline bool at_UCS_4(unsigned char x8data[]) {
227  return caseless_comp<ASCII, 'u', 'c', 's', '-', '4'>(x8data);
228}
229
230inline bool at_UCS_2LE(unsigned char x8data[]) {
231  return caseless_comp<ASCII, 'u', 'c', 's', '-', '2', 'l', 'e'>(x8data);
232}
233
234inline bool at_UCS_2BE(unsigned char x8data[]) {
235  return caseless_comp<ASCII, 'u', 'c', 's', '-', '2', 'b', 'e'>(x8data);
236}
237
238inline bool at_UCS_4LE(unsigned char x8data[]) {
239  return caseless_comp<ASCII, 'u', 'c', 's', '-', '4', 'l', 'e'>(x8data);
240}
241
242inline bool at_UCS_4BE(unsigned char x8data[]) {
243  return caseless_comp<ASCII, 'u', 'c', 's', '-', '4', 'b', 'e'>(x8data);
244}
245
246inline bool at_UTF_16(unsigned char x8data[]) {
247  return caseless_comp<ASCII, 'u', 't', 'f', '-', '1', '6'>(x8data);
248}
249
250inline bool at_UTF_32(unsigned char x8data[]) {
251  return caseless_comp<ASCII, 'u', 't', 'f', '-', '3', '2'>(x8data);
252}
253
254inline bool at_UTF_16LE(unsigned char x8data[]) {
255  return caseless_comp<ASCII, 'u', 't', 'f', '-', '1', '6', 'l', 'e'>(x8data);
256}
257
258inline bool at_UTF_32LE(unsigned char x8data[]) {
259  return caseless_comp<ASCII, 'u', 't', 'f', '-', '3', '2', 'l', 'e'>(x8data);
260}
261
262inline bool at_UTF_16BE(unsigned char x8data[]) {
263  return caseless_comp<ASCII, 'u', 't', 'f', '-', '1', '6', 'b', 'e'>(x8data);
264}
265
266inline bool at_UTF_32BE(unsigned char x8data[]) {
267  return caseless_comp<ASCII, 'u', 't', 'f', '-', '3', '2', 'b', 'e'>(x8data);
268}
269
270inline bool at_ASCII(unsigned char x8data[]) {
271  return caseless_comp<ASCII, 'a', 's', 'c', 'i', 'i'>(x8data);
272}
273
274inline bool at_Latin1(unsigned char x8data[]) {
275  return caseless_comp<ASCII, 'l', 'a', 't', 'i', 'n', '1'>(x8data);
276}
277
278inline bool at_EBCDIC(unsigned char x8data[]) {
279  return caseless_comp<EBCDIC, 'e', 'b', 'c', 'd', 'i', 'c'>(x8data);
280}
281
282template<CodeUnit_Base C>
283inline bool at_DOCTYPE_start(unsigned char x8data[]) {
284        return s8int64(x8data) == c8int64<C, '<', '!','D', 'O', 'C', 'T', 'Y', 'P'>::value & AtChar<C,'E'>(&x8data[8]);
285}
286
287template<CodeUnit_Base C>
288inline bool at_SYSTEM(unsigned char x8data[]) {
289        return s6int64(x8data) == c6int64<C, 'S', 'Y', 'S', 'T', 'E', 'M'>::value;
290}
291
292template<CodeUnit_Base C>
293inline bool at_PUBLIC(unsigned char x8data[]) {
294        return s6int64(x8data) == c6int64<C, 'P', 'U', 'B', 'L', 'I', 'C'>::value;
295}
296
297template<CodeUnit_Base C>
298inline bool at_ELEMENT(unsigned char x8data[]) {
299        return s7int64(x8data) == c7int64<C, 'E', 'L', 'E', 'M', 'E', 'N', 'T'>::value;
300}
301
302template<CodeUnit_Base C>
303inline bool at_ATTLIST(unsigned char x8data[]) {
304        return s7int64(x8data) == c7int64<C, 'A', 'T', 'T', 'L', 'I', 'S', 'T'>::value;
305}
306
307template<CodeUnit_Base C>
308inline bool at_ENTITY(unsigned char x8data[]) {
309        return s6int64(x8data) == c6int64<C, 'E', 'N', 'T', 'I', 'T', 'Y'>::value;
310}
311
312template<CodeUnit_Base C>
313inline bool at_NOTATION(unsigned char x8data[]) {
314        return s8int64(x8data) == c8int64<C, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N'>::value;
315}
316
317template<CodeUnit_Base C>
318inline bool at_EMPTY(unsigned char x8data[]) {
319        return s5int64(x8data) == c5int64<C, 'E', 'M', 'P', 'T', 'Y'>::value;
320}
321
322template<CodeUnit_Base C>
323inline bool at_PCDATA(unsigned char x8data[]) {
324        return s7int64(x8data) == c7int64<C, '#', 'P', 'C', 'D', 'A', 'T', 'A'>::value;
325}
326
327template<CodeUnit_Base C>
328inline bool at_Para_star(unsigned char x8data[]) {
329        return s2int16(x8data) == c2int16<C, ')', '*'>::value;
330}
331
332template<CodeUnit_Base C>
333inline bool at_CDATA(unsigned char x8data[]) {
334        return s5int64(x8data) == c5int64<C, 'C', 'D', 'A', 'T', 'A'>::value;
335}
336
337template<CodeUnit_Base C>
338inline bool at_ID(unsigned char x8data[]) {
339        return s2int16(x8data) == c2int16<C, 'I', 'D'>::value;
340}
341
342template<CodeUnit_Base C>
343inline bool at_IDREF(unsigned char x8data[]) {
344        return s5int64(x8data) == c5int64<C, 'I', 'D', 'R', 'E', 'F'>::value;
345}
346
347template<CodeUnit_Base C>
348inline bool at_NDATA(unsigned char x8data[]) {
349        return s5int64(x8data) == c5int64<C, 'N', 'D', 'A', 'T', 'A'>::value;
350}
351
352template<CodeUnit_Base C>
353inline bool at_IDREFS(unsigned char x8data[]) {
354        return s6int64(x8data) == c6int64<C, 'I', 'D', 'R', 'E', 'F', 'S'>::value;
355}
356
357template<CodeUnit_Base C>
358inline bool at_ENTITIES(unsigned char x8data[]) {
359        return s8int64(x8data) == c8int64<C, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S'>::value;
360}
361
362template<CodeUnit_Base C>
363inline bool at_NMTOKEN(unsigned char x8data[]) {
364        return s7int64(x8data) == c7int64<C, 'N', 'M', 'T', 'O', 'K', 'E', 'N'>::value;
365}
366
367template<CodeUnit_Base C>
368inline bool at_NMTOKENS(unsigned char x8data[]) {
369        return s8int64(x8data) == c8int64<C, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S'>::value;
370}
371
372template<CodeUnit_Base C>
373inline bool at_REQUIRED(unsigned char x8data[]) {
374        return s8int64(x8data) == c8int64<C, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E'>::value
375          & AtChar<C,'D'>(&x8data[8]);
376}
377
378template<CodeUnit_Base C>
379inline bool at_IMPLIED(unsigned char x8data[]) {
380        return s8int64(x8data) == c8int64<C, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D'>::value;
381}
382
383template<CodeUnit_Base C>
384inline bool at_FIXED(unsigned char x8data[]) {
385        return s6int64(x8data) == c6int64<C, '#', 'F', 'I', 'X', 'E', 'D'>::value;
386}
387
388template<CodeUnit_Base C>
389inline bool at_ANY(unsigned char x8data[]) {
390        return s3int32(x8data) == c3int32<C, 'A', 'N', 'Y'>::value;
391}
392
393template<CodeUnit_Base C>
394inline bool at_INCLUDE(unsigned char x8data[]) {
395        return s7int64(x8data) == c7int64<C, 'I', 'N', 'C', 'L', 'U', 'D', 'E'>::value;
396}
397
398template<CodeUnit_Base C>
399inline bool at_IGNORE(unsigned char x8data[]) {
400        return s6int64(x8data) == c6int64<C, 'I', 'G', 'N', 'O', 'R', 'E'>::value;
401}
402
403template<CodeUnit_Base C>
404inline bool at_condSect_start(unsigned char x8data[]) {
405        return s3int32(x8data) == c3int32<C, '<', '!', '['>::value;
406}
407
408template<CodeUnit_Base C>
409inline bool at_xml(unsigned char x8data[]) { 
410  return (s4int32(x8data) == c4int32<C, '?', 'x', 'm', 'l'>::value);
411}
412
413template<CodeUnit_Base C>
414inline bool at_PubidChar(unsigned char x8data[]) {
415        switch (x8data[0]) {
416                case Ord<C, '0'>::value: case Ord<C, '1'>::value: 
417                case Ord<C, '2'>::value: case Ord<C, '3'>::value: 
418                case Ord<C, '4'>::value: case Ord<C, '5'>::value:
419                case Ord<C, '6'>::value: case Ord<C, '7'>::value:
420                case Ord<C, '8'>::value: case Ord<C, '9'>::value:
421                case Ord<C, 'A'>::value: case Ord<C, 'a'>::value:
422                case Ord<C, 'B'>::value: case Ord<C, 'b'>::value:
423                case Ord<C, 'C'>::value: case Ord<C, 'c'>::value:
424                case Ord<C, 'D'>::value: case Ord<C, 'd'>::value:
425                case Ord<C, 'E'>::value: case Ord<C, 'e'>::value:
426                case Ord<C, 'F'>::value: case Ord<C, 'f'>::value:
427                case Ord<C, 'G'>::value: case Ord<C, 'g'>::value:
428                case Ord<C, 'H'>::value: case Ord<C, 'h'>::value:
429                case Ord<C, 'I'>::value: case Ord<C, 'i'>::value:
430                case Ord<C, 'J'>::value: case Ord<C, 'j'>::value:
431                case Ord<C, 'K'>::value: case Ord<C, 'k'>::value:
432                case Ord<C, 'L'>::value: case Ord<C, 'l'>::value:
433                case Ord<C, 'M'>::value: case Ord<C, 'm'>::value:
434                case Ord<C, 'N'>::value: case Ord<C, 'n'>::value:
435                case Ord<C, 'O'>::value: case Ord<C, 'o'>::value:
436                case Ord<C, 'P'>::value: case Ord<C, 'p'>::value:
437                case Ord<C, 'Q'>::value: case Ord<C, 'q'>::value:
438                case Ord<C, 'R'>::value: case Ord<C, 'r'>::value:
439                case Ord<C, 'S'>::value: case Ord<C, 's'>::value:
440                case Ord<C, 'T'>::value: case Ord<C, 't'>::value:
441                case Ord<C, 'U'>::value: case Ord<C, 'u'>::value:
442                case Ord<C, 'V'>::value: case Ord<C, 'v'>::value:
443                case Ord<C, 'W'>::value: case Ord<C, 'w'>::value:
444                case Ord<C, 'X'>::value: case Ord<C, 'x'>::value:
445                case Ord<C, 'Y'>::value: case Ord<C, 'y'>::value:
446                case Ord<C, 'Z'>::value: case Ord<C, 'z'>::value:
447                case Ord<C, '-'>::value: case Ord<C, '\''>::value:
448                case Ord<C, '('>::value: case Ord<C, ')'>::value:
449                case Ord<C, '+'>::value: case Ord<C, ','>::value:
450                case Ord<C, '.'>::value: case Ord<C, '/'>::value:
451                case Ord<C, ':'>::value: case Ord<C, '='>::value:
452                case Ord<C, '?'>::value: case Ord<C, ';'>::value:
453                case Ord<C, '!'>::value: case Ord<C, '*'>::value:
454                case Ord<C, '#'>::value: case Ord<C, '@'>::value:
455                case Ord<C, '$'>::value: case Ord<C, '_'>::value:
456                case Ord<C, '%'>::value: case Ord<C, ' '>::value:
457                case CR<C>::value: case LF<C>::value:
458                        return true;
459                default: return false;
460        }
461}
462#endif
Note: See TracBrowser for help on using the repository browser.