summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fstring.h21
-rw-r--r--src/unit/xml.cpp39
-rw-r--r--src/xmlreader.cpp165
-rw-r--r--src/xmlreader.h54
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
13class Unit : public Bu::UnitSuite
14{
15public:
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
35int 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
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
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
6namespace 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