diff options
Diffstat (limited to 'src/stable/formatter.h')
-rw-r--r-- | src/stable/formatter.h | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/src/stable/formatter.h b/src/stable/formatter.h new file mode 100644 index 0000000..a440ec3 --- /dev/null +++ b/src/stable/formatter.h | |||
@@ -0,0 +1,303 @@ | |||
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 | #ifndef BU_FORMATTER_H | ||
9 | #define BU_FORMATTER_H | ||
10 | |||
11 | #include "bu/string.h" | ||
12 | #include "bu/fmt.h" | ||
13 | |||
14 | #include <math.h> | ||
15 | |||
16 | namespace Bu | ||
17 | { | ||
18 | class Stream; | ||
19 | |||
20 | template<typename t> t tlog( t x ); | ||
21 | template<> float tlog( float x ); | ||
22 | template<> double tlog( double x ); | ||
23 | template<> long double tlog( long double x ); | ||
24 | |||
25 | template<typename t> t tfloor( t x ); | ||
26 | template<> float tfloor( float x ); | ||
27 | template<> double tfloor( double x ); | ||
28 | template<> long double tfloor( long double x ); | ||
29 | |||
30 | template<typename t> t tpow( t x, t y ); | ||
31 | template<> float tpow( float x, float y ); | ||
32 | template<> double tpow( double x, double y ); | ||
33 | template<> long double tpow( long double x, long double y ); | ||
34 | |||
35 | class Formatter | ||
36 | { | ||
37 | public: | ||
38 | Formatter( Stream &rStream ); | ||
39 | virtual ~Formatter(); | ||
40 | |||
41 | void write( const Bu::String &sStr ); | ||
42 | void write( const void *sStr, int iLen ); | ||
43 | void writeAligned( const Bu::String &sStr ); | ||
44 | void writeAligned( const char *sStr, int iLen ); | ||
45 | |||
46 | void read( void *sStr, int iLen ); | ||
47 | Bu::String readToken(); | ||
48 | |||
49 | void incIndent(); | ||
50 | void decIndent(); | ||
51 | void setIndent( uint8_t uLevel ); | ||
52 | void clearIndent(); | ||
53 | uint8_t getIndent() const { return uIndent; } | ||
54 | void setIndentChar( char cIndent ); | ||
55 | char getIndentChar() const { return cIndent; } | ||
56 | |||
57 | void setFormat( const Fmt &f ) | ||
58 | { | ||
59 | fLast = f; | ||
60 | bTempFmt = false; | ||
61 | } | ||
62 | |||
63 | void setTempFormat( const Fmt &f ) | ||
64 | { | ||
65 | fLast = f; | ||
66 | bTempFmt = true; | ||
67 | } | ||
68 | |||
69 | void usedFormat() | ||
70 | { | ||
71 | if( bTempFmt ) | ||
72 | fLast = Fmt(); | ||
73 | } | ||
74 | |||
75 | template<typename type> | ||
76 | void ifmt( type i ) | ||
77 | { | ||
78 | // This code is taken from Nango, hopefully we can make it better. | ||
79 | bool bNeg = i<0; | ||
80 | char cBase = fLast.bCaps?'A':'a'; | ||
81 | char buf[sizeof(type)*8+1]; | ||
82 | if( bNeg ) i = -i; | ||
83 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | ||
84 | { | ||
85 | usedFormat(); | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | for( int j = sizeof(type)*8; j >= 0; j-- ) | ||
90 | { | ||
91 | int c = i%fLast.uRadix; | ||
92 | i /= fLast.uRadix; | ||
93 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); | ||
94 | if( i == 0 ) | ||
95 | { | ||
96 | if( bNeg ) buf[--j] = '-'; | ||
97 | else if( fLast.bPlus ) buf[--j] = '+'; | ||
98 | writeAligned( buf+j, sizeof(type)*8-j+1 ); | ||
99 | |||
100 | return; | ||
101 | } | ||
102 | } | ||
103 | usedFormat(); | ||
104 | } | ||
105 | |||
106 | template<typename type> | ||
107 | void ufmt( type i ) | ||
108 | { | ||
109 | // This code is taken from Nango, hopefully we can make it better. | ||
110 | char buf[sizeof(type)*8+1]; | ||
111 | char cBase = fLast.bCaps?'A':'a'; | ||
112 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | ||
113 | { | ||
114 | usedFormat(); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | for( int j = sizeof(type)*8; j >= 0; j-- ) | ||
119 | { | ||
120 | int c = i%fLast.uRadix; | ||
121 | i /= fLast.uRadix; | ||
122 | buf[j] = (char)((c<10)?('0'+c):(cBase+c-10)); | ||
123 | if( i == 0 ) | ||
124 | { | ||
125 | if( fLast.bPlus ) buf[--j] = '+'; | ||
126 | writeAligned( buf+j, sizeof(type)*8-j+1 ); | ||
127 | |||
128 | return; | ||
129 | } | ||
130 | } | ||
131 | usedFormat(); | ||
132 | } | ||
133 | |||
134 | template<typename type> | ||
135 | void ffmt( type f ) | ||
136 | { | ||
137 | Bu::String fTmp; | ||
138 | char cBase = fLast.bCaps?'A':'a'; | ||
139 | if( fLast.uRadix < 2 || fLast.uRadix > 36 ) | ||
140 | { | ||
141 | usedFormat(); | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | if( signbit(f) ) | ||
146 | { | ||
147 | f = -f; | ||
148 | fTmp += "-"; | ||
149 | } | ||
150 | int iScale = tfloor(tlog( f ) / tlog( (type)fLast.uRadix )); | ||
151 | f /= tpow( (type)fLast.uRadix, (type)iScale ); | ||
152 | |||
153 | if( iScale < 0 ) | ||
154 | { | ||
155 | fTmp += "0."; | ||
156 | for( int j = 1; j < -iScale; j++ ) | ||
157 | fTmp += '0'; | ||
158 | } | ||
159 | int c = f; | ||
160 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); | ||
161 | f -= (int)f; | ||
162 | int j; | ||
163 | for( j = 0; j < 8 && f; j++ ) | ||
164 | { | ||
165 | if( iScale - j == 0 ) | ||
166 | fTmp += '.'; | ||
167 | f = f*fLast.uRadix; | ||
168 | int c = f; | ||
169 | fTmp += (char)((c<10)?('0'+c):(cBase+c-10)); | ||
170 | f -= (int)f; | ||
171 | } | ||
172 | if( iScale >= j ) | ||
173 | { | ||
174 | for( int k = j; k < iScale; k++ ) | ||
175 | fTmp += '0'; | ||
176 | fTmp += ".0"; | ||
177 | } | ||
178 | |||
179 | writeAligned( fTmp ); | ||
180 | usedFormat(); | ||
181 | } | ||
182 | |||
183 | template<typename type> | ||
184 | void iparse( type &i, const Bu::String &sBuf ) | ||
185 | { | ||
186 | if( !sBuf.isSet() ) | ||
187 | return; | ||
188 | if( sBuf[0] != '+' && sBuf[0] != '-' && | ||
189 | (sBuf[0] < '0' && sBuf[0] > '9') ) | ||
190 | return; | ||
191 | int j = 1; | ||
192 | int iMax = sBuf.getSize(); | ||
193 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } | ||
194 | i = 0; | ||
195 | type iPos = 1; | ||
196 | for(j--; j >= 0; j-- ) | ||
197 | { | ||
198 | if( sBuf[j] == '+' || sBuf[j] == '-' ) | ||
199 | continue; | ||
200 | i += (sBuf[j]-'0')*iPos; | ||
201 | iPos *= fLast.uRadix; | ||
202 | } | ||
203 | if( sBuf[0] == '-' ) | ||
204 | i = -i; | ||
205 | |||
206 | usedFormat(); | ||
207 | } | ||
208 | |||
209 | template<typename type> | ||
210 | void uparse( type &i, const Bu::String &sBuf ) | ||
211 | { | ||
212 | if( !sBuf.isSet() ) | ||
213 | return; | ||
214 | if( sBuf[0] != '+' && | ||
215 | (sBuf[0] < '0' && sBuf[0] > '9') ) | ||
216 | return; | ||
217 | int j = 1; | ||
218 | int iMax = sBuf.getSize(); | ||
219 | for(; j < iMax && (sBuf[j] >= '0' && sBuf[j] <= '9'); j++ ) { } | ||
220 | i = 0; | ||
221 | type iPos = 1; | ||
222 | for(j--; j >= 0; j-- ) | ||
223 | { | ||
224 | if( sBuf[j] == '+' ) | ||
225 | continue; | ||
226 | i += (sBuf[j]-'0')*iPos; | ||
227 | iPos *= fLast.uRadix; | ||
228 | } | ||
229 | |||
230 | usedFormat(); | ||
231 | } | ||
232 | |||
233 | template<typename type> | ||
234 | void fparse( type &f, const Bu::String &sBuf ) | ||
235 | { | ||
236 | double fIn; | ||
237 | sscanf( sBuf.getStr(), "%lf", &fIn ); | ||
238 | f = fIn; | ||
239 | usedFormat(); | ||
240 | } | ||
241 | |||
242 | enum Special | ||
243 | { | ||
244 | nl, | ||
245 | flush | ||
246 | }; | ||
247 | |||
248 | void doFlush(); | ||
249 | |||
250 | private: | ||
251 | Stream &rStream; | ||
252 | Fmt fLast; | ||
253 | bool bTempFmt; | ||
254 | uint8_t uIndent; | ||
255 | char cIndent; | ||
256 | }; | ||
257 | |||
258 | Formatter &operator<<( Formatter &f, const Fmt &fmt ); | ||
259 | Formatter &operator<<( Formatter &f, Formatter::Special s ); | ||
260 | Formatter &operator<<( Formatter &f, const char *sStr ); | ||
261 | Formatter &operator<<( Formatter &f, char *sStr ); | ||
262 | Formatter &operator<<( Formatter &f, const Bu::String &sStr ); | ||
263 | Formatter &operator<<( Formatter &f, signed char c ); | ||
264 | Formatter &operator<<( Formatter &f, char c ); | ||
265 | Formatter &operator<<( Formatter &f, unsigned char c ); | ||
266 | Formatter &operator<<( Formatter &f, signed short i ); | ||
267 | Formatter &operator<<( Formatter &f, unsigned short i ); | ||
268 | Formatter &operator<<( Formatter &f, signed int i ); | ||
269 | Formatter &operator<<( Formatter &f, unsigned int i ); | ||
270 | Formatter &operator<<( Formatter &f, signed long i ); | ||
271 | Formatter &operator<<( Formatter &f, unsigned long i ); | ||
272 | Formatter &operator<<( Formatter &f, signed long long i ); | ||
273 | Formatter &operator<<( Formatter &f, unsigned long long i ); | ||
274 | Formatter &operator<<( Formatter &f, float flt ); | ||
275 | Formatter &operator<<( Formatter &f, double flt ); | ||
276 | Formatter &operator<<( Formatter &f, long double flt ); | ||
277 | Formatter &operator<<( Formatter &f, bool b ); | ||
278 | |||
279 | Formatter &operator>>( Formatter &f, Bu::String &sStr ); | ||
280 | Formatter &operator>>( Formatter &f, signed char &c ); | ||
281 | Formatter &operator>>( Formatter &f, char &c ); | ||
282 | Formatter &operator>>( Formatter &f, unsigned char &c ); | ||
283 | Formatter &operator>>( Formatter &f, signed short &i ); | ||
284 | Formatter &operator>>( Formatter &f, unsigned short &i ); | ||
285 | Formatter &operator>>( Formatter &f, signed int &i ); | ||
286 | Formatter &operator>>( Formatter &f, unsigned int &i ); | ||
287 | Formatter &operator>>( Formatter &f, signed long &i ); | ||
288 | Formatter &operator>>( Formatter &f, unsigned long &i ); | ||
289 | Formatter &operator>>( Formatter &f, signed long long &i ); | ||
290 | Formatter &operator>>( Formatter &f, unsigned long long &i ); | ||
291 | Formatter &operator>>( Formatter &f, float &flt ); | ||
292 | Formatter &operator>>( Formatter &f, double &flt ); | ||
293 | Formatter &operator>>( Formatter &f, long double &flt ); | ||
294 | Formatter &operator>>( Formatter &f, bool &b ); | ||
295 | |||
296 | template<typename type> | ||
297 | Formatter &operator<<( Formatter &f, const type *p ) | ||
298 | { | ||
299 | return f << "0x" << Fmt::hex(sizeof(ptrdiff_t)*2) << (ptrdiff_t)(p); | ||
300 | } | ||
301 | }; | ||
302 | |||
303 | #endif | ||