serialize.h revision 71e5a4a2fa18ff55b1e04e73b70b2938150a143c
1#if !defined(SERIALIZE_H) 2#define SERIALIZE_H 3 4#include "traits.h" 5 6#include <algorithm> 7#include <vector> 8 9#include <assert.h> 10#include <string.h> 11#include <stdint.h> 12#include <stddef.h> 13 14namespace detail { 15 inline bool is_host_little_endian() { 16 unsigned long one = 0x1UL; 17 return *reinterpret_cast<unsigned char *>(&one); 18 } 19 20 inline void swap_byte_order(unsigned char (&array)[1]) { 21 // Nothing to do 22 } 23 24 inline void swap_byte_order(unsigned char (&array)[2]) { 25 std::swap(array[0], array[1]); 26 } 27 28 inline void swap_byte_order(unsigned char (&array)[4]) { 29 std::swap(array[0], array[3]); 30 std::swap(array[1], array[2]); 31 } 32 33 inline void swap_byte_order(unsigned char (&array)[8]) { 34 std::swap(array[0], array[7]); 35 std::swap(array[1], array[6]); 36 std::swap(array[2], array[5]); 37 std::swap(array[3], array[4]); 38 } 39} 40 41 42template <bool isArchiveLittleEndian> 43class ArchiveReader { 44private: 45 unsigned char const *buf_begin; 46 unsigned char const *buf_end; 47 unsigned char const *cursor; 48 unsigned char const *cursor_base; 49 50 bool good; 51 52public: 53 ArchiveReader(unsigned char const *buf = NULL, size_t size = 0) 54 : buf_begin(buf), buf_end(buf + size), 55 cursor(buf), cursor_base(NULL), good(buf != NULL) { 56 } 57 58 void prologue(size_t size) { 59 assert(cursor_base == NULL); 60 cursor_base = cursor; 61 } 62 63 void epilogue(size_t size) { 64 assert(cursor_base != NULL); 65 assert(cursor_base + size >= cursor); 66 cursor = cursor_base + size; 67 cursor_base = NULL; 68 } 69 70 void seek(off_t off, bool from_begin = false) { 71 if (from_begin) { 72 cursor = buf_begin + off; 73 } else { 74 cursor += off; 75 } 76 } 77 78 void readBytes(void *array, size_t size) { 79 if (!good || cursor + size > buf_end) { 80 good = false; 81 } else { 82 memcpy(array, cursor, size); 83 } 84 } 85 86 template <size_t size> 87 void operator&(char (&array)[size]) { 88 readBytes(array, size); 89 seek(size); 90 } 91 92 template <size_t size> 93 void operator&(unsigned char (&array)[size]) { 94 readBytes(array, size); 95 seek(size); 96 } 97 98 template <typename T> 99 void operator&(T &v) { 100 seekAlignment<T>(); 101 readBytes(&v, TypeTraits<T>::size); 102 seek(TypeTraits<T>::size); 103 104 if (isArchiveLittleEndian != detail::is_host_little_endian()) { 105 detail::swap_byte_order( 106 reinterpret_cast<unsigned char (&)[TypeTraits<T>::size]>(v)); 107 } 108 } 109 110 operator void const *() const { 111 return good ? this : 0; 112 } 113 114 bool operator!() const { 115 return !good; 116 } 117 118private: 119 template <typename T> 120 void seekAlignment() { 121 size_t align = TypeTraits<T>::align; 122 size_t delta = static_cast<size_t>(cursor - buf_begin) % align; 123 124 if (delta > 0) { 125 seek(align - delta); 126 } 127 } 128 129}; 130 131typedef ArchiveReader<true> ArchiveReaderLE; 132typedef ArchiveReader<false> ArchiveReaderBE; 133 134#endif // SERIALIZE_H 135