source: proto/parabix2/util/xmldecl.c @ 4183

Last change on this file since 4183 was 2172, checked in by ksherdy, 7 years ago

Add support headers.

File size: 8.3 KB
Line 
1/*  xmldecl.c - Parsing XML and Text Declarations.
2    Copyright (c) 2008, Robert D. Cameron.
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters, Inc., under the Academic
5    Free License 3.0.
6
7*/
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/types.h>
12
13#include "xml_error.h"
14#include "multiliteral.h"
15#include "bytelex.h"
16
17
18Entity_Info::Entity_Info() {
19        encoding = NULL;
20}
21Entity_Info::~Entity_Info() {
22        delete [] encoding;
23}
24
25/* Signature-based character set family detection in accord with
26   Appendix F of the XML 1.0 and 1.1 specifications. */
27
28/* These definitions use b2int16 to determine appropriate doublebyte
29   values based on endianness of the underlying architecture. */
30static const int x0000 = b2int16<0x00, 0x00>::value;
31static const int xFEFF = b2int16<0xFE, 0xFF>::value;
32static const int xFFFE = b2int16<0xFF, 0xFE>::value;
33static const int x003C = b2int16<0x00, 0x3C>::value;
34static const int x3C00 = b2int16<0x3C, 0x00>::value;
35static const int x4C6F = b2int16<0x4C, 0x6F>::value;
36static const int xA794 = b2int16<0xA7, 0x94>::value;
37static const int xEFBE = b2int16<0xEF, 0xBE>::value;
38
39void Entity_Info::AnalyzeSignature(unsigned char * signature) {
40        uint16_t * XML_dbl_byte = (uint16_t *) signature;
41        switch (XML_dbl_byte[0]) {
42                case x0000:
43                        switch (XML_dbl_byte[1]) {
44                                case xFEFF: set_charset_family(ASCII, QuadByte, BigEndian, 1);break;
45                                case xFFFE: set_charset_family(ASCII, QuadByte, Unusual_2143, 1);break;
46                                case x3C00: set_charset_family(ASCII, QuadByte, Unusual_2143, 0);break;
47                                default: set_charset_family(ASCII, QuadByte, BigEndian, 0);
48                        }
49                        break;
50                case xFEFF:
51                        if (XML_dbl_byte[1] == x0000)
52                                set_charset_family(ASCII, QuadByte, Unusual_3412, 1);
53                        else set_charset_family(ASCII, DoubleByte, BigEndian, 1);
54                        break;
55                case xFFFE:
56                        if (XML_dbl_byte[1] == x0000)
57                                set_charset_family(ASCII, QuadByte, LittleEndian, 1);
58                        else set_charset_family(ASCII, DoubleByte, LittleEndian, 1);
59                        break;
60                case x003C:
61                        if (XML_dbl_byte[1] == x0000)
62                                set_charset_family(ASCII, QuadByte, Unusual_3412, 0);
63                        else set_charset_family(ASCII, DoubleByte, BigEndian, 0);
64                        break;
65                case x3C00:
66                        if (XML_dbl_byte[1] == x0000)
67                                set_charset_family(ASCII, QuadByte, LittleEndian, 0);
68                        else set_charset_family(ASCII, DoubleByte, LittleEndian, 0);
69                        break;
70                case x4C6F:
71                        if (XML_dbl_byte[1] == xA794)
72                                set_charset_family(EBCDIC, SingleByte, BigEndian, 0);
73                        else set_charset_family(ASCII, SingleByte, BigEndian, 0);
74                        break;
75                case xEFBE:
76                        if (signature[2] == 0xBF)
77                                set_charset_family(ASCII, SingleByte, BigEndian, 3);
78                        else set_charset_family(ASCII, SingleByte, BigEndian, 0);
79                        break;
80                default:
81                        set_charset_family(ASCII, SingleByte, BigEndian, 0);
82        }
83}
84void Entity_Info::set_charset_family(CodeUnit_Base C, CodeUnit_Size S, CodeUnit_ByteOrder O, int B){
85                code_unit_base = C;
86                code_unit_size = S;
87                byte_order = O;
88                BOM_units = B;
89 }
90
91
92template <CodeUnit_Base C>
93XML_Decl_Parser<C>::XML_Decl_Parser(unsigned char * bytes){
94        buffer_base_pos = 0;
95        x8data = bytes;
96}
97
98template <CodeUnit_Base C>
99XML_Decl_Parser<C>::~XML_Decl_Parser(){
100}
101
102template <CodeUnit_Base C>
103inline void XML_Decl_Parser<C>::DeclError() {
104        DeclarationError(AbsPos());
105}
106
107template <CodeUnit_Base C>
108inline int XML_Decl_Parser<C>::AbsPos() const {
109        return  buffer_base_pos + buffer_rel_pos;
110}
111
112template <CodeUnit_Base C>
113inline unsigned char * XML_Decl_Parser<C>::cur() const {
114        return &x8data[buffer_rel_pos];
115}
116
117template <CodeUnit_Base C>
118inline void XML_Decl_Parser<C>::Advance(int n) {
119        buffer_rel_pos += n;
120}
121
122template <CodeUnit_Base C>
123inline void XML_Decl_Parser<C>::Scan_WS() {
124        while (at_WhiteSpace_10<C>(cur())) Advance(1);
125}
126
127template <CodeUnit_Base C>
128inline void XML_Decl_Parser<C>::ScanEncodingName() {
129        if (at_ASCII_letter<C>(cur())) {
130          Advance(1);
131          while (at_ASCII_ncnamechar<C>(cur())) Advance(1);
132        }
133}
134
135template <CodeUnit_Base C>
136inline void XML_Decl_Parser<C>::ParseVersion(Entity_Info & e) {
137        /* Skip "version" */
138        Advance(7);
139        Scan_WS();
140        if (!AtChar<C,'='>(cur())) DeclError();
141        Advance(1);
142        Scan_WS();
143        if (at_1_0<C>(cur())) e.version = XML_1_0;
144        else if (at_1_1<C>(cur())) e.version = XML_1_1;
145        else DeclError();
146        Advance(5);
147}
148
149template <CodeUnit_Base C>
150inline void XML_Decl_Parser<C>::ParseEncoding(Entity_Info & e) {
151        /* Skip "encoding" */
152        Advance(8);
153        e.has_encoding_decl = true;
154        Scan_WS();
155        if (!AtChar<C,'='>(cur())) DeclError();
156        Advance(1);
157        Scan_WS();
158        if (AtQuote<C>(cur())) {
159                unsigned char quoteCh = cur()[0];
160                Advance(1);
161                int start_pos = AbsPos();
162                ScanEncodingName();
163                if (cur()[0] != quoteCh) DeclError();
164                int lgth = AbsPos() - start_pos;
165                e.encoding = new unsigned char[lgth + 1];
166                memcpy(e.encoding, &x8data[start_pos-buffer_base_pos], lgth);
167                e.encoding[lgth] = '\0';
168        }
169        else DeclError();
170        Advance(1);
171}
172
173template <CodeUnit_Base C>
174inline void XML_Decl_Parser<C>::ParseStandalone(Entity_Info & e) {
175        /* Skip "standalone" */
176        Advance(10);
177        Scan_WS();
178        if (!AtChar<C,'='>(cur())) DeclError();
179        Advance(1);
180        Scan_WS();
181        if (at_yes<C>(cur())) {Advance(5); e.standalone = Standalone_yes;}
182        else if (at_no<C>(cur())) {Advance(4); e.standalone = Standalone_no;}
183        else DeclError();
184}
185
186template <CodeUnit_Base C>
187void XML_Decl_Parser<C>::ReadXMLInfo(Entity_Info & e) {
188        e.version = no_XML_version_value;
189        e.has_encoding_decl = false;
190        e.standalone = Standalone_no_value;
191        buffer_rel_pos = e.BOM_units;
192        // It is possible that there is no XML declaration.
193        if (!at_XmlDecl_start<C>(cur())) {
194                e.content_start = AbsPos();
195                return;
196        }
197        // Otherwise, the XML declaration exists and must have
198        // at least version information.
199        Advance(6);
200        Scan_WS();
201        if (!at_version<C>(cur())) DeclError();
202        ParseVersion(e);
203        if (at_PI_End<C>(cur())) {
204                e.content_start = AbsPos()+2;
205                return;
206        }
207        if (!at_WhiteSpace_10<C>(cur())) DeclError();
208        Scan_WS();
209        if (at_encoding<C>(cur())) {
210                ParseEncoding(e);
211                if (at_PI_End<C>(cur())) {
212                        e.content_start = AbsPos()+2;
213                        return;
214                }
215                if (!at_WhiteSpace_10<C>(cur())) DeclError();
216                Scan_WS();
217        }
218        if (at_standalone<C>(cur())) {
219                ParseStandalone(e);
220                Scan_WS();
221        }
222        if (!at_PI_End<C>(cur())) DeclError();
223        e.content_start = AbsPos()+2;
224}
225
226// Similar to reading the XML_declaration of the document entity,
227// ReadTextDeclaration reads the text declaration of an external
228// parsed entity.
229
230template <CodeUnit_Base C>
231void XML_Decl_Parser<C>::ReadTextDeclaration(Entity_Info & e) {
232        e.version = no_XML_version_value;
233        e.has_encoding_decl = false;
234        e.standalone = Standalone_no_value;
235        buffer_rel_pos = e.BOM_units;
236        // It is possible that there is no text declaration.
237        if (!at_XmlDecl_start<C>(cur())) {
238                e.content_start = AbsPos();
239                return;
240        }
241        // Otherwise, the text declaration exists and may have
242        // version information.
243        Advance(6);
244        Scan_WS();
245        if (at_version<C>(cur())) {
246                ParseVersion(e);
247                // Must have whitespace character before encoding declaration.
248                if (!at_WhiteSpace_10<C>(cur())) DeclError();
249                Scan_WS();
250        }
251        if (!at_encoding<C>(cur())) DeclError();
252        ParseEncoding(e);
253        Scan_WS();
254        if (!at_PI_End<C>(cur())) DeclError();
255        e.content_start = AbsPos()+2;
256}
257
258template <CodeUnit_Base C>
259void XML_Decl_Parser<C>::ReadXMLorTextDecl(Entity_Info & e) {
260        e.version = no_XML_version_value;
261        e.has_encoding_decl = false;
262        e.standalone = Standalone_no_value;
263        buffer_rel_pos = e.BOM_units;
264        // It is possible that there is no XML or text declaration.
265        if (!at_XmlDecl_start<C>(cur())) {
266                e.content_start = AbsPos();
267                return;
268        }
269        // Otherwise, the XML or text declaration exists and may have
270        // version information.
271        Advance(6);
272        Scan_WS();
273        if (at_version<C>(cur())) {
274                ParseVersion(e);
275                if (at_PI_End<C>(cur())) {
276                        e.content_start = AbsPos()+2;
277                        return;
278                }
279                if (!at_WhiteSpace_10<C>(cur())) DeclError();
280                Scan_WS();
281                if (at_encoding<C>(cur())) {
282                        ParseEncoding(e);
283                        if (at_PI_End<C>(cur())) {
284                                e.content_start = AbsPos()+2;
285                                return;
286                        }
287                        if (!at_WhiteSpace_10<C>(cur())) DeclError();
288                        Scan_WS();
289                }
290                if (at_standalone<C>(cur())) {
291                        ParseStandalone(e);
292                        Scan_WS();
293                }
294        }
295        else {  // Without version, we can only have a text declaration,
296                // in which case an encoding spec is required.
297                if (!at_encoding<C>(cur())) DeclError();
298                ParseEncoding(e);
299                Scan_WS();
300                // No standalone spec is allowed in a text declaration.
301        }
302        if (!at_PI_End<C>(cur())) DeclError(); 
303        e.content_start = AbsPos()+2;
304}
Note: See TracBrowser for help on using the repository browser.