• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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