summaryrefslogtreecommitdiff
path: root/src/xmlreader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmlreader.cpp')
-rw-r--r--src/xmlreader.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp
new file mode 100644
index 0000000..9d299e6
--- /dev/null
+++ b/src/xmlreader.cpp
@@ -0,0 +1,165 @@
1#include "bu/xmlreader.h"
2#include "bu/stream.h"
3#include "bu/exceptions.h"
4
5Bu::XmlReader::XmlReader( Stream &rInput ) :
6 rInput( rInput ),
7 iCurToken( 0 ),
8 iNextToken( 0 ),
9 bIgnoreWS( true )
10{
11 nextToken();
12 stDocument();
13}
14
15Bu::XmlReader::~XmlReader()
16{
17}
18
19void Bu::XmlReader::fillBuffer()
20{
21 if( rInput.isEOS() )
22 return;
23 char buf[1024];
24 int iSize = rInput.read( buf, 1024 );
25 sBuf.append( buf, iSize );
26}
27
28void Bu::XmlReader::cleanupBuffer( int iUsed )
29{
30 for( int j = 0; j < iUsed; j++ )
31 {
32 if( sBuf[j] == '\n' )
33 {
34 spNextToken.iLine++;
35 spNextToken.iChar = 1;
36 }
37 else
38 {
39 spNextToken.iChar++;
40 }
41 }
42
43 printf("--Deleting %d bytes from front of buffer.\n", iUsed );
44 sBuf.trimFront( iUsed );
45}
46
47int Bu::XmlReader::nextToken()
48{
49 fillBuffer();
50
51 int iUsed = 1;
52
53 iCurToken = iNextToken;
54 spCurToken = spNextToken;
55
56 switch( sBuf[0] )
57 {
58 case '<':
59 if( !strncmp( sBuf.getStr(), "<?xml", 5 ) )
60 {
61 iNextToken = tokXmlDeclHead;
62 iUsed = 5;
63 }
64 else
65 {
66 iNextToken = '<';
67 }
68 break;
69
70 case '?':
71 if( sBuf[1] == '>' )
72 {
73 iNextToken = tokXmlDeclEnd;
74 iUsed = 2;
75 }
76 else
77 {
78 iNextToken = '?';
79 }
80 break;
81
82 case ' ':
83 case '\t':
84 case '\n':
85 case '\r':
86 for( int j = 1;; j++ )
87 {
88 if( j == sBuf.getSize() )
89 {
90 if( rInput.isEOS() )
91 error("Reached end of input while waiting for whitespace to end.");
92
93 fillBuffer();
94 }
95 if( sBuf[j] == ' ' || sBuf[j] == '\t' ||
96 sBuf[j] == '\n' || sBuf[j] == '\r' )
97 iUsed++;
98 else
99 break;
100 }
101 sStr.clear();
102 sStr.append( sBuf, iUsed );
103 iNextToken = tokWS;
104 break;
105
106 case '=':
107 iNextToken = sBuf[0];
108 break;
109
110 default:
111 if( (sBuf[0] >= 'a' && sBuf[0] <= 'z') ||
112 (sBuf[0] >= 'A' && sBuf[0] <= 'Z') )
113 {
114 for( int j = 1;; j++ )
115 {
116 if( j == sBuf.getSize() )
117 {
118 if( rInput.isEOS() )
119 error("Reached end of input while waiting for a string to end.");
120
121 fillBuffer();
122 }
123 if( (sBuf[j] >= 'a' && sBuf[j] <= 'z') ||
124 (sBuf[j] >= 'A' && sBuf[j] <= 'Z') )
125 iUsed++;
126 else
127 break;
128 }
129 sStr.clear();
130 sStr.append( sBuf, iUsed );
131 iNextToken = tokIdent;
132 }
133 }
134
135 cleanupBuffer( iUsed );
136
137 return iCurToken;
138}
139
140void Bu::XmlReader::error( const char *sMessage )
141{
142 throw Bu::XmlException("%d:%d: %s",
143 spCurToken.iLine, spCurToken.iChar, sMessage );
144}
145
146void Bu::XmlReader::stDocument()
147{
148 stProlog();
149}
150
151void Bu::XmlReader::stProlog()
152{
153 stXmlDecl();
154}
155
156void Bu::XmlReader::stXmlDecl()
157{
158 if( nextToken() != tokXmlDeclHead )
159 error("You must begin your xml file with a declaration: <?xml ... ?>");
160 if( nextToken() != tokIdent )
161 error("A version comes first!");
162 if( sStr != "version" )
163 error("No, a version!");
164}
165