| /* |
| * Copyright 2006 The Android Open Source Project |
| * |
| * Some handy functions for manipulating bits and bytes. |
| */ |
| #ifndef _MINZIP_BITS |
| #define _MINZIP_BITS |
| |
| #include "inline_magic.h" |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| /* |
| * Get 1 byte. (Included to make the code more legible.) |
| */ |
| INLINE unsigned char get1(unsigned const char* pSrc) |
| { |
| return *pSrc; |
| } |
| |
| /* |
| * Get 2 big-endian bytes. |
| */ |
| INLINE unsigned short get2BE(unsigned char const* pSrc) |
| { |
| unsigned short result; |
| |
| result = *pSrc++ << 8; |
| result |= *pSrc++; |
| |
| return result; |
| } |
| |
| /* |
| * Get 4 big-endian bytes. |
| */ |
| INLINE unsigned int get4BE(unsigned char const* pSrc) |
| { |
| unsigned int result; |
| |
| result = *pSrc++ << 24; |
| result |= *pSrc++ << 16; |
| result |= *pSrc++ << 8; |
| result |= *pSrc++; |
| |
| return result; |
| } |
| |
| /* |
| * Get 8 big-endian bytes. |
| */ |
| INLINE unsigned long long get8BE(unsigned char const* pSrc) |
| { |
| unsigned long long result; |
| |
| result = (unsigned long long) *pSrc++ << 56; |
| result |= (unsigned long long) *pSrc++ << 48; |
| result |= (unsigned long long) *pSrc++ << 40; |
| result |= (unsigned long long) *pSrc++ << 32; |
| result |= (unsigned long long) *pSrc++ << 24; |
| result |= (unsigned long long) *pSrc++ << 16; |
| result |= (unsigned long long) *pSrc++ << 8; |
| result |= (unsigned long long) *pSrc++; |
| |
| return result; |
| } |
| |
| /* |
| * Get 2 little-endian bytes. |
| */ |
| INLINE unsigned short get2LE(unsigned char const* pSrc) |
| { |
| unsigned short result; |
| |
| result = *pSrc++; |
| result |= *pSrc++ << 8; |
| |
| return result; |
| } |
| |
| /* |
| * Get 4 little-endian bytes. |
| */ |
| INLINE unsigned int get4LE(unsigned char const* pSrc) |
| { |
| unsigned int result; |
| |
| result = *pSrc++; |
| result |= *pSrc++ << 8; |
| result |= *pSrc++ << 16; |
| result |= *pSrc++ << 24; |
| |
| return result; |
| } |
| |
| /* |
| * Get 8 little-endian bytes. |
| */ |
| INLINE unsigned long long get8LE(unsigned char const* pSrc) |
| { |
| unsigned long long result; |
| |
| result = (unsigned long long) *pSrc++; |
| result |= (unsigned long long) *pSrc++ << 8; |
| result |= (unsigned long long) *pSrc++ << 16; |
| result |= (unsigned long long) *pSrc++ << 24; |
| result |= (unsigned long long) *pSrc++ << 32; |
| result |= (unsigned long long) *pSrc++ << 40; |
| result |= (unsigned long long) *pSrc++ << 48; |
| result |= (unsigned long long) *pSrc++ << 56; |
| |
| return result; |
| } |
| |
| /* |
| * Grab 1 byte and advance the data pointer. |
| */ |
| INLINE unsigned char read1(unsigned const char** ppSrc) |
| { |
| return *(*ppSrc)++; |
| } |
| |
| /* |
| * Grab 2 big-endian bytes and advance the data pointer. |
| */ |
| INLINE unsigned short read2BE(unsigned char const** ppSrc) |
| { |
| unsigned short result; |
| |
| result = *(*ppSrc)++ << 8; |
| result |= *(*ppSrc)++; |
| |
| return result; |
| } |
| |
| /* |
| * Grab 4 big-endian bytes and advance the data pointer. |
| */ |
| INLINE unsigned int read4BE(unsigned char const** ppSrc) |
| { |
| unsigned int result; |
| |
| result = *(*ppSrc)++ << 24; |
| result |= *(*ppSrc)++ << 16; |
| result |= *(*ppSrc)++ << 8; |
| result |= *(*ppSrc)++; |
| |
| return result; |
| } |
| |
| /* |
| * Get 8 big-endian bytes. |
| */ |
| INLINE unsigned long long read8BE(unsigned char const** ppSrc) |
| { |
| unsigned long long result; |
| |
| result = (unsigned long long) *(*ppSrc)++ << 56; |
| result |= (unsigned long long) *(*ppSrc)++ << 48; |
| result |= (unsigned long long) *(*ppSrc)++ << 40; |
| result |= (unsigned long long) *(*ppSrc)++ << 32; |
| result |= (unsigned long long) *(*ppSrc)++ << 24; |
| result |= (unsigned long long) *(*ppSrc)++ << 16; |
| result |= (unsigned long long) *(*ppSrc)++ << 8; |
| result |= (unsigned long long) *(*ppSrc)++; |
| |
| return result; |
| } |
| |
| /* |
| * Grab 2 little-endian bytes and advance the data pointer. |
| */ |
| INLINE unsigned short read2LE(unsigned char const** ppSrc) |
| { |
| unsigned short result; |
| |
| result = *(*ppSrc)++; |
| result |= *(*ppSrc)++ << 8; |
| |
| return result; |
| } |
| |
| /* |
| * Grab 4 little-endian bytes and advance the data pointer. |
| */ |
| INLINE unsigned int read4LE(unsigned char const** ppSrc) |
| { |
| unsigned int result; |
| |
| result = *(*ppSrc)++; |
| result |= *(*ppSrc)++ << 8; |
| result |= *(*ppSrc)++ << 16; |
| result |= *(*ppSrc)++ << 24; |
| |
| return result; |
| } |
| |
| /* |
| * Get 8 little-endian bytes. |
| */ |
| INLINE unsigned long long read8LE(unsigned char const** ppSrc) |
| { |
| unsigned long long result; |
| |
| result = (unsigned long long) *(*ppSrc)++; |
| result |= (unsigned long long) *(*ppSrc)++ << 8; |
| result |= (unsigned long long) *(*ppSrc)++ << 16; |
| result |= (unsigned long long) *(*ppSrc)++ << 24; |
| result |= (unsigned long long) *(*ppSrc)++ << 32; |
| result |= (unsigned long long) *(*ppSrc)++ << 40; |
| result |= (unsigned long long) *(*ppSrc)++ << 48; |
| result |= (unsigned long long) *(*ppSrc)++ << 56; |
| |
| return result; |
| } |
| |
| /* |
| * Skip over a UTF-8 string. |
| */ |
| INLINE void skipUtf8String(unsigned char const** ppSrc) |
| { |
| unsigned int length = read4BE(ppSrc); |
| |
| (*ppSrc) += length; |
| } |
| |
| /* |
| * Read a UTF-8 string into a fixed-size buffer, and null-terminate it. |
| * |
| * Returns the length of the original string. |
| */ |
| INLINE int readUtf8String(unsigned char const** ppSrc, char* buf, size_t bufLen) |
| { |
| unsigned int length = read4BE(ppSrc); |
| size_t copyLen = (length < bufLen) ? length : bufLen-1; |
| |
| memcpy(buf, *ppSrc, copyLen); |
| buf[copyLen] = '\0'; |
| |
| (*ppSrc) += length; |
| return length; |
| } |
| |
| /* |
| * Read a UTF-8 string into newly-allocated storage, and null-terminate it. |
| * |
| * Returns the string and its length. (The latter is probably unnecessary |
| * for the way we're using UTF8.) |
| */ |
| INLINE char* readNewUtf8String(unsigned char const** ppSrc, size_t* pLength) |
| { |
| unsigned int length = read4BE(ppSrc); |
| char* buf; |
| |
| buf = (char*) malloc(length+1); |
| |
| memcpy(buf, *ppSrc, length); |
| buf[length] = '\0'; |
| |
| (*ppSrc) += length; |
| |
| *pLength = length; |
| return buf; |
| } |
| |
| |
| /* |
| * Set 1 byte. (Included to make the code more legible.) |
| */ |
| INLINE void set1(unsigned char* buf, unsigned char val) |
| { |
| *buf = (unsigned char)(val); |
| } |
| |
| /* |
| * Set 2 big-endian bytes. |
| */ |
| INLINE void set2BE(unsigned char* buf, unsigned short val) |
| { |
| *buf++ = (unsigned char)(val >> 8); |
| *buf = (unsigned char)(val); |
| } |
| |
| /* |
| * Set 4 big-endian bytes. |
| */ |
| INLINE void set4BE(unsigned char* buf, unsigned int val) |
| { |
| *buf++ = (unsigned char)(val >> 24); |
| *buf++ = (unsigned char)(val >> 16); |
| *buf++ = (unsigned char)(val >> 8); |
| *buf = (unsigned char)(val); |
| } |
| |
| /* |
| * Set 8 big-endian bytes. |
| */ |
| INLINE void set8BE(unsigned char* buf, unsigned long long val) |
| { |
| *buf++ = (unsigned char)(val >> 56); |
| *buf++ = (unsigned char)(val >> 48); |
| *buf++ = (unsigned char)(val >> 40); |
| *buf++ = (unsigned char)(val >> 32); |
| *buf++ = (unsigned char)(val >> 24); |
| *buf++ = (unsigned char)(val >> 16); |
| *buf++ = (unsigned char)(val >> 8); |
| *buf = (unsigned char)(val); |
| } |
| |
| /* |
| * Set 2 little-endian bytes. |
| */ |
| INLINE void set2LE(unsigned char* buf, unsigned short val) |
| { |
| *buf++ = (unsigned char)(val); |
| *buf = (unsigned char)(val >> 8); |
| } |
| |
| /* |
| * Set 4 little-endian bytes. |
| */ |
| INLINE void set4LE(unsigned char* buf, unsigned int val) |
| { |
| *buf++ = (unsigned char)(val); |
| *buf++ = (unsigned char)(val >> 8); |
| *buf++ = (unsigned char)(val >> 16); |
| *buf = (unsigned char)(val >> 24); |
| } |
| |
| /* |
| * Set 8 little-endian bytes. |
| */ |
| INLINE void set8LE(unsigned char* buf, unsigned long long val) |
| { |
| *buf++ = (unsigned char)(val); |
| *buf++ = (unsigned char)(val >> 8); |
| *buf++ = (unsigned char)(val >> 16); |
| *buf++ = (unsigned char)(val >> 24); |
| *buf++ = (unsigned char)(val >> 32); |
| *buf++ = (unsigned char)(val >> 40); |
| *buf++ = (unsigned char)(val >> 48); |
| *buf = (unsigned char)(val >> 56); |
| } |
| |
| /* |
| * Stuff a UTF-8 string into the buffer. |
| */ |
| INLINE void setUtf8String(unsigned char* buf, const unsigned char* str) |
| { |
| unsigned int strLen = strlen((const char*)str); |
| |
| set4BE(buf, strLen); |
| memcpy(buf + sizeof(unsigned int), str, strLen); |
| } |
| |
| #endif /*_MINZIP_BITS*/ |