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