1 /* 2 * Copyright 2014 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 #ifndef IMG_UTILS_ENDIAN_UTILS 18 #define IMG_UTILS_ENDIAN_UTILS 19 20 #include <img_utils/Output.h> 21 22 #include <cutils/compiler.h> 23 #include <utils/Errors.h> 24 #include <stdint.h> 25 #include <endian.h> 26 #include <assert.h> 27 28 namespace android { 29 namespace img_utils { 30 31 /** 32 * Endianness types supported. 33 */ 34 enum ANDROID_API Endianness { 35 UNDEFINED_ENDIAN, // Default endianness will be used. 36 BIG, 37 LITTLE 38 }; 39 40 /** 41 * Convert from the native device endianness to big endian. 42 */ 43 template<typename T> 44 T convertToBigEndian(T in); 45 46 /** 47 * Convert from the native device endianness to little endian. 48 */ 49 template<typename T> 50 T convertToLittleEndian(T in); 51 52 /** 53 * A utility class for writing to an Output with the given endianness. 54 */ 55 class ANDROID_API EndianOutput : public Output { 56 public: 57 /** 58 * Wrap the given Output. Calling write methods will result in 59 * writes to this output. 60 */ 61 explicit EndianOutput(Output* out, Endianness end=LITTLE); 62 63 virtual ~EndianOutput(); 64 65 /** 66 * Call open on the wrapped output. 67 */ 68 virtual status_t open(); 69 70 /** 71 * Call close on the wrapped output. 72 */ 73 virtual status_t close(); 74 75 /** 76 * Set the endianness to use when writing. 77 */ 78 virtual void setEndianness(Endianness end); 79 80 /** 81 * Get the currently configured endianness. 82 */ 83 virtual Endianness getEndianness() const; 84 85 /** 86 * Get the current number of bytes written by this EndianOutput. 87 */ 88 virtual uint32_t getCurrentOffset() const; 89 90 91 // TODO: switch write methods to uint32_t instead of size_t, 92 // the max size of a TIFF files is bounded 93 94 /** 95 * The following methods will write elements from given input buffer to the output. 96 * Count elements in the buffer will be written with the endianness set for this 97 * EndianOutput. If the given offset is greater than zero, that many elements will 98 * be skipped in the buffer before writing. 99 * 100 * Returns OK on success, or a negative error code. 101 */ 102 virtual status_t write(const uint8_t* buf, size_t offset, size_t count); 103 104 virtual status_t write(const int8_t* buf, size_t offset, size_t count); 105 106 virtual status_t write(const uint16_t* buf, size_t offset, size_t count); 107 108 virtual status_t write(const int16_t* buf, size_t offset, size_t count); 109 110 virtual status_t write(const uint32_t* buf, size_t offset, size_t count); 111 112 virtual status_t write(const int32_t* buf, size_t offset, size_t count); 113 114 virtual status_t write(const uint64_t* buf, size_t offset, size_t count); 115 116 virtual status_t write(const int64_t* buf, size_t offset, size_t count); 117 118 virtual status_t write(const float* buf, size_t offset, size_t count); 119 120 virtual status_t write(const double* buf, size_t offset, size_t count); 121 122 protected: 123 template<typename T> 124 inline status_t writeHelper(const T* buf, size_t offset, size_t count); 125 126 uint32_t mOffset; 127 Output* mOutput; 128 Endianness mEndian; 129 }; 130 131 template<typename T> 132 inline status_t EndianOutput::writeHelper(const T* buf, size_t offset, size_t count) { 133 assert(offset <= count); 134 status_t res = OK; 135 size_t size = sizeof(T); 136 switch(mEndian) { 137 case BIG: { 138 for (size_t i = offset; i < count; ++i) { 139 T tmp = convertToBigEndian<T>(buf[offset + i]); 140 if ((res = mOutput->write(reinterpret_cast<uint8_t*>(&tmp), 0, size)) 141 != OK) { 142 return res; 143 } 144 mOffset += size; 145 } 146 break; 147 } 148 case LITTLE: { 149 for (size_t i = offset; i < count; ++i) { 150 T tmp = convertToLittleEndian<T>(buf[offset + i]); 151 if ((res = mOutput->write(reinterpret_cast<uint8_t*>(&tmp), 0, size)) 152 != OK) { 153 return res; 154 } 155 mOffset += size; 156 } 157 break; 158 } 159 default: { 160 return BAD_VALUE; 161 } 162 } 163 return res; 164 } 165 166 template<> 167 inline uint8_t convertToBigEndian(uint8_t in) { 168 return in; 169 } 170 171 template<> 172 inline int8_t convertToBigEndian(int8_t in) { 173 return in; 174 } 175 176 template<> 177 inline uint16_t convertToBigEndian(uint16_t in) { 178 return htobe16(in); 179 } 180 181 template<> 182 inline int16_t convertToBigEndian(int16_t in) { 183 return htobe16(in); 184 } 185 186 template<> 187 inline uint32_t convertToBigEndian(uint32_t in) { 188 return htobe32(in); 189 } 190 191 template<> 192 inline int32_t convertToBigEndian(int32_t in) { 193 return htobe32(in); 194 } 195 196 template<> 197 inline uint64_t convertToBigEndian(uint64_t in) { 198 return htobe64(in); 199 } 200 201 template<> 202 inline int64_t convertToBigEndian(int64_t in) { 203 return htobe64(in); 204 } 205 206 template<> 207 inline uint8_t convertToLittleEndian(uint8_t in) { 208 return in; 209 } 210 211 template<> 212 inline int8_t convertToLittleEndian(int8_t in) { 213 return in; 214 } 215 216 template<> 217 inline uint16_t convertToLittleEndian(uint16_t in) { 218 return htole16(in); 219 } 220 221 template<> 222 inline int16_t convertToLittleEndian(int16_t in) { 223 return htole16(in); 224 } 225 226 template<> 227 inline uint32_t convertToLittleEndian(uint32_t in) { 228 return htole32(in); 229 } 230 231 template<> 232 inline int32_t convertToLittleEndian(int32_t in) { 233 return htole32(in); 234 } 235 236 template<> 237 inline uint64_t convertToLittleEndian(uint64_t in) { 238 return htole64(in); 239 } 240 241 template<> 242 inline int64_t convertToLittleEndian(int64_t in) { 243 return htole64(in); 244 } 245 246 } /*namespace img_utils*/ 247 } /*namespace android*/ 248 249 #endif /*IMG_UTILS_ENDIAN_UTILS*/ 250 251