Home | History | Annotate | Download | only in img_utils
      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