diff options
Diffstat (limited to 'src/xmlreader.cpp')
-rw-r--r-- | src/xmlreader.cpp | 165 |
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 | |||
5 | Bu::XmlReader::XmlReader( Stream &rInput ) : | ||
6 | rInput( rInput ), | ||
7 | iCurToken( 0 ), | ||
8 | iNextToken( 0 ), | ||
9 | bIgnoreWS( true ) | ||
10 | { | ||
11 | nextToken(); | ||
12 | stDocument(); | ||
13 | } | ||
14 | |||
15 | Bu::XmlReader::~XmlReader() | ||
16 | { | ||
17 | } | ||
18 | |||
19 | void 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 | |||
28 | void 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 | |||
47 | int 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 | |||
140 | void Bu::XmlReader::error( const char *sMessage ) | ||
141 | { | ||
142 | throw Bu::XmlException("%d:%d: %s", | ||
143 | spCurToken.iLine, spCurToken.iChar, sMessage ); | ||
144 | } | ||
145 | |||
146 | void Bu::XmlReader::stDocument() | ||
147 | { | ||
148 | stProlog(); | ||
149 | } | ||
150 | |||
151 | void Bu::XmlReader::stProlog() | ||
152 | { | ||
153 | stXmlDecl(); | ||
154 | } | ||
155 | |||
156 | void 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 | |||