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 28namespace android { 29namespace img_utils { 30 31/** 32 * Endianness types supported. 33 */ 34enum 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 */ 43template<typename T> 44T convertToBigEndian(T in); 45 46/** 47 * Convert from the native device endianness to little endian. 48 */ 49template<typename T> 50T convertToLittleEndian(T in); 51 52/** 53 * A utility class for writing to an Output with the given endianness. 54 */ 55class 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 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 131template<typename T> 132inline 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 166template<> 167inline uint8_t convertToBigEndian(uint8_t in) { 168 return in; 169} 170 171template<> 172inline int8_t convertToBigEndian(int8_t in) { 173 return in; 174} 175 176template<> 177inline uint16_t convertToBigEndian(uint16_t in) { 178 return htobe16(in); 179} 180 181template<> 182inline int16_t convertToBigEndian(int16_t in) { 183 return htobe16(in); 184} 185 186template<> 187inline uint32_t convertToBigEndian(uint32_t in) { 188 return htobe32(in); 189} 190 191template<> 192inline int32_t convertToBigEndian(int32_t in) { 193 return htobe32(in); 194} 195 196template<> 197inline uint64_t convertToBigEndian(uint64_t in) { 198 return htobe64(in); 199} 200 201template<> 202inline int64_t convertToBigEndian(int64_t in) { 203 return htobe64(in); 204} 205 206template<> 207inline uint8_t convertToLittleEndian(uint8_t in) { 208 return in; 209} 210 211template<> 212inline int8_t convertToLittleEndian(int8_t in) { 213 return in; 214} 215 216template<> 217inline uint16_t convertToLittleEndian(uint16_t in) { 218 return htole16(in); 219} 220 221template<> 222inline int16_t convertToLittleEndian(int16_t in) { 223 return htole16(in); 224} 225 226template<> 227inline uint32_t convertToLittleEndian(uint32_t in) { 228 return htole32(in); 229} 230 231template<> 232inline int32_t convertToLittleEndian(int32_t in) { 233 return htole32(in); 234} 235 236template<> 237inline uint64_t convertToLittleEndian(uint64_t in) { 238 return htole64(in); 239} 240 241template<> 242inline 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