103f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao/*
203f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * Copyright 2011, The Android Open Source Project
303f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao *
403f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License");
503f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * you may not use this file except in compliance with the License.
603f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * You may obtain a copy of the License at
703f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao *
803f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao *     http://www.apache.org/licenses/LICENSE-2.0
903f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao *
1003f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * Unless required by applicable law or agreed to in writing, software
1103f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS,
1203f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1303f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * See the License for the specific language governing permissions and
1403f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao * limitations under the License.
1503f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao */
1603f75e22ad9ea75dc536d199c3d11a98884be314Shih-wei Liao
17b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien#if !defined(SERIALIZE_H)
18b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien#define SERIALIZE_H
19b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
20c85473833f3b6f0dc951698e2481e3d3d98942eeLogan Chien#include "traits.h"
21c85473833f3b6f0dc951698e2481e3d3d98942eeLogan Chien
220f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien#include <algorithm>
230f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien#include <vector>
240f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
25c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa#include "utils/rsl_assert.h"
26b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien#include <string.h>
27b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien#include <stdint.h>
28203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien#include <stddef.h>
29b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
30b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chiennamespace detail {
31b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien  inline bool is_host_little_endian() {
32b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien    unsigned long one = 0x1UL;
33b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien    return *reinterpret_cast<unsigned char *>(&one);
34b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien  }
35b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
360f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  inline void swap_byte_order(unsigned char (&array)[1]) {
37b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien    // Nothing to do
38b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien  }
39b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
400f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  inline void swap_byte_order(unsigned char (&array)[2]) {
410f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[0], array[1]);
42b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien  }
43b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
440f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  inline void swap_byte_order(unsigned char (&array)[4]) {
450f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[0], array[3]);
460f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[1], array[2]);
47b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien  }
48b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
490f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  inline void swap_byte_order(unsigned char (&array)[8]) {
500f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[0], array[7]);
510f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[1], array[6]);
520f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[2], array[5]);
530f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    std::swap(array[3], array[4]);
54b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien  }
550f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien}
56b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
57b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
5800e067ef50c860668ed67003309d5ae71aa02b32Logan Chientemplate <bool isArchiveLittleEndian>
5900e067ef50c860668ed67003309d5ae71aa02b32Logan Chienclass ArchiveReader {
600f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chienprivate:
610f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  unsigned char const *buf_begin;
620f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  unsigned char const *buf_end;
630f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  unsigned char const *cursor;
64203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  unsigned char const *cursor_base;
65b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
660f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  bool good;
67b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
68b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chienpublic:
6900e067ef50c860668ed67003309d5ae71aa02b32Logan Chien  ArchiveReader(unsigned char const *buf = NULL, size_t size = 0)
70203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  : buf_begin(buf), buf_end(buf + size),
7100e067ef50c860668ed67003309d5ae71aa02b32Logan Chien    cursor(buf), cursor_base(NULL), good(buf != NULL) {
720f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
730f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
7418a839ad774a15637f481ea6da561cef8dd9c309Logan Chien  void prologue(size_t size) {
75c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa    rsl_assert(cursor_base == NULL);
76203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien    cursor_base = cursor;
770f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
780f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
7918a839ad774a15637f481ea6da561cef8dd9c309Logan Chien  void epilogue(size_t size) {
80c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa    rsl_assert(cursor_base != NULL);
81c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa    rsl_assert(cursor_base + size >= cursor);
8218a839ad774a15637f481ea6da561cef8dd9c309Logan Chien    cursor = cursor_base + size;
83203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien    cursor_base = NULL;
840f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
850f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
860f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  void seek(off_t off, bool from_begin = false) {
870f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    if (from_begin) {
880f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien      cursor = buf_begin + off;
890f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    } else {
900f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien      cursor += off;
910f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    }
920f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
930f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
9400e067ef50c860668ed67003309d5ae71aa02b32Logan Chien  void readBytes(void *array, size_t size) {
95e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien    if (!good || cursor + size > buf_end) {
96e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien      good = false;
97e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien    } else {
98e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien      memcpy(array, cursor, size);
99e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien    }
100e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien  }
101e04718485e859b865d14fad20df1f5ac602e9e58Logan Chien
102203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  template <size_t size>
103203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  void operator&(char (&array)[size]) {
10400e067ef50c860668ed67003309d5ae71aa02b32Logan Chien    readBytes(array, size);
105203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien    seek(size);
1060f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
1070f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
108203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  template <size_t size>
109203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  void operator&(unsigned char (&array)[size]) {
11000e067ef50c860668ed67003309d5ae71aa02b32Logan Chien    readBytes(array, size);
111203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien    seek(size);
112203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  }
1130f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
11471e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien  template <typename T>
11571e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien  void operator&(T &v) {
11671e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien    seekAlignment<T>();
11771e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien    readBytes(&v, TypeTraits<T>::size);
11871e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien    seek(TypeTraits<T>::size);
11971e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien
12071e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien    if (isArchiveLittleEndian != detail::is_host_little_endian()) {
12171e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien      detail::swap_byte_order(
12271e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien        reinterpret_cast<unsigned char (&)[TypeTraits<T>::size]>(v));
12371e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien    }
12471e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien  }
1250f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
126fd1e42426bcaca4bae92e579dd8ec0f8fe36ad0fLogan Chien  operator void const *() const {
1270f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    return good ? this : 0;
1280f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
1290f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
1300f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  bool operator!() const {
1310f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien    return !good;
1320f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien  }
133203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien
134203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chienprivate:
135203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  template <typename T>
13671e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien  void seekAlignment() {
13700e067ef50c860668ed67003309d5ae71aa02b32Logan Chien    size_t align = TypeTraits<T>::align;
138dd4ed54c02bb7abc16adcfcf78bf631aa26deb18Logan Chien    size_t delta = static_cast<size_t>(cursor - buf_begin) % align;
13900e067ef50c860668ed67003309d5ae71aa02b32Logan Chien
14000e067ef50c860668ed67003309d5ae71aa02b32Logan Chien    if (delta > 0) {
14100e067ef50c860668ed67003309d5ae71aa02b32Logan Chien      seek(align - delta);
142203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien    }
143203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien  }
144203bf2d31f9e4f55bcee1899e14bade235f1f1eeLogan Chien
145b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien};
146b10ad5844867c7a33bb0d994e3ba55c17e41d18dLogan Chien
14700e067ef50c860668ed67003309d5ae71aa02b32Logan Chientypedef ArchiveReader<true>  ArchiveReaderLE;
14800e067ef50c860668ed67003309d5ae71aa02b32Logan Chientypedef ArchiveReader<false> ArchiveReaderBE;
1490f6173b8f0bb91772f29f701a55933bdf40f2ee4Logan Chien
150de9cff6dadefcdce43728f2bc54dd65675657e02Logan Chien#endif // SERIALIZE_H
151