source: trunk/src/xmldecl.c @ 163

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

Restructuring: Document/Externalt? Entity Info into xmldecl.h

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