• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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