source: trunk/src/xmldecl.c @ 125

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

Consolidation of error handling: xml_error.c

File size: 5.5 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
20template <CodeUnit_Base C>
21XML_Decl_Parser<C>::XML_Decl_Parser(Byteplex * b){
22        byteplex = b;
23        buffer_base_pos = 0;
24        x8data = (unsigned char *) byteplex->x8data;
25}
26
27template <CodeUnit_Base C>
28XML_Decl_Parser<C>::~XML_Decl_Parser(){
29}
30
31template <CodeUnit_Base C>
32inline int XML_Decl_Parser<C>::AbsPos() const {
33        return  buffer_base_pos + buffer_rel_pos;
34}
35
36template <CodeUnit_Base C>
37inline unsigned char * XML_Decl_Parser<C>::cur() const {
38        return &x8data[buffer_rel_pos];
39}
40
41template <CodeUnit_Base C>
42inline void XML_Decl_Parser<C>::Advance(int n) {
43        buffer_rel_pos += n;
44        if (buffer_rel_pos >= BYTEPLEX_SIZE) {
45                 byteplex->AdvanceInputBuffer(BYTEPLEX_SIZE);
46        }
47}
48
49template <CodeUnit_Base C>
50inline void XML_Decl_Parser<C>::Scan_WS() {
51        while (at_WhiteSpace<XML_1_0, C>(cur())) Advance(1);
52}
53
54template <CodeUnit_Base C>
55inline void XML_Decl_Parser<C>::ScanToQuote() {
56        int quote_start_pos = buffer_rel_pos;   
57        while (!AtQuote<C>(cur())) buffer_rel_pos+=1;
58        if (buffer_rel_pos >= BYTEPLEX_SIZE) {
59                byteplex->AdvanceInputBuffer(quote_start_pos);
60                buffer_rel_pos -= quote_start_pos;
61                buffer_base_pos += quote_start_pos;
62                while (!AtQuote<C>(cur())) buffer_rel_pos+=1;
63                if (buffer_rel_pos >= BYTEPLEX_SIZE) {
64                        ImplementationLimitError("Encoding name exceeds BYTEPLEX_SIZE");
65                }
66        }
67}
68
69template <CodeUnit_Base C>
70int XML_Decl_Parser<C>::EncodingAction(Entity_Info *e, int start_pos, int end_pos) {
71        e->encoding = (unsigned char *) malloc(end_pos-start_pos+1);
72        memcpy(e->encoding, &x8data[start_pos-buffer_base_pos], end_pos - start_pos);
73        e->encoding[end_pos - start_pos] = '\0';
74}
75//
76template <CodeUnit_Base C>
77int XML_Decl_Parser<C>::ReadXMLInfo(Entity_Info *e) {
78        e->version = no_XML_version_value;
79        e->has_encoding_decl = false;
80        e->standalone = Standalone_no_value;
81        buffer_rel_pos = e->BOM_units;
82        // It is possible that there is no XML declaration.
83        if (!at_XmlDecl_start<C>(cur())) {
84                return AbsPos();
85        }
86        // Otherwise, the XML declaration exists and must have
87        // at least version information.
88        Advance(6);
89        Scan_WS();
90        if (!at_version<C>(cur())) DeclarationError(AbsPos());
91        Advance(7);
92        Scan_WS();
93        if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
94        Advance(1);
95        Scan_WS();
96        if (at_1_0<C>(cur())) e->version = XML_1_0;
97        else if (at_1_1<C>(cur())) e->version = XML_1_1;
98        else DeclarationError(AbsPos());
99        Advance(5);
100        if (at_PI_End<C>(cur())) return AbsPos()+2;
101        if (!at_WhiteSpace<XML_1_0, ASCII>(cur())) DeclarationError(AbsPos());
102        Scan_WS();
103        if (at_encoding<C>(cur())) {
104                e->has_encoding_decl = true;
105                Advance(8);
106                Scan_WS();
107                if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
108                Advance(1);
109                Scan_WS();
110                if (AtQuote<C>(cur())) {
111                        unsigned char quoteCh = cur()[0];
112                        Advance(1);
113                        int encoding_start_pos = AbsPos();
114                        ScanToQuote();
115                        if (cur()[0] != quoteCh) DeclarationError(AbsPos());
116                        EncodingAction(e, encoding_start_pos, AbsPos());
117                }
118                else DeclarationError(AbsPos());
119                Advance(1);
120                if (at_PI_End<C>(cur())) return AbsPos()+2;
121                if (!at_WhiteSpace<XML_1_0, ASCII>(cur())) DeclarationError(AbsPos());
122                Scan_WS();
123        }
124        if (at_standalone<C>(cur())) {
125                Advance(10);
126                Scan_WS();
127                if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
128                Advance(1);
129                Scan_WS();
130                if (at_yes<C>(cur())) {Advance(5); e->standalone = Standalone_yes;}
131                else if (at_no<C>(cur())) {Advance(4); e->standalone = Standalone_no;}
132                else DeclarationError(AbsPos());
133                Scan_WS();
134        }
135        if (!at_PI_End<C>(cur())) DeclarationError(AbsPos());
136        return AbsPos()+2;
137}
138
139// Similar to reading the XML_declaration of the document entity,
140// ReadTextDeclaration reads the text declaration of an external
141// parsed entity.  This is not really needed at present, for DTDless
142// processing.
143template <CodeUnit_Base C>
144int XML_Decl_Parser<C>::ReadTextDeclaration(Entity_Info *e) {
145        e->version = no_XML_version_value;
146        e->has_encoding_decl = false;
147        e->standalone = Standalone_no_value;
148        buffer_rel_pos = e->BOM_units;
149        // It is possible that there is no XML declaration.
150        if (!at_XmlDecl_start<C>(cur())) {
151                return AbsPos();
152        }
153        // Otherwise, the text declaration exists and may have
154        // version information.
155        Advance(6);
156        Scan_WS();
157        if (at_version<C>(cur())) {
158                Advance(7);
159                Scan_WS();
160                if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
161                Advance(1);
162                Scan_WS();
163                if (at_1_0<C>(cur())) e->version = XML_1_0;
164                else if (at_1_1<C>(cur())) e->version = XML_1_1;
165                else DeclarationError(AbsPos());
166                Advance(5);
167                // Must have whitespace character before declaration.
168                if (!at_WhiteSpace<XML_1_0, ASCII>(cur())) DeclarationError(AbsPos());
169                Scan_WS();
170        }
171        if (!at_encoding<C>(cur())) DeclarationError(AbsPos());
172        e->has_encoding_decl = true;
173        Advance(8);
174        Scan_WS();
175        if (!AtChar<C,'='>(cur())) DeclarationError(AbsPos());
176        Advance(1);
177        Scan_WS();
178        if (AtQuote<C>(cur())) {
179                unsigned char quoteCh = cur()[0];
180                Advance(1);
181                int encoding_start_pos = AbsPos();
182                ScanToQuote();
183                if (cur()[0] != quoteCh) DeclarationError(AbsPos());
184                EncodingAction(e, encoding_start_pos, AbsPos());
185        }
186        else DeclarationError(AbsPos());
187        Advance(1);
188        Scan_WS();
189        if (!at_PI_End<C>(cur())) DeclarationError(AbsPos());
190        return AbsPos()+2;
191}
192
Note: See TracBrowser for help on using the repository browser.