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