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