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 */
get1(unsigned const char * pSrc)33 INLINE u1 get1(unsigned const char* pSrc)
34 {
35 return *pSrc;
36 }
37
38 /*
39 * Get 2 big-endian bytes.
40 */
get2BE(unsigned char const * pSrc)41 INLINE u2 get2BE(unsigned char const* pSrc)
42 {
43 return (pSrc[0] << 8) | pSrc[1];
44 }
45
46 /*
47 * Get 4 big-endian bytes.
48 */
get4BE(unsigned char const * pSrc)49 INLINE 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 */
get8BE(unsigned char const * pSrc)57 INLINE 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 */
get2LE(unsigned char const * pSrc)76 INLINE u2 get2LE(unsigned char const* pSrc)
77 {
78 return pSrc[0] | (pSrc[1] << 8);
79 }
80
81 /*
82 * Get 4 little-endian bytes.
83 */
get4LE(unsigned char const * pSrc)84 INLINE 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 */
get8LE(unsigned char const * pSrc)99 INLINE 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 */
read1(unsigned const char ** ppSrc)117 INLINE 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 */
read2BE(unsigned char const ** ppSrc)125 INLINE 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 */
read4BE(unsigned char const ** ppSrc)136 INLINE 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 */
read8BE(unsigned char const ** ppSrc)153 INLINE 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 */
read2LE(unsigned char const ** ppSrc)174 INLINE 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 */
read4LE(unsigned char const ** ppSrc)184 INLINE 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 */
read8LE(unsigned char const ** ppSrc)201 INLINE 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 */
skipUtf8String(unsigned char const ** ppSrc)222 INLINE 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 */
readUtf8String(unsigned char const ** ppSrc,char * buf,size_t bufLen)234 INLINE 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 */
readNewUtf8String(unsigned char const ** ppSrc,size_t * pLength)252 INLINE 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 */
set1(u1 * buf,u1 val)272 INLINE void set1(u1* buf, u1 val)
273 {
274 *buf = (u1)(val);
275 }
276
277 /*
278 * Set 2 big-endian bytes.
279 */
set2BE(u1 * buf,u2 val)280 INLINE 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 */
set4BE(u1 * buf,u4 val)289 INLINE 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 */
set8BE(u1 * buf,u8 val)300 INLINE 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 */
set2LE(u1 * buf,u2 val)315 INLINE 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 */
set4LE(u1 * buf,u4 val)324 INLINE 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 */
set8LE(u1 * buf,u8 val)335 INLINE 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 */
setUtf8String(u1 * buf,const u1 * str)350 INLINE 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