source: trunk/src/xmldecl.c @ 165

Last change on this file since 165 was 165, checked in by cameron, 11 years ago

new/delete for encoding; DeclError?

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