/* | |

* 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*/ |