1/*
2 * Copyright (C) 2013 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 LE_FX_ENGINE_COMMON_CORE_BYTE_SWAPPER_H_
18#define LE_FX_ENGINE_COMMON_CORE_BYTE_SWAPPER_H_
19
20#include <stdio.h>
21#include <string.h>
22
23#include "common/core/basic_types.h"
24#include "common/core/os.h"
25
26namespace le_fx {
27
28namespace arch {
29
30inline bool IsLittleEndian(void) {
31  int16 word = 1;
32  char *cp = reinterpret_cast<char *>(&word);
33  return cp[0] != 0;
34}
35
36inline bool IsBigEndian(void) {
37  return !IsLittleEndian();
38}
39
40template <typename T, unsigned int kValSize>
41struct ByteSwapper {
42  static T Swap(const T &val) {
43    T new_val = val;
44    char *first = &new_val, *last = first + kValSize - 1, x;
45    for (; first < last; ++first, --last) {
46      x = *last;
47      *last = *first;
48      *first = x;
49    }
50    return new_val;
51  }
52};
53
54template <typename T>
55struct ByteSwapper<T, 1> {
56  static T Swap(const T &val) {
57    return val;
58  }
59};
60
61template <typename T>
62struct ByteSwapper<T, 2> {
63  static T Swap(const T &val) {
64    T new_val;
65    const char *o = (const char *)&val;
66    char *p = reinterpret_cast<char *>(&new_val);
67    p[0] = o[1];
68    p[1] = o[0];
69    return new_val;
70  }
71};
72
73template <typename T>
74struct ByteSwapper<T, 4> {
75  static T Swap(const T &val) {
76    T new_val;
77    const char *o = (const char *)&val;
78    char *p = reinterpret_cast<char *>(&new_val);
79    p[0] = o[3];
80    p[1] = o[2];
81    p[2] = o[1];
82    p[3] = o[0];
83    return new_val;
84  }
85};
86
87template <typename T>
88struct ByteSwapper<T, 8> {
89  static T Swap(const T &val) {
90    T new_val = val;
91    const char *o = (const char *)&val;
92    char *p = reinterpret_cast<char *>(&new_val);
93    p[0] = o[7];
94    p[1] = o[6];
95    p[2] = o[5];
96    p[3] = o[4];
97    p[4] = o[3];
98    p[5] = o[2];
99    p[6] = o[1];
100    p[7] = o[0];
101    return new_val;
102  }
103};
104
105template <typename T>
106T SwapBytes(const T &val, bool force_swap) {
107  if (force_swap) {
108#if !defined(LE_FX__NEED_BYTESWAP)
109    return ByteSwapper<T, sizeof(T)>::Swap(val);
110#else
111    return val;
112#endif  // !LE_FX_NEED_BYTESWAP
113  } else {
114#if !defined(LE_FX_NEED_BYTESWAP)
115    return val;
116#else
117    return ByteSwapper<T, sizeof(T)>::Swap(val);
118#endif  // !LE_FX_NEED_BYTESWAP
119  }
120}
121
122template <typename T>
123const T *SwapBytes(const T *vals, unsigned int num_items, bool force_swap) {
124  if (force_swap) {
125#if !defined(LE_FX_NEED_BYTESWAP)
126    T *writeable_vals = const_cast<T *>(vals);
127    for (unsigned int i = 0; i < num_items; i++) {
128      writeable_vals[i] = ByteSwapper<T, sizeof(T)>::Swap(vals[i]);
129    }
130    return writeable_vals;
131#else
132    return vals;
133#endif  // !LE_FX_NEED_BYTESWAP
134  } else {
135#if !defined(LE_FX_NEED_BYTESWAP)
136    return vals;
137#else
138    T *writeable_vals = const_cast<T *>(vals);
139    for (unsigned int i = 0; i < num_items; i++) {
140      writeable_vals[i] = ByteSwapper<T, sizeof(T)>::Swap(vals[i]);
141    }
142    return writeable_vals;
143#endif  // !LE_FX_NEED_BYTESWAP
144  }
145}
146
147}  // namespace arch
148
149}  // namespace le_fx
150
151#endif  // LE_FX_ENGINE_COMMON_CORE_BYTE_SWAPPER_H_
152