Bits.h revision 375fb116bcb817b37509ab579dbd55cdbb765cbf
1/*
2 * Copyright (C) 2008 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 * Some handy functions for manipulating bits and bytes.
18 *
19 * These get inlined, so prefer small size over maximum speed.
20 */
21#ifndef DALVIK_BITS_H_
22#define DALVIK_BITS_H_
23
24#include "Common.h"
25#include "Inlines.h"
26
27#include <stdlib.h>
28#include <string.h>
29
30/*
31 * Get 1 byte.  (Included to make the code more legible.)
32 */
33INLINE u1 get1(unsigned const char* pSrc)
34{
35    return *pSrc;
36}
37
38/*
39 * Get 2 big-endian bytes.
40 */
41INLINE u2 get2BE(unsigned char const* pSrc)
42{
43    return (pSrc[0] << 8) | pSrc[1];
44}
45
46/*
47 * Get 4 big-endian bytes.
48 */
49INLINE u4 get4BE(unsigned char const* pSrc)
50{
51    return (pSrc[0] << 24) | (pSrc[1] << 16) | (pSrc[2] << 8) | pSrc[3];
52}
53
54/*
55 * Get 8 big-endian bytes.
56 */
57INLINE u8 get8BE(unsigned char const* pSrc)
58{
59    u4 low, high;
60
61    high = pSrc[0];
62    high = (high << 8) | pSrc[1];
63    high = (high << 8) | pSrc[2];
64    high = (high << 8) | pSrc[3];
65    low = pSrc[4];
66    low = (low << 8) | pSrc[5];
67    low = (low << 8) | pSrc[6];
68    low = (low << 8) | pSrc[7];
69
70    return ((u8) high << 32) | (u8) low;
71}
72
73/*
74 * Get 2 little-endian bytes.
75 */
76INLINE u2 get2LE(unsigned char const* pSrc)
77{
78    return pSrc[0] | (pSrc[1] << 8);
79}
80
81/*
82 * Get 4 little-endian bytes.
83 */
84INLINE u4 get4LE(unsigned char const* pSrc)
85{
86    u4 result;
87
88    result = pSrc[0];
89    result |= pSrc[1] << 8;
90    result |= pSrc[2] << 16;
91    result |= pSrc[3] << 24;
92
93    return result;
94}
95
96/*
97 * Get 8 little-endian bytes.
98 */
99INLINE u8 get8LE(unsigned char const* pSrc)
100{
101    u4 low, high;
102
103    low = pSrc[0];
104    low |= pSrc[1] << 8;
105    low |= pSrc[2] << 16;
106    low |= pSrc[3] << 24;
107    high = pSrc[4];
108    high |= pSrc[5] << 8;
109    high |= pSrc[6] << 16;
110    high |= pSrc[7] << 24;
111    return ((u8) high << 32) | (u8) low;
112}
113
114/*
115 * Grab 1 byte and advance the data pointer.
116 */
117INLINE u1 read1(unsigned const char** ppSrc)
118{
119    return *(*ppSrc)++;
120}
121
122/*
123 * Grab 2 big-endian bytes and advance the data pointer.
124 */
125INLINE u2 read2BE(unsigned char const** ppSrc)
126{
127    const unsigned char* pSrc = *ppSrc;
128
129    *ppSrc = pSrc + 2;
130    return pSrc[0] << 8 | pSrc[1];
131}
132
133/*
134 * Grab 4 big-endian bytes and advance the data pointer.
135 */
136INLINE u4 read4BE(unsigned char const** ppSrc)
137{
138    const unsigned char* pSrc = *ppSrc;
139    u4 result;
140
141    result = pSrc[0] << 24;
142    result |= pSrc[1] << 16;
143    result |= pSrc[2] << 8;
144    result |= pSrc[3];
145
146    *ppSrc = pSrc + 4;
147    return result;
148}
149
150/*
151 * Get 8 big-endian bytes and advance the data pointer.
152 */
153INLINE u8 read8BE(unsigned char const** ppSrc)
154{
155    const unsigned char* pSrc = *ppSrc;
156    u4 low, high;
157
158    high = pSrc[0];
159    high = (high << 8) | pSrc[1];
160    high = (high << 8) | pSrc[2];
161    high = (high << 8) | pSrc[3];
162    low = pSrc[4];
163    low = (low << 8) | pSrc[5];
164    low = (low << 8) | pSrc[6];
165    low = (low << 8) | pSrc[7];
166
167    *ppSrc = pSrc + 8;
168    return ((u8) high << 32) | (u8) low;
169}
170
171/*
172 * Grab 2 little-endian bytes and advance the data pointer.
173 */
174INLINE u2 read2LE(unsigned char const** ppSrc)
175{
176    const unsigned char* pSrc = *ppSrc;
177    *ppSrc = pSrc + 2;
178    return pSrc[0] | pSrc[1] << 8;
179}
180
181/*
182 * Grab 4 little-endian bytes and advance the data pointer.
183 */
184INLINE u4 read4LE(unsigned char const** ppSrc)
185{
186    const unsigned char* pSrc = *ppSrc;
187    u4 result;
188
189    result = pSrc[0];
190    result |= pSrc[1] << 8;
191    result |= pSrc[2] << 16;
192    result |= pSrc[3] << 24;
193
194    *ppSrc = pSrc + 4;
195    return result;
196}
197
198/*
199 * Get 8 little-endian bytes and advance the data pointer.
200 */
201INLINE u8 read8LE(unsigned char const** ppSrc)
202{
203    const unsigned char* pSrc = *ppSrc;
204    u4 low, high;
205
206    low = pSrc[0];
207    low |= pSrc[1] << 8;
208    low |= pSrc[2] << 16;
209    low |= pSrc[3] << 24;
210    high = pSrc[4];
211    high |= pSrc[5] << 8;
212    high |= pSrc[6] << 16;
213    high |= pSrc[7] << 24;
214
215    *ppSrc = pSrc + 8;
216    return ((u8) high << 32) | (u8) low;
217}
218
219/*
220 * Skip over a UTF-8 string (preceded by a 4-byte length).
221 */
222INLINE void skipUtf8String(unsigned char const** ppSrc)
223{
224    u4 length = read4BE(ppSrc);
225
226    (*ppSrc) += length;
227}
228
229/*
230 * Read a UTF-8 string into a fixed-size buffer, and null-terminate it.
231 *
232 * Returns the length of the original string.
233 */
234INLINE int readUtf8String(unsigned char const** ppSrc, char* buf, size_t bufLen)
235{
236    u4 length = read4BE(ppSrc);
237    size_t copyLen = (length < bufLen) ? length : bufLen-1;
238
239    memcpy(buf, *ppSrc, copyLen);
240    buf[copyLen] = '\0';
241
242    (*ppSrc) += length;
243    return length;
244}
245
246/*
247 * Read a UTF-8 string into newly-allocated storage, and null-terminate it.
248 *
249 * Returns the string and its length.  (The latter is probably unnecessary
250 * for the way we're using UTF8.)
251 */
252INLINE char* readNewUtf8String(unsigned char const** ppSrc, size_t* pLength)
253{
254    u4 length = read4BE(ppSrc);
255    char* buf;
256
257    buf = (char*) malloc(length+1);
258
259    memcpy(buf, *ppSrc, length);
260    buf[length] = '\0';
261
262    (*ppSrc) += length;
263
264    *pLength = length;
265    return buf;
266}
267
268
269/*
270 * Set 1 byte.  (Included to make code more consistent/legible.)
271 */
272INLINE void set1(u1* buf, u1 val)
273{
274    *buf = (u1)(val);
275}
276
277/*
278 * Set 2 big-endian bytes.
279 */
280INLINE void set2BE(u1* buf, u2 val)
281{
282    *buf++ = (u1)(val >> 8);
283    *buf = (u1)(val);
284}
285
286/*
287 * Set 4 big-endian bytes.
288 */
289INLINE void set4BE(u1* buf, u4 val)
290{
291    *buf++ = (u1)(val >> 24);
292    *buf++ = (u1)(val >> 16);
293    *buf++ = (u1)(val >> 8);
294    *buf = (u1)(val);
295}
296
297/*
298 * Set 8 big-endian bytes.
299 */
300INLINE void set8BE(u1* buf, u8 val)
301{
302    *buf++ = (u1)(val >> 56);
303    *buf++ = (u1)(val >> 48);
304    *buf++ = (u1)(val >> 40);
305    *buf++ = (u1)(val >> 32);
306    *buf++ = (u1)(val >> 24);
307    *buf++ = (u1)(val >> 16);
308    *buf++ = (u1)(val >> 8);
309    *buf = (u1)(val);
310}
311
312/*
313 * Set 2 little-endian bytes.
314 */
315INLINE void set2LE(u1* buf, u2 val)
316{
317    *buf++ = (u1)(val);
318    *buf = (u1)(val >> 8);
319}
320
321/*
322 * Set 4 little-endian bytes.
323 */
324INLINE void set4LE(u1* buf, u4 val)
325{
326    *buf++ = (u1)(val);
327    *buf++ = (u1)(val >> 8);
328    *buf++ = (u1)(val >> 16);
329    *buf = (u1)(val >> 24);
330}
331
332/*
333 * Set 8 little-endian bytes.
334 */
335INLINE void set8LE(u1* buf, u8 val)
336{
337    *buf++ = (u1)(val);
338    *buf++ = (u1)(val >> 8);
339    *buf++ = (u1)(val >> 16);
340    *buf++ = (u1)(val >> 24);
341    *buf++ = (u1)(val >> 32);
342    *buf++ = (u1)(val >> 40);
343    *buf++ = (u1)(val >> 48);
344    *buf = (u1)(val >> 56);
345}
346
347/*
348 * Stuff a UTF-8 string into the buffer.
349 */
350INLINE void setUtf8String(u1* buf, const u1* str)
351{
352    u4 strLen = strlen((const char*)str);
353
354    set4BE(buf, strLen);
355    memcpy(buf + sizeof(u4), str, strLen);
356}
357
358#endif  // DALVIK_BITS_H_
359