1 | #ifndef __cxxtest__ValueTraits_h__ |
---|
2 | #define __cxxtest__ValueTraits_h__ |
---|
3 | |
---|
4 | // |
---|
5 | // ValueTraits are used by CxxTest to convert arbitrary |
---|
6 | // values used in TS_ASSERT_EQUALS() to a string representation. |
---|
7 | // |
---|
8 | // This header file contains value traits for builtin integral types. |
---|
9 | // To declare value traits for new types you should instantiate the class |
---|
10 | // ValueTraits<YourClass>. |
---|
11 | // |
---|
12 | |
---|
13 | #include <cxxtest/Flags.h> |
---|
14 | |
---|
15 | #ifdef _CXXTEST_OLD_TEMPLATE_SYNTAX |
---|
16 | # define CXXTEST_TEMPLATE_INSTANTIATION |
---|
17 | #else // !_CXXTEST_OLD_TEMPLATE_SYNTAX |
---|
18 | # define CXXTEST_TEMPLATE_INSTANTIATION template<> |
---|
19 | #endif // _CXXTEST_OLD_TEMPLATE_SYNTAX |
---|
20 | |
---|
21 | namespace CxxTest |
---|
22 | { |
---|
23 | // |
---|
24 | // This is how we use the value traits |
---|
25 | // |
---|
26 | # define TS_AS_STRING(x) CxxTest::traits(x).asString() |
---|
27 | |
---|
28 | // |
---|
29 | // Char representation of a digit |
---|
30 | // |
---|
31 | char digitToChar( unsigned digit ); |
---|
32 | |
---|
33 | // |
---|
34 | // Convert byte value to hex digits |
---|
35 | // Returns pointer to internal buffer |
---|
36 | // |
---|
37 | const char *byteToHex( unsigned char byte ); |
---|
38 | |
---|
39 | // |
---|
40 | // Convert byte values to string |
---|
41 | // Returns one past the copied data |
---|
42 | // |
---|
43 | char *bytesToString( const unsigned char *bytes, unsigned numBytes, unsigned maxBytes, char *s ); |
---|
44 | |
---|
45 | // |
---|
46 | // Copy a string. |
---|
47 | // Returns one past the end of the destination string |
---|
48 | // Remember -- we can't use the standard library! |
---|
49 | // |
---|
50 | char *copyString( char *dst, const char *src ); |
---|
51 | |
---|
52 | // |
---|
53 | // Compare two strings. |
---|
54 | // Remember -- we can't use the standard library! |
---|
55 | // |
---|
56 | bool stringsEqual( const char *s1, const char *s2 ); |
---|
57 | |
---|
58 | // |
---|
59 | // Represent a character value as a string |
---|
60 | // Returns one past the end of the string |
---|
61 | // This will be the actual char if printable or '\xXXXX' otherwise |
---|
62 | // |
---|
63 | char *charToString( unsigned long c, char *s ); |
---|
64 | |
---|
65 | // |
---|
66 | // Prevent problems with negative (signed char)s |
---|
67 | // |
---|
68 | char *charToString( char c, char *s ); |
---|
69 | |
---|
70 | // |
---|
71 | // The default ValueTraits class dumps up to 8 bytes as hex values |
---|
72 | // |
---|
73 | template <class T> |
---|
74 | class ValueTraits |
---|
75 | { |
---|
76 | enum { MAX_BYTES = 8 }; |
---|
77 | char _asString[sizeof("{ ") + sizeof("XX ") * MAX_BYTES + sizeof("... }")]; |
---|
78 | |
---|
79 | public: |
---|
80 | ValueTraits( const T &t ) { bytesToString( (const unsigned char *)&t, sizeof(T), MAX_BYTES, _asString ); } |
---|
81 | const char *asString( void ) const { return _asString; } |
---|
82 | }; |
---|
83 | |
---|
84 | // |
---|
85 | // traits( T t ) |
---|
86 | // Creates an object of type ValueTraits<T> |
---|
87 | // |
---|
88 | template <class T> |
---|
89 | inline ValueTraits<T> traits( T t ) |
---|
90 | { |
---|
91 | return ValueTraits<T>( t ); |
---|
92 | } |
---|
93 | |
---|
94 | // |
---|
95 | // You can duplicate the implementation of an existing ValueTraits |
---|
96 | // |
---|
97 | # define CXXTEST_COPY_TRAITS(CXXTEST_NEW_CLASS, CXXTEST_OLD_CLASS) \ |
---|
98 | CXXTEST_TEMPLATE_INSTANTIATION \ |
---|
99 | class ValueTraits< CXXTEST_NEW_CLASS > \ |
---|
100 | { \ |
---|
101 | ValueTraits< CXXTEST_OLD_CLASS > _old; \ |
---|
102 | public: \ |
---|
103 | ValueTraits( CXXTEST_NEW_CLASS n ) : _old( (CXXTEST_OLD_CLASS)n ) {} \ |
---|
104 | const char *asString( void ) const { return _old.asString(); } \ |
---|
105 | } |
---|
106 | |
---|
107 | // |
---|
108 | // Certain compilers need separate declarations for T and const T |
---|
109 | // |
---|
110 | # ifdef _CXXTEST_NO_COPY_CONST |
---|
111 | # define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS) |
---|
112 | # else // !_CXXTEST_NO_COPY_CONST |
---|
113 | # define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS) CXXTEST_COPY_TRAITS(CXXTEST_CLASS, const CXXTEST_CLASS) |
---|
114 | # endif // _CXXTEST_NO_COPY_CONST |
---|
115 | |
---|
116 | // |
---|
117 | // Avoid compiler warnings about unsigned types always >= 0 |
---|
118 | // |
---|
119 | template<class N> inline bool negative( N n ) { return n < 0; } |
---|
120 | template<class N> inline N abs( N n ) { return negative(n) ? -n : n; } |
---|
121 | |
---|
122 | # define CXXTEST_NON_NEGATIVE(Type) \ |
---|
123 | CXXTEST_TEMPLATE_INSTANTIATION \ |
---|
124 | inline bool negative<Type>( Type ) { return false; } \ |
---|
125 | CXXTEST_TEMPLATE_INSTANTIATION \ |
---|
126 | inline Type abs<Type>( Type value ) { return value; } |
---|
127 | |
---|
128 | CXXTEST_NON_NEGATIVE( bool ) |
---|
129 | CXXTEST_NON_NEGATIVE( unsigned char ) |
---|
130 | CXXTEST_NON_NEGATIVE( unsigned short int ) |
---|
131 | CXXTEST_NON_NEGATIVE( unsigned int ) |
---|
132 | CXXTEST_NON_NEGATIVE( unsigned long int ) |
---|
133 | # ifdef _CXXTEST_LONGLONG |
---|
134 | CXXTEST_NON_NEGATIVE( unsigned _CXXTEST_LONGLONG ) |
---|
135 | # endif // _CXXTEST_LONGLONG |
---|
136 | |
---|
137 | // |
---|
138 | // Represent (integral) number as a string |
---|
139 | // Returns one past the end of the string |
---|
140 | // Remember -- we can't use the standard library! |
---|
141 | // |
---|
142 | template<class N> |
---|
143 | char *numberToString( N n, char *s, |
---|
144 | N base = 10, |
---|
145 | unsigned skipDigits = 0, |
---|
146 | unsigned maxDigits = (unsigned)-1 ) |
---|
147 | { |
---|
148 | if ( negative(n) ) { |
---|
149 | *s++ = '-'; |
---|
150 | n = abs(n); |
---|
151 | } |
---|
152 | |
---|
153 | N digit = 1; |
---|
154 | while ( digit <= (n / base) ) |
---|
155 | digit *= base; |
---|
156 | N digitValue; |
---|
157 | for ( ; digit >= 1 && skipDigits; n -= digit * digitValue, digit /= base, -- skipDigits ) |
---|
158 | digitValue = (unsigned)(n / digit); |
---|
159 | for ( ; digit >= 1 && maxDigits; n -= digit * digitValue, digit /= base, -- maxDigits ) |
---|
160 | *s++ = digitToChar( (unsigned)(digitValue = (unsigned)(n / digit)) ); |
---|
161 | |
---|
162 | *s = '\0'; |
---|
163 | return s; |
---|
164 | } |
---|
165 | |
---|
166 | // |
---|
167 | // All the specific ValueTraits follow. |
---|
168 | // You can #define CXXTEST_USER_VALUE_TRAITS if you don't want them |
---|
169 | // |
---|
170 | |
---|
171 | #ifndef CXXTEST_USER_VALUE_TRAITS |
---|
172 | // |
---|
173 | // ValueTraits: const char * const & |
---|
174 | // This is used for printing strings, as in TS_FAIL( "Message" ) |
---|
175 | // |
---|
176 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
177 | class ValueTraits<const char * const &> |
---|
178 | { |
---|
179 | ValueTraits &operator=( const ValueTraits & ); |
---|
180 | const char *_asString; |
---|
181 | |
---|
182 | public: |
---|
183 | ValueTraits( const char * const &value ) : _asString( value ) {} |
---|
184 | ValueTraits( const ValueTraits &other ) : _asString( other._asString ) {} |
---|
185 | const char *asString( void ) const { return _asString; } |
---|
186 | }; |
---|
187 | |
---|
188 | CXXTEST_COPY_TRAITS( const char *, const char * const & ); |
---|
189 | CXXTEST_COPY_TRAITS( char *, const char * const & ); |
---|
190 | |
---|
191 | // |
---|
192 | // ValueTraits: bool |
---|
193 | // |
---|
194 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
195 | class ValueTraits<const bool> |
---|
196 | { |
---|
197 | bool _value; |
---|
198 | |
---|
199 | public: |
---|
200 | ValueTraits( const bool value ) : _value( value ) {} |
---|
201 | const char *asString( void ) const { return _value ? "true" : "false"; } |
---|
202 | }; |
---|
203 | |
---|
204 | CXXTEST_COPY_CONST_TRAITS( bool ); |
---|
205 | |
---|
206 | # ifdef _CXXTEST_LONGLONG |
---|
207 | // |
---|
208 | // ValueTraits: signed long long |
---|
209 | // |
---|
210 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
211 | class ValueTraits<const signed _CXXTEST_LONGLONG> |
---|
212 | { |
---|
213 | typedef _CXXTEST_LONGLONG T; |
---|
214 | char _asString[2 + 3 * sizeof(T)]; |
---|
215 | public: |
---|
216 | ValueTraits( T t ) { numberToString<T>( t, _asString ); } |
---|
217 | const char *asString( void ) const { return _asString; } |
---|
218 | }; |
---|
219 | |
---|
220 | CXXTEST_COPY_CONST_TRAITS( signed _CXXTEST_LONGLONG ); |
---|
221 | |
---|
222 | // |
---|
223 | // ValueTraits: unsigned long long |
---|
224 | // |
---|
225 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
226 | class ValueTraits<const unsigned _CXXTEST_LONGLONG> |
---|
227 | { |
---|
228 | typedef unsigned _CXXTEST_LONGLONG T; |
---|
229 | char _asString[1 + 3 * sizeof(T)]; |
---|
230 | public: |
---|
231 | ValueTraits( T t ) { numberToString<T>( t, _asString ); } |
---|
232 | const char *asString( void ) const { return _asString; } |
---|
233 | }; |
---|
234 | |
---|
235 | CXXTEST_COPY_CONST_TRAITS( unsigned _CXXTEST_LONGLONG ); |
---|
236 | # endif // _CXXTEST_LONGLONG |
---|
237 | |
---|
238 | // |
---|
239 | // ValueTraits: signed long |
---|
240 | // |
---|
241 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
242 | class ValueTraits<const signed long int> |
---|
243 | { |
---|
244 | typedef signed long int T; |
---|
245 | char _asString[2 + 3 * sizeof(T)]; |
---|
246 | public: |
---|
247 | ValueTraits( T t ) { numberToString<T>( t, _asString ); } |
---|
248 | const char *asString( void ) const { return _asString; } |
---|
249 | }; |
---|
250 | |
---|
251 | CXXTEST_COPY_CONST_TRAITS( signed long int ); |
---|
252 | |
---|
253 | // |
---|
254 | // ValueTraits: unsigned long |
---|
255 | // |
---|
256 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
257 | class ValueTraits<const unsigned long int> |
---|
258 | { |
---|
259 | typedef unsigned long int T; |
---|
260 | char _asString[1 + 3 * sizeof(T)]; |
---|
261 | public: |
---|
262 | ValueTraits( T t ) { numberToString<T>( t, _asString ); } |
---|
263 | const char *asString( void ) const { return _asString; } |
---|
264 | }; |
---|
265 | |
---|
266 | CXXTEST_COPY_CONST_TRAITS( unsigned long int ); |
---|
267 | |
---|
268 | // |
---|
269 | // All decimals are the same as the long version |
---|
270 | // |
---|
271 | |
---|
272 | CXXTEST_COPY_TRAITS( const signed int, const signed long int ); |
---|
273 | CXXTEST_COPY_TRAITS( const unsigned int, const unsigned long int ); |
---|
274 | CXXTEST_COPY_TRAITS( const signed short int, const signed long int ); |
---|
275 | CXXTEST_COPY_TRAITS( const unsigned short int, const unsigned long int ); |
---|
276 | CXXTEST_COPY_TRAITS( const unsigned char, const unsigned long int ); |
---|
277 | |
---|
278 | CXXTEST_COPY_CONST_TRAITS( signed int ); |
---|
279 | CXXTEST_COPY_CONST_TRAITS( unsigned int ); |
---|
280 | CXXTEST_COPY_CONST_TRAITS( signed short int ); |
---|
281 | CXXTEST_COPY_CONST_TRAITS( unsigned short int ); |
---|
282 | CXXTEST_COPY_CONST_TRAITS( unsigned char ); |
---|
283 | |
---|
284 | // |
---|
285 | // ValueTraits: char |
---|
286 | // Returns 'x' for printable chars, '\x??' for others |
---|
287 | // |
---|
288 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
289 | class ValueTraits<const char> |
---|
290 | { |
---|
291 | char _asString[sizeof("'\\xXX'")]; |
---|
292 | public: |
---|
293 | ValueTraits( char c ) { copyString( charToString( c, copyString( _asString, "'" ) ), "'" ); } |
---|
294 | const char *asString( void ) const { return _asString; } |
---|
295 | }; |
---|
296 | |
---|
297 | CXXTEST_COPY_CONST_TRAITS( char ); |
---|
298 | |
---|
299 | // |
---|
300 | // ValueTraits: signed char |
---|
301 | // Same as char, some compilers need it |
---|
302 | // |
---|
303 | CXXTEST_COPY_TRAITS( const signed char, const char ); |
---|
304 | CXXTEST_COPY_CONST_TRAITS( signed char ); |
---|
305 | |
---|
306 | // |
---|
307 | // ValueTraits: double |
---|
308 | // |
---|
309 | CXXTEST_TEMPLATE_INSTANTIATION |
---|
310 | class ValueTraits<const double> |
---|
311 | { |
---|
312 | public: |
---|
313 | ValueTraits( double t ) |
---|
314 | { |
---|
315 | ( requiredDigitsOnLeft( t ) > MAX_DIGITS_ON_LEFT ) ? |
---|
316 | hugeNumber( t ) : |
---|
317 | normalNumber( t ); |
---|
318 | } |
---|
319 | |
---|
320 | const char *asString( void ) const { return _asString; } |
---|
321 | |
---|
322 | private: |
---|
323 | enum { MAX_DIGITS_ON_LEFT = 24, DIGITS_ON_RIGHT = 4, BASE = 10 }; |
---|
324 | char _asString[1 + MAX_DIGITS_ON_LEFT + 1 + DIGITS_ON_RIGHT + 1]; |
---|
325 | |
---|
326 | static unsigned requiredDigitsOnLeft( double t ); |
---|
327 | char *doNegative( double &t ); |
---|
328 | void hugeNumber( double t ); |
---|
329 | void normalNumber( double t ); |
---|
330 | char *doubleToString( double t, char *s, unsigned skip = 0, unsigned max = (unsigned)-1 ); |
---|
331 | }; |
---|
332 | |
---|
333 | CXXTEST_COPY_CONST_TRAITS( double ); |
---|
334 | |
---|
335 | // |
---|
336 | // ValueTraits: float |
---|
337 | // |
---|
338 | CXXTEST_COPY_TRAITS( const float, const double ); |
---|
339 | CXXTEST_COPY_CONST_TRAITS( float ); |
---|
340 | #endif // !CXXTEST_USER_VALUE_TRAITS |
---|
341 | }; |
---|
342 | |
---|
343 | #ifdef _CXXTEST_HAVE_STD |
---|
344 | # include <cxxtest/StdValueTraits.h> |
---|
345 | #endif // _CXXTEST_HAVE_STD |
---|
346 | |
---|
347 | // |
---|
348 | // CXXTEST_ENUM_TRAITS |
---|
349 | // |
---|
350 | #define CXXTEST_ENUM_TRAITS( TYPE, VALUES ) \ |
---|
351 | namespace CxxTest \ |
---|
352 | { \ |
---|
353 | CXXTEST_TEMPLATE_INSTANTIATION \ |
---|
354 | class ValueTraits<TYPE> \ |
---|
355 | { \ |
---|
356 | TYPE _value; \ |
---|
357 | char _fallback[sizeof("(" #TYPE ")") + 3 * sizeof(TYPE)]; \ |
---|
358 | public: \ |
---|
359 | ValueTraits( TYPE value ) { \ |
---|
360 | _value = value; \ |
---|
361 | numberToString<unsigned long int>( _value, copyString( _fallback, "(" #TYPE ")" ) ); \ |
---|
362 | } \ |
---|
363 | const char *asString( void ) const \ |
---|
364 | { \ |
---|
365 | switch ( _value ) \ |
---|
366 | { \ |
---|
367 | VALUES \ |
---|
368 | default: return _fallback; \ |
---|
369 | } \ |
---|
370 | } \ |
---|
371 | }; \ |
---|
372 | } |
---|
373 | |
---|
374 | #define CXXTEST_ENUM_MEMBER( MEMBER ) \ |
---|
375 | case MEMBER: return #MEMBER; |
---|
376 | |
---|
377 | #endif // __cxxtest__ValueTraits_h__ |
---|