summaryrefslogtreecommitdiff
path: root/cxxtest/ValueTraits.h
diff options
context:
space:
mode:
Diffstat (limited to 'cxxtest/ValueTraits.h')
-rw-r--r--cxxtest/ValueTraits.h377
1 files changed, 377 insertions, 0 deletions
diff --git a/cxxtest/ValueTraits.h b/cxxtest/ValueTraits.h
new file mode 100644
index 0000000..71145ad
--- /dev/null
+++ b/cxxtest/ValueTraits.h
@@ -0,0 +1,377 @@
+#ifndef __cxxtest__ValueTraits_h__
+#define __cxxtest__ValueTraits_h__
+
+//
+// ValueTraits are used by CxxTest to convert arbitrary
+// values used in TS_ASSERT_EQUALS() to a string representation.
+//
+// This header file contains value traits for builtin integral types.
+// To declare value traits for new types you should instantiate the class
+// ValueTraits<YourClass>.
+//
+
+#include <cxxtest/Flags.h>
+
+#ifdef _CXXTEST_OLD_TEMPLATE_SYNTAX
+# define CXXTEST_TEMPLATE_INSTANTIATION
+#else // !_CXXTEST_OLD_TEMPLATE_SYNTAX
+# define CXXTEST_TEMPLATE_INSTANTIATION template<>
+#endif // _CXXTEST_OLD_TEMPLATE_SYNTAX
+
+namespace CxxTest
+{
+ //
+ // This is how we use the value traits
+ //
+# define TS_AS_STRING(x) CxxTest::traits(x).asString()
+
+ //
+ // Char representation of a digit
+ //
+ char digitToChar( unsigned digit );
+
+ //
+ // Convert byte value to hex digits
+ // Returns pointer to internal buffer
+ //
+ const char *byteToHex( unsigned char byte );
+
+ //
+ // Convert byte values to string
+ // Returns one past the copied data
+ //
+ char *bytesToString( const unsigned char *bytes, unsigned numBytes, unsigned maxBytes, char *s );
+
+ //
+ // Copy a string.
+ // Returns one past the end of the destination string
+ // Remember -- we can't use the standard library!
+ //
+ char *copyString( char *dst, const char *src );
+
+ //
+ // Compare two strings.
+ // Remember -- we can't use the standard library!
+ //
+ bool stringsEqual( const char *s1, const char *s2 );
+
+ //
+ // Represent a character value as a string
+ // Returns one past the end of the string
+ // This will be the actual char if printable or '\xXXXX' otherwise
+ //
+ char *charToString( unsigned long c, char *s );
+
+ //
+ // Prevent problems with negative (signed char)s
+ //
+ char *charToString( char c, char *s );
+
+ //
+ // The default ValueTraits class dumps up to 8 bytes as hex values
+ //
+ template <class T>
+ class ValueTraits
+ {
+ enum { MAX_BYTES = 8 };
+ char _asString[sizeof("{ ") + sizeof("XX ") * MAX_BYTES + sizeof("... }")];
+
+ public:
+ ValueTraits( const T &t ) { bytesToString( (const unsigned char *)&t, sizeof(T), MAX_BYTES, _asString ); }
+ const char *asString( void ) const { return _asString; }
+ };
+
+ //
+ // traits( T t )
+ // Creates an object of type ValueTraits<T>
+ //
+ template <class T>
+ inline ValueTraits<T> traits( T t )
+ {
+ return ValueTraits<T>( t );
+ }
+
+ //
+ // You can duplicate the implementation of an existing ValueTraits
+ //
+# define CXXTEST_COPY_TRAITS(CXXTEST_NEW_CLASS, CXXTEST_OLD_CLASS) \
+ CXXTEST_TEMPLATE_INSTANTIATION \
+ class ValueTraits< CXXTEST_NEW_CLASS > \
+ { \
+ ValueTraits< CXXTEST_OLD_CLASS > _old; \
+ public: \
+ ValueTraits( CXXTEST_NEW_CLASS n ) : _old( (CXXTEST_OLD_CLASS)n ) {} \
+ const char *asString( void ) const { return _old.asString(); } \
+ }
+
+ //
+ // Certain compilers need separate declarations for T and const T
+ //
+# ifdef _CXXTEST_NO_COPY_CONST
+# define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS)
+# else // !_CXXTEST_NO_COPY_CONST
+# define CXXTEST_COPY_CONST_TRAITS(CXXTEST_CLASS) CXXTEST_COPY_TRAITS(CXXTEST_CLASS, const CXXTEST_CLASS)
+# endif // _CXXTEST_NO_COPY_CONST
+
+ //
+ // Avoid compiler warnings about unsigned types always >= 0
+ //
+ template<class N> inline bool negative( N n ) { return n < 0; }
+ template<class N> inline N abs( N n ) { return negative(n) ? -n : n; }
+
+# define CXXTEST_NON_NEGATIVE(Type) \
+ CXXTEST_TEMPLATE_INSTANTIATION \
+ inline bool negative<Type>( Type ) { return false; } \
+ CXXTEST_TEMPLATE_INSTANTIATION \
+ inline Type abs<Type>( Type value ) { return value; }
+
+ CXXTEST_NON_NEGATIVE( bool )
+ CXXTEST_NON_NEGATIVE( unsigned char )
+ CXXTEST_NON_NEGATIVE( unsigned short int )
+ CXXTEST_NON_NEGATIVE( unsigned int )
+ CXXTEST_NON_NEGATIVE( unsigned long int )
+# ifdef _CXXTEST_LONGLONG
+ CXXTEST_NON_NEGATIVE( unsigned _CXXTEST_LONGLONG )
+# endif // _CXXTEST_LONGLONG
+
+ //
+ // Represent (integral) number as a string
+ // Returns one past the end of the string
+ // Remember -- we can't use the standard library!
+ //
+ template<class N>
+ char *numberToString( N n, char *s,
+ N base = 10,
+ unsigned skipDigits = 0,
+ unsigned maxDigits = (unsigned)-1 )
+ {
+ if ( negative(n) ) {
+ *s++ = '-';
+ n = abs(n);
+ }
+
+ N digit = 1;
+ while ( digit <= (n / base) )
+ digit *= base;
+ N digitValue;
+ for ( ; digit >= 1 && skipDigits; n -= digit * digitValue, digit /= base, -- skipDigits )
+ digitValue = (unsigned)(n / digit);
+ for ( ; digit >= 1 && maxDigits; n -= digit * digitValue, digit /= base, -- maxDigits )
+ *s++ = digitToChar( (unsigned)(digitValue = (unsigned)(n / digit)) );
+
+ *s = '\0';
+ return s;
+ }
+
+ //
+ // All the specific ValueTraits follow.
+ // You can #define CXXTEST_USER_VALUE_TRAITS if you don't want them
+ //
+
+#ifndef CXXTEST_USER_VALUE_TRAITS
+ //
+ // ValueTraits: const char * const &
+ // This is used for printing strings, as in TS_FAIL( "Message" )
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const char * const &>
+ {
+ ValueTraits &operator=( const ValueTraits & );
+ const char *_asString;
+
+ public:
+ ValueTraits( const char * const &value ) : _asString( value ) {}
+ ValueTraits( const ValueTraits &other ) : _asString( other._asString ) {}
+ const char *asString( void ) const { return _asString; }
+ };
+
+ CXXTEST_COPY_TRAITS( const char *, const char * const & );
+ CXXTEST_COPY_TRAITS( char *, const char * const & );
+
+ //
+ // ValueTraits: bool
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const bool>
+ {
+ bool _value;
+
+ public:
+ ValueTraits( const bool value ) : _value( value ) {}
+ const char *asString( void ) const { return _value ? "true" : "false"; }
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( bool );
+
+# ifdef _CXXTEST_LONGLONG
+ //
+ // ValueTraits: signed long long
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const signed _CXXTEST_LONGLONG>
+ {
+ typedef _CXXTEST_LONGLONG T;
+ char _asString[2 + 3 * sizeof(T)];
+ public:
+ ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+ const char *asString( void ) const { return _asString; }
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( signed _CXXTEST_LONGLONG );
+
+ //
+ // ValueTraits: unsigned long long
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const unsigned _CXXTEST_LONGLONG>
+ {
+ typedef unsigned _CXXTEST_LONGLONG T;
+ char _asString[1 + 3 * sizeof(T)];
+ public:
+ ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+ const char *asString( void ) const { return _asString; }
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( unsigned _CXXTEST_LONGLONG );
+# endif // _CXXTEST_LONGLONG
+
+ //
+ // ValueTraits: signed long
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const signed long int>
+ {
+ typedef signed long int T;
+ char _asString[2 + 3 * sizeof(T)];
+ public:
+ ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+ const char *asString( void ) const { return _asString; }
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( signed long int );
+
+ //
+ // ValueTraits: unsigned long
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const unsigned long int>
+ {
+ typedef unsigned long int T;
+ char _asString[1 + 3 * sizeof(T)];
+ public:
+ ValueTraits( T t ) { numberToString<T>( t, _asString ); }
+ const char *asString( void ) const { return _asString; }
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( unsigned long int );
+
+ //
+ // All decimals are the same as the long version
+ //
+
+ CXXTEST_COPY_TRAITS( const signed int, const signed long int );
+ CXXTEST_COPY_TRAITS( const unsigned int, const unsigned long int );
+ CXXTEST_COPY_TRAITS( const signed short int, const signed long int );
+ CXXTEST_COPY_TRAITS( const unsigned short int, const unsigned long int );
+ CXXTEST_COPY_TRAITS( const unsigned char, const unsigned long int );
+
+ CXXTEST_COPY_CONST_TRAITS( signed int );
+ CXXTEST_COPY_CONST_TRAITS( unsigned int );
+ CXXTEST_COPY_CONST_TRAITS( signed short int );
+ CXXTEST_COPY_CONST_TRAITS( unsigned short int );
+ CXXTEST_COPY_CONST_TRAITS( unsigned char );
+
+ //
+ // ValueTraits: char
+ // Returns 'x' for printable chars, '\x??' for others
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const char>
+ {
+ char _asString[sizeof("'\\xXX'")];
+ public:
+ ValueTraits( char c ) { copyString( charToString( c, copyString( _asString, "'" ) ), "'" ); }
+ const char *asString( void ) const { return _asString; }
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( char );
+
+ //
+ // ValueTraits: signed char
+ // Same as char, some compilers need it
+ //
+ CXXTEST_COPY_TRAITS( const signed char, const char );
+ CXXTEST_COPY_CONST_TRAITS( signed char );
+
+ //
+ // ValueTraits: double
+ //
+ CXXTEST_TEMPLATE_INSTANTIATION
+ class ValueTraits<const double>
+ {
+ public:
+ ValueTraits( double t )
+ {
+ ( requiredDigitsOnLeft( t ) > MAX_DIGITS_ON_LEFT ) ?
+ hugeNumber( t ) :
+ normalNumber( t );
+ }
+
+ const char *asString( void ) const { return _asString; }
+
+ private:
+ enum { MAX_DIGITS_ON_LEFT = 24, DIGITS_ON_RIGHT = 4, BASE = 10 };
+ char _asString[1 + MAX_DIGITS_ON_LEFT + 1 + DIGITS_ON_RIGHT + 1];
+
+ static unsigned requiredDigitsOnLeft( double t );
+ char *doNegative( double &t );
+ void hugeNumber( double t );
+ void normalNumber( double t );
+ char *doubleToString( double t, char *s, unsigned skip = 0, unsigned max = (unsigned)-1 );
+ };
+
+ CXXTEST_COPY_CONST_TRAITS( double );
+
+ //
+ // ValueTraits: float
+ //
+ CXXTEST_COPY_TRAITS( const float, const double );
+ CXXTEST_COPY_CONST_TRAITS( float );
+#endif // !CXXTEST_USER_VALUE_TRAITS
+};
+
+#ifdef _CXXTEST_HAVE_STD
+# include <cxxtest/StdValueTraits.h>
+#endif // _CXXTEST_HAVE_STD
+
+//
+// CXXTEST_ENUM_TRAITS
+//
+#define CXXTEST_ENUM_TRAITS( TYPE, VALUES ) \
+ namespace CxxTest \
+ { \
+ CXXTEST_TEMPLATE_INSTANTIATION \
+ class ValueTraits<TYPE> \
+ { \
+ TYPE _value; \
+ char _fallback[sizeof("(" #TYPE ")") + 3 * sizeof(TYPE)]; \
+ public: \
+ ValueTraits( TYPE value ) { \
+ _value = value; \
+ numberToString<unsigned long int>( _value, copyString( _fallback, "(" #TYPE ")" ) ); \
+ } \
+ const char *asString( void ) const \
+ { \
+ switch ( _value ) \
+ { \
+ VALUES \
+ default: return _fallback; \
+ } \
+ } \
+ }; \
+ }
+
+#define CXXTEST_ENUM_MEMBER( MEMBER ) \
+ case MEMBER: return #MEMBER;
+
+#endif // __cxxtest__ValueTraits_h__