358 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			358 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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*/
 |