diff options
Diffstat (limited to '')
-rw-r--r-- | src/fstring.h | 21 | ||||
-rw-r--r-- | src/unit/xml.cpp | 39 | ||||
-rw-r--r-- | src/xmlreader.cpp | 165 | ||||
-rw-r--r-- | src/xmlreader.h | 54 |
4 files changed, 278 insertions, 1 deletions
diff --git a/src/fstring.h b/src/fstring.h index 8b22160..fb4bf55 100644 --- a/src/fstring.h +++ b/src/fstring.h | |||
@@ -187,7 +187,26 @@ namespace Bu | |||
187 | append( &cData, 1 ); | 187 | append( &cData, 1 ); |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | ||
192 | * Append another FString to this one. | ||
193 | *@param sData (MyType &) The FString to append. | ||
194 | */ | ||
195 | void append( const MyType & sData ) | ||
196 | { | ||
197 | append( sData.getStr(), sData.getSize() ); | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * Append another FString to this one. | ||
202 | *@param sData (MyType &) The FString to append. | ||
203 | *@param nLen How much data to append. | ||
204 | */ | ||
205 | void append( const MyType & sData, long nLen ) | ||
206 | { | ||
207 | append( sData.getStr(), nLen ); | ||
208 | } | ||
209 | |||
191 | /** | 210 | /** |
192 | * Prepend another FString to this one. | 211 | * Prepend another FString to this one. |
193 | *@param sData (MyType &) The FString to prepend. | 212 | *@param sData (MyType &) The FString to prepend. |
diff --git a/src/unit/xml.cpp b/src/unit/xml.cpp new file mode 100644 index 0000000..e845cc1 --- /dev/null +++ b/src/unit/xml.cpp | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2008 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/fstring.h" | ||
9 | #include "bu/unitsuite.h" | ||
10 | #include "bu/xmlreader.h" | ||
11 | #include "bu/membuf.h" | ||
12 | |||
13 | class Unit : public Bu::UnitSuite | ||
14 | { | ||
15 | public: | ||
16 | Unit() | ||
17 | { | ||
18 | setName("Xml"); | ||
19 | addTest( Unit::declaration ); | ||
20 | } | ||
21 | |||
22 | virtual ~Unit() | ||
23 | { | ||
24 | } | ||
25 | |||
26 | void declaration() | ||
27 | { | ||
28 | Bu::FString sXml("<?xml ?> <hi />"); | ||
29 | Bu::MemBuf buf( sXml ); | ||
30 | Bu::XmlReader xr( buf ); | ||
31 | } | ||
32 | |||
33 | }; | ||
34 | |||
35 | int main( int argc, char *argv[] ) | ||
36 | { | ||
37 | return Unit().run( argc, argv ); | ||
38 | } | ||
39 | |||
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 | |||
diff --git a/src/xmlreader.h b/src/xmlreader.h new file mode 100644 index 0000000..375dfe3 --- /dev/null +++ b/src/xmlreader.h | |||
@@ -0,0 +1,54 @@ | |||
1 | #ifndef BU_XML_READER_H | ||
2 | #define BU_XML_READER_H | ||
3 | |||
4 | #include "bu/fstring.h" | ||
5 | |||
6 | namespace Bu | ||
7 | { | ||
8 | class Stream; | ||
9 | |||
10 | class XmlReader | ||
11 | { | ||
12 | public: | ||
13 | XmlReader( Stream &rInput ); | ||
14 | virtual ~XmlReader(); | ||
15 | |||
16 | private: | ||
17 | Stream &rInput; | ||
18 | int iCurToken; | ||
19 | int iNextToken; | ||
20 | Bu::FString sBuf; | ||
21 | Bu::FString sStr; | ||
22 | bool bIgnoreWS; | ||
23 | typedef struct StreamPos | ||
24 | { | ||
25 | StreamPos() : iLine( 1 ), iChar( 1 ) { } | ||
26 | int iLine; | ||
27 | int iChar; | ||
28 | } StreamPos; | ||
29 | StreamPos spCurToken; | ||
30 | StreamPos spNextToken; | ||
31 | |||
32 | |||
33 | enum | ||
34 | { | ||
35 | tokXmlDeclHead = 0x100, | ||
36 | tokXmlDeclEnd, | ||
37 | tokWS, | ||
38 | tokIdent, | ||
39 | tokString | ||
40 | }; | ||
41 | |||
42 | void fillBuffer(); | ||
43 | void cleanupBuffer( int iUsed ); | ||
44 | int nextToken(); | ||
45 | |||
46 | void stDocument(); | ||
47 | void stProlog(); | ||
48 | void stXmlDecl(); | ||
49 | |||
50 | void error( const char *sMessage ); | ||
51 | }; | ||
52 | }; | ||
53 | |||
54 | #endif | ||