Home | History | Annotate | Download | only in utils
      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 {
     31   inline bool is_host_little_endian() {
     32     unsigned long one = 0x1UL;
     33     return *reinterpret_cast<unsigned char *>(&one);
     34   }
     35 
     36   inline void swap_byte_order(unsigned char (&array)[1]) {
     37     // Nothing to do
     38   }
     39 
     40   inline void swap_byte_order(unsigned char (&array)[2]) {
     41     std::swap(array[0], array[1]);
     42   }
     43 
     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 
     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)
     70   : buf_begin(buf), buf_end(buf + size),
     71     cursor(buf), cursor_base(NULL), good(buf != NULL) {
     72   }
     73 
     74   void prologue(size_t size) {
     75     rsl_assert(cursor_base == NULL);
     76     cursor_base = cursor;
     77   }
     78 
     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 
     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>
    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