CACAO
endianess.hpp
Go to the documentation of this file.
1 /* src/toolbox/endianess.hpp - utilities for reading/writing to/from a
2  buffer in little or big endian
3 
4  Copyright (C) 1996-2013
5  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 
7  This file is part of CACAO.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2, or (at
12  your option) any later version.
13 
14  This program is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  02110-1301, USA.
23 
24 */
25 
26 #ifndef CACAO_ENDIANESS_
27 #define CACAO_ENDIANESS_ 1
28 
29 #include "mm/memory.hpp"
30 #include "toolbox/assert.hpp"
31 #include "vm/types.hpp"
32 
33 namespace cacao {
34  // ***** READ UNSIGNED, LITTLE ENDIAN **************************************
35 
36 #if defined(__I386__) || defined(__X86_64__)
37 
38  // we can optimize the LE access on little endian machines without alignment
39 
40  static inline uint8_t read_u1_le(const uint8_t *src) { return *src; }
41  static inline uint16_t read_u2_le(const uint8_t *src) { return *((uint16_t*) src); }
42  static inline uint32_t read_u4_le(const uint8_t *src) { return *((uint32_t*) src); }
43  static inline uint64_t read_u8_le(const uint8_t *src) { return *((uint64_t*) src); }
44 
45 #else // defined(__I386__) || defined(__X86_64__)
46 
47  static inline uint8_t read_u1_le(const uint8_t *src) {
48  return *src;
49  }
50 
51  static inline uint16_t read_u2_le(const uint8_t *src) {
52  return (((uint16_t) src[1]) << 8) +
53  ((uint16_t) src[0]);
54  }
55 
56  static inline uint32_t read_u4_le(const uint8_t *src) {
57  return (((uint32_t) src[3]) << 24) +
58  (((uint32_t) src[2]) << 16) +
59  (((uint32_t) src[1]) << 8) +
60  ((uint32_t) src[0]);
61  }
62 
63  static inline uint64_t read_u8_le(const uint8_t *src) {
64  return (((uint64_t) src[7]) << 56) +
65  (((uint64_t) src[6]) << 48) +
66  (((uint64_t) src[5]) << 40) +
67  (((uint64_t) src[4]) << 32) +
68  (((uint64_t) src[3]) << 24) +
69  (((uint64_t) src[2]) << 16) +
70  (((uint64_t) src[1]) << 8) +
71  ((uint64_t) src[0]);
72  }
73 
74 #endif // defined(__I386__) || defined(__X86_64__)
75 
76  // ***** READ SIGNED, LITTLE ENDIAN ****************************************
77 
78  /// read int8_t from pointer little endian
79  static inline int8_t read_s1_le(const uint8_t *src) { return (int8_t) read_u1_le(src); }
80 
81  /// read int16_t from pointer little endian
82  static inline int16_t read_s2_le(const uint8_t *src) { return (int16_t) read_u2_le(src); }
83 
84  /// read int32_t from pointer little endian
85  static inline int32_t read_s4_le(const uint8_t *src) { return (int32_t) read_u4_le(src); }
86 
87  /// read int64_t from pointer little endian
88  static inline int64_t read_s8_le(const uint8_t *src) { return (int64_t) read_u8_le(src); }
89 
90  // ***** READ UNSIGNED, BIG ENDIAN (for Java class files ) *****************
91 
92  /// read uint8_t from pointer big endian
93  static inline uint8_t read_u1_be(const uint8_t *src) {
94  return *src;
95  }
96 
97  /// read uint16_t from pointer big endian
98  static inline uint16_t read_u2_be(const uint8_t *src) {
99  return (((uint16_t) src[0]) << 8) +
100  ((uint16_t) src[1]);
101  }
102 
103  /// read uint32_t from pointer big endian
104  static inline uint32_t read_u4_be(const uint8_t *src) {
105  return (((uint32_t) src[0]) << 24) +
106  (((uint32_t) src[1]) << 16) +
107  (((uint32_t) src[2]) << 8) +
108  ((uint32_t) src[3]);
109  }
110 
111  /// read uint64_t from pointer big endian
112  static inline uint64_t read_u8_be(const uint8_t *src) {
113  return (((uint64_t) src[0]) << 56) +
114  (((uint64_t) src[1]) << 48) +
115  (((uint64_t) src[2]) << 40) +
116  (((uint64_t) src[3]) << 32) +
117  (((uint64_t) src[4]) << 24) +
118  (((uint64_t) src[5]) << 16) +
119  (((uint64_t) src[6]) << 8) +
120  ((uint64_t) src[7]);
121  }
122 
123  // ***** READ SIGNED, BIG ENDIAN ************************
124 
125  /// read int8_t from pointer big endian
126  static inline int8_t read_s1_be(const uint8_t *src) { return (int8_t) read_u1_be(src); }
127 
128  /// read int16_t from pointer big endian
129  static inline int16_t read_s2_be(const uint8_t *src) { return (int16_t) read_u2_be(src); }
130 
131  /// read int32_t from pointer big endian
132  static inline int32_t read_s4_be(const uint8_t *src) { return (int32_t) read_u4_be(src); }
133 
134  /// read int64_t from pointer big endian
135  static inline int64_t read_s8_be(const uint8_t *src) { return (int64_t) read_u8_be(src); }
136 
137  // ***** READ FLOATING POINT, BIG ENDIAN ****************
138 
139  static inline float read_float_be(const uint8_t *src) {
140  EXPENSIVE_ASSERT(sizeof(float) == 4);
141 
142  float f;
143 
144  #if WORDS_BIGENDIAN == 0
145  uint8_t buffer[4];
146 
147  for (int i = 0; i < 4; i++)
148  buffer[3 - i] = read_u1_be(src + i);
149 
150  MCOPY((uint8_t *) (&f), buffer, u1, 4);
151  #else
152  MCOPY((uint8_t *) (&f), src, u1, 4);
153  #endif
154 
155  return f;
156  }
157 
158  static inline double read_double_be(const uint8_t *src) {
159  EXPENSIVE_ASSERT(sizeof(double) == 8);
160 
161  double d;
162 
163  #if WORDS_BIGENDIAN == 0
164  uint8_t buffer[8];
165 
166  # if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
167  // On little endian ARM processors when using FPA, word order
168  // of doubles is still big endian. So take that into account
169  // here. When using VFP, word order of doubles follows byte
170  // order. (michi 2005/07/24)
171 
172  for (int i = 0; i < 4; i++)
173  buffer[3 - i] = read_u1_be(src + i);
174  for (int i = 0; i < 4; i++)
175  buffer[7 - i] = read_u1_be(src + i + 4);
176  # else
177  for (int i = 0; i < 8; i++)
178  buffer[7 - i] = read_u1_be(src + i);
179  # endif
180 
181  MCOPY((uint8_t *) (&d), buffer, u1, 8);
182  #else
183  MCOPY((uint8_t *) (&d), src, u1, 8);
184  #endif
185 
186  return d;
187  }
188 } // end namespace cacao
189 
190 #endif // CACAO_ENDIANESS_
191 
192 /*
193  * These are local overrides for various environment variables in Emacs.
194  * Please do not remove this and leave it at the end of the file, where
195  * Emacs will automagically detect them.
196  * ---------------------------------------------------------------------
197  * Local variables:
198  * mode: c++
199  * indent-tabs-mode: t
200  * c-basic-offset: 4
201  * tab-width: 4
202  * End:
203  * vim:noexpandtab:sw=4:ts=4:
204  */
static int64_t read_s8_be(const uint8_t *src)
read int64_t from pointer big endian
Definition: endianess.hpp:135
static uint64_t read_u8_le(const uint8_t *src)
Definition: endianess.hpp:63
static uint64_t read_u8_be(const uint8_t *src)
read uint64_t from pointer big endian
Definition: endianess.hpp:112
uint8_t u1
Definition: types.hpp:40
static int16_t read_s2_le(const uint8_t *src)
read int16_t from pointer little endian
Definition: endianess.hpp:82
static uint8_t read_u1_be(const uint8_t *src)
read uint8_t from pointer big endian
Definition: endianess.hpp:93
static int8_t read_s1_le(const uint8_t *src)
read int8_t from pointer little endian
Definition: endianess.hpp:79
static int16_t read_s2_be(const uint8_t *src)
read int16_t from pointer big endian
Definition: endianess.hpp:129
MIIterator i
static double read_double_be(const uint8_t *src)
Definition: endianess.hpp:158
static int64_t read_s8_le(const uint8_t *src)
read int64_t from pointer little endian
Definition: endianess.hpp:88
static uint16_t read_u2_be(const uint8_t *src)
read uint16_t from pointer big endian
Definition: endianess.hpp:98
static int32_t read_s4_le(const uint8_t *src)
read int32_t from pointer little endian
Definition: endianess.hpp:85
#define EXPENSIVE_ASSERT(EXPR)
An assertion that performs computations too expensive even for a normal debug build.
Definition: assert.hpp:90
static uint8_t read_u1_le(const uint8_t *src)
Definition: endianess.hpp:47
static float read_float_be(const uint8_t *src)
Definition: endianess.hpp:139
static uint16_t read_u2_le(const uint8_t *src)
Definition: endianess.hpp:51
Additional assertion macros.
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
static uint32_t read_u4_le(const uint8_t *src)
Definition: endianess.hpp:56
static int32_t read_s4_be(const uint8_t *src)
read int32_t from pointer big endian
Definition: endianess.hpp:132
static uint32_t read_u4_be(const uint8_t *src)
read uint32_t from pointer big endian
Definition: endianess.hpp:104
static int8_t read_s1_be(const uint8_t *src)
read int8_t from pointer big endian
Definition: endianess.hpp:126