1 /* 2 * Copyright 2011, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #if !defined(SERIALIZE_H) 18 #define SERIALIZE_H 19 20 #include "traits.h" 21 22 #include <algorithm> 23 #include <vector> 24 25 #include "utils/rsl_assert.h" 26 #include <string.h> 27 #include <stdint.h> 28 #include <stddef.h> 29 30 namespace detail { is_host_little_endian()31 inline bool is_host_little_endian() { 32 unsigned long one = 0x1UL; 33 return *reinterpret_cast<unsigned char *>(&one); 34 } 35 swap_byte_order(unsigned char (& array)[1])36 inline void swap_byte_order(unsigned char (&array)[1]) { 37 // Nothing to do 38 } 39 swap_byte_order(unsigned char (& array)[2])40 inline void swap_byte_order(unsigned char (&array)[2]) { 41 std::swap(array[0], array[1]); 42 } 43 swap_byte_order(unsigned char (& array)[4])44 inline void swap_byte_order(unsigned char (&array)[4]) { 45 std::swap(array[0], array[3]); 46 std::swap(array[1], array[2]); 47 } 48 swap_byte_order(unsigned char (& array)[8])49 inline void swap_byte_order(unsigned char (&array)[8]) { 50 std::swap(array[0], array[7]); 51 std::swap(array[1], array[6]); 52 std::swap(array[2], array[5]); 53 std::swap(array[3], array[4]); 54 } 55 } 56 57 58 template <bool isArchiveLittleEndian> 59 class ArchiveReader { 60 private: 61 unsigned char const *buf_begin; 62 unsigned char const *buf_end; 63 unsigned char const *cursor; 64 unsigned char const *cursor_base; 65 66 bool good; 67 68 public: 69 ArchiveReader(unsigned char const *buf = NULL, size_t size = 0) buf_begin(buf)70 : buf_begin(buf), buf_end(buf + size), 71 cursor(buf), cursor_base(NULL), good(buf != NULL) { 72 } 73 prologue(size_t size)74 void prologue(size_t size) { 75 rsl_assert(cursor_base == NULL); 76 cursor_base = cursor; 77 } 78 epilogue(size_t size)79 void epilogue(size_t size) { 80 rsl_assert(cursor_base != NULL); 81 rsl_assert(cursor_base + size >= cursor); 82 cursor = cursor_base + size; 83 cursor_base = NULL; 84 } 85 86 void seek(off_t off, bool from_begin = false) { 87 if (from_begin) { 88 cursor = buf_begin + off; 89 } else { 90 cursor += off; 91 } 92 } 93 readBytes(void * array,size_t size)94 void readBytes(void *array, size_t size) { 95 if (!good || cursor + size > buf_end) { 96 good = false; 97 } else { 98 memcpy(array, cursor, size); 99 } 100 } 101 102 template <size_t size> 103 void operator&(char (&array)[size]) { 104 readBytes(array, size); 105 seek(size); 106 } 107 108 template <size_t size> 109 void operator&(unsigned char (&array)[size]) { 110 readBytes(array, size); 111 seek(size); 112 } 113 114 template <typename T> 115 void operator&(T &v) { 116 seekAlignment<T>(); 117 readBytes(&v, TypeTraits<T>::size); 118 seek(TypeTraits<T>::size); 119 120 if (isArchiveLittleEndian != detail::is_host_little_endian()) { 121 detail::swap_byte_order( 122 reinterpret_cast<unsigned char (&)[TypeTraits<T>::size]>(v)); 123 } 124 } 125 126 operator void const *() const { 127 return good ? this : 0; 128 } 129 130 bool operator!() const { 131 return !good; 132 } 133 134 private: 135 template <typename T> seekAlignment()136 void seekAlignment() { 137 size_t align = TypeTraits<T>::align; 138 size_t delta = static_cast<size_t>(cursor - buf_begin) % align; 139 140 if (delta > 0) { 141 seek(align - delta); 142 } 143 } 144 145 }; 146 147 typedef ArchiveReader<true> ArchiveReaderLE; 148 typedef ArchiveReader<false> ArchiveReaderBE; 149 150 #endif // SERIALIZE_H 151