1b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines/*
2b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Copyright 2011, The Android Open Source Project
3b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *
4b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
5b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * you may not use this file except in compliance with the License.
6b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * You may obtain a copy of the License at
7b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *
8b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
9b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines *
10b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * Unless required by applicable law or agreed to in writing, software
11b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
12b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * See the License for the specific language governing permissions and
14b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines * limitations under the License.
15b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines */
16b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
17b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#if !defined(SERIALIZE_H)
18b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#define SERIALIZE_H
19b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
20b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "traits.h"
21b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
22b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <algorithm>
23b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <vector>
24b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
25b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include "utils/rsl_assert.h"
26b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <string.h>
27b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stdint.h>
28b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#include <stddef.h>
29b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
30b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesnamespace detail {
31b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  inline bool is_host_little_endian() {
32b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    unsigned long one = 0x1UL;
33b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return *reinterpret_cast<unsigned char *>(&one);
34b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
35b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
36b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  inline void swap_byte_order(unsigned char (&array)[1]) {
37b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    // Nothing to do
38b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
39b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
40b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  inline void swap_byte_order(unsigned char (&array)[2]) {
41b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[0], array[1]);
42b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
43b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
44b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  inline void swap_byte_order(unsigned char (&array)[4]) {
45b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[0], array[3]);
46b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[1], array[2]);
47b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
48b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
49b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  inline void swap_byte_order(unsigned char (&array)[8]) {
50b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[0], array[7]);
51b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[1], array[6]);
52b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[2], array[5]);
53b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    std::swap(array[3], array[4]);
54b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
55b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines}
56b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
57b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
58b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinestemplate <bool isArchiveLittleEndian>
59b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesclass ArchiveReader {
60b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesprivate:
61b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  unsigned char const *buf_begin;
62b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  unsigned char const *buf_end;
63b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  unsigned char const *cursor;
64b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  unsigned char const *cursor_base;
65b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
66b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  bool good;
67b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
68b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinespublic:
69b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  ArchiveReader(unsigned char const *buf = NULL, size_t size = 0)
70b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  : buf_begin(buf), buf_end(buf + size),
71b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    cursor(buf), cursor_base(NULL), good(buf != NULL) {
72b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
73b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
74b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void prologue(size_t size) {
75b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    rsl_assert(cursor_base == NULL);
76b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    cursor_base = cursor;
77b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
78b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
79b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void epilogue(size_t size) {
80b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    rsl_assert(cursor_base != NULL);
81b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    rsl_assert(cursor_base + size >= cursor);
82b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    cursor = cursor_base + size;
83b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    cursor_base = NULL;
84b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
85b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
86b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void seek(off_t off, bool from_begin = false) {
87b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    if (from_begin) {
88b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      cursor = buf_begin + off;
89b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    } else {
90b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      cursor += off;
91b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    }
92b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
93b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
94b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void readBytes(void *array, size_t size) {
95b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    if (!good || cursor + size > buf_end) {
96b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      good = false;
97b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    } else {
98b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      memcpy(array, cursor, size);
99b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    }
100b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
101b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
102b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  template <size_t size>
103b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void operator&(char (&array)[size]) {
104b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    readBytes(array, size);
105b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    seek(size);
106b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
107b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
108b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  template <size_t size>
109b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void operator&(unsigned char (&array)[size]) {
110b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    readBytes(array, size);
111b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    seek(size);
112b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
113b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
114b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  template <typename T>
115b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void operator&(T &v) {
116b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    seekAlignment<T>();
117b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    readBytes(&v, TypeTraits<T>::size);
118b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    seek(TypeTraits<T>::size);
119b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
120b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    if (isArchiveLittleEndian != detail::is_host_little_endian()) {
121b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      detail::swap_byte_order(
122b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines        reinterpret_cast<unsigned char (&)[TypeTraits<T>::size]>(v));
123b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    }
124b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
125b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
126b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  operator void const *() const {
127b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return good ? this : 0;
128b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
129b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
130b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  bool operator!() const {
131b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    return !good;
132b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
133b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
134b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinesprivate:
135b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  template <typename T>
136b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  void seekAlignment() {
137b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    size_t align = TypeTraits<T>::align;
138b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    size_t delta = static_cast<size_t>(cursor - buf_begin) % align;
139b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
140b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    if (delta > 0) {
141b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines      seek(align - delta);
142b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines    }
143b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines  }
144b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
145b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines};
146b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
147b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinestypedef ArchiveReader<true>  ArchiveReaderLE;
148b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hinestypedef ArchiveReader<false> ArchiveReaderBE;
149b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines
150b53c8a59e6f21ed36a0c3d9d4ce5834d4cc3c298Stephen Hines#endif // SERIALIZE_H
151