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 */ 33 INLINE u1 get1(unsigned const char* pSrc) 34 { 35 return *pSrc; 36 } 37 38 /* 39 * Get 2 big-endian bytes. 40 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 272 INLINE void set1(u1* buf, u1 val) 273 { 274 *buf = (u1)(val); 275 } 276 277 /* 278 * Set 2 big-endian bytes. 279 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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