Home | History | Annotate | Download | only in ustl-1.0
      1 // This file is part of the ustl library, an STL implementation.
      2 //
      3 // Copyright (C) 2005 by Mike Sharov <msharov (at) users.sourceforge.net>
      4 // This file is free software, distributed under the MIT License.
      5 //
      6 /// \file strmsize.h
      7 /// \brief This file contains stream_size_of functions for basic types and *STREAMABLE macros.
      8 /// stream_size_of functions return the size of the object's data that is written or
      9 /// read from a stream.
     10 //
     11 
     12 #ifndef STRMSIZE_H_052FF16B2D8A608761BF10333D065073
     13 #define STRMSIZE_H_052FF16B2D8A608761BF10333D065073
     14 
     15 #include "uassert.h"
     16 
     17 namespace ustl {
     18 
     19 /// Returns the size of the given object. Overloads for standard types are available.
     20 template <typename T>
     21 inline size_t stream_size_of (T*)	{ return (sizeof(T*));		}
     22 #ifndef DOXYGEN_SHOULD_IGNORE_THIS
     23 inline size_t stream_size_of (int8_t)	{ return (sizeof(int8_t));	}
     24 inline size_t stream_size_of (uint8_t)	{ return (sizeof(uint8_t));	}
     25 inline size_t stream_size_of (int16_t)	{ return (sizeof(int16_t));	}
     26 inline size_t stream_size_of (uint16_t)	{ return (sizeof(uint16_t));	}
     27 inline size_t stream_size_of (int32_t)	{ return (sizeof(int32_t));	}
     28 inline size_t stream_size_of (uint32_t)	{ return (sizeof(uint32_t));	}
     29 inline size_t stream_size_of (float)	{ return (sizeof(float));	}
     30 inline size_t stream_size_of (double)	{ return (sizeof(double));	}
     31 inline size_t stream_size_of (bool)	{ return (sizeof(uint8_t));	}
     32 inline size_t stream_size_of (wchar_t)	{ return (sizeof(wchar_t));	}
     33 #if HAVE_THREE_CHAR_TYPES
     34 inline size_t stream_size_of (char)	{ return (sizeof(char));	}
     35 #endif
     36 #if HAVE_INT64_T
     37 inline size_t stream_size_of (int64_t)	{ return (sizeof(int64_t));	}
     38 inline size_t stream_size_of (uint64_t)	{ return (sizeof(uint64_t));	}
     39 #endif
     40 #if SIZE_OF_LONG == SIZE_OF_INT
     41 inline size_t stream_size_of (long v)			{ return (sizeof (v));	}
     42 inline size_t stream_size_of (unsigned long v)		{ return (sizeof (v));	}
     43 #endif
     44 #if HAVE_LONG_LONG && (!HAVE_INT64_T || SIZE_OF_LONG_LONG > 8)
     45 inline size_t stream_size_of (long long v)		{ return (sizeof (v));	}
     46 inline size_t stream_size_of (unsigned long long v)	{ return (sizeof (v));	}
     47 #endif
     48 #endif // DOXYGEN_SHOULD_IGNORE_THIS
     49 
     50 } // namespace ustl
     51 
     52 /// Declares that T is not written to istream/ostream.
     53 #define NOT_STREAMABLE(T)	\
     54     namespace ustl {		\
     55 	inline istream& operator>> (istream& is, T&)		{ return (is); }	\
     56 	inline ostream& operator<< (ostream& os, const T&)	{ return (os); }	\
     57 	inline size_t stream_size_of (const T&)			{ return (0); }		\
     58     }
     59 
     60 //
     61 // Extra overloads in this macro are needed because it is the one used for
     62 // marshalling pointers. Passing a pointer to stream_size_of creates a
     63 // conversion ambiguity between converting to const pointer& and converting
     64 // to bool; the compiler always chooses the bool conversion (because it
     65 // requires 1 conversion instead of 2 for the other choice). There is little
     66 // point in adding the overloads to other macros, since they are never used
     67 // for pointers.
     68 //
     69 /// Declares that T is to be written as is into binary streams.
     70 #define INTEGRAL_STREAMABLE(T)	\
     71     namespace ustl {		\
     72 	inline istream& operator>> (istream& is, T& v)		{ is.iread(v);  return (is); }	\
     73 	inline ostream& operator<< (ostream& os, const T& v)	{ os.iwrite(v); return (os); }	\
     74 	inline ostream& operator<< (ostream& os, T& v)		{ os.iwrite(v); return (os); }	\
     75 	inline size_t stream_size_of (const T& v)		{ return (sizeof(v)); }		\
     76 	inline size_t stream_size_of (T& v)			{ return (sizeof(v)); }		\
     77     }
     78 
     79 #ifdef NDEBUG
     80     #define STD_STREAMABLE_SZCHK_BEGIN
     81     #define STD_STREAMABLE_SZCHK_END
     82 #else
     83     #define STD_STREAMABLE_SZCHK_BEGIN		\
     84 	assert (os.aligned (alignof (v)));	\
     85 	const uoff_t vStart (os.pos())
     86     #define STD_STREAMABLE_SZCHK_END		\
     87 	if (os.pos() - vStart != v.stream_size()) \
     88 	    throw stream_bounds_exception ("write", typeid(v).name(), vStart, os.pos() - vStart, v.stream_size())
     89 #endif
     90 
     91 /// Declares that T contains read, write, and stream_size methods.
     92 #define STD_STREAMABLE(T)	\
     93     namespace ustl {		\
     94 	inline istream& operator>> (istream& is, T& v)		{ assert (is.aligned (alignof (v))); v.read (is);  return (is); }	\
     95 	inline ostream& operator<< (ostream& os, const T& v)	{ STD_STREAMABLE_SZCHK_BEGIN; v.write (os); STD_STREAMABLE_SZCHK_END; return (os); }	\
     96 	inline size_t stream_size_of (const T& v)		{ return (v.stream_size()); }	\
     97     }
     98 
     99 /// Declares that T is to be cast into TSUB for streaming.
    100 #define CAST_STREAMABLE(T,TSUB)	\
    101     namespace ustl {		\
    102 	inline istream& operator>> (istream& is, T& v)		{ TSUB sv; is >> sv; v = (T)(sv); return (is); }	\
    103 	inline ostream& operator<< (ostream& os, const T& v)	{ os << TSUB(v); return (os); }			\
    104 	inline size_t stream_size_of (const T& v)		{ return (sizeof(TSUB(v))); }				\
    105     }
    106 
    107 /// Placed into a class it declares the methods required by STD_STREAMABLE. Syntactic sugar.
    108 #define DECLARE_STD_STREAMABLE			\
    109     public:					\
    110 	void	read (istream& is);		\
    111 	void	write (ostream& os) const;	\
    112 	size_t	stream_size (void) const
    113 
    114 /// Declares \p T to be writable to text streams. Reading is not implemented because you should not do it.
    115 #define TEXT_STREAMABLE(T)	\
    116     namespace ustl {		\
    117 	inline ostringstream& operator<< (ostringstream& os, const T& v)	\
    118 	    { v.text_write (os); return (os); }	\
    119     }
    120 
    121 /// Specifies that \p T is printed by using it as an index into \p Names string array.
    122 #define LOOKUP_TEXT_STREAMABLE(T,Names,nNames)	\
    123     namespace ustl {		\
    124 	inline ostringstream& operator<< (ostringstream& os, const T& v)	\
    125 	{				\
    126 	    if (uoff_t(v) < (nNames))	\
    127 		os << Names[v];		\
    128 	    else			\
    129 		os << uoff_t(v);	\
    130 	    return (os);		\
    131 	}				\
    132     }
    133 
    134 #endif
    135 
    136