Home | History | Annotate | Download | only in minzip
      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  */
     17 INLINE unsigned char get1(unsigned const char* pSrc)
     18 {
     19     return *pSrc;
     20 }
     21 
     22 /*
     23  * Get 2 big-endian bytes.
     24  */
     25 INLINE 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  */
     38 INLINE 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  */
     53 INLINE 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  */
     72 INLINE 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  */
     85 INLINE 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  */
    100 INLINE 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  */
    119 INLINE 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  */
    127 INLINE 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  */
    140 INLINE 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  */
    155 INLINE 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  */
    174 INLINE 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  */
    187 INLINE 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  */
    202 INLINE 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  */
    221 INLINE 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  */
    233 INLINE 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  */
    251 INLINE 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  */
    271 INLINE void set1(unsigned char* buf, unsigned char val)
    272 {
    273     *buf = (unsigned char)(val);
    274 }
    275 
    276 /*
    277  * Set 2 big-endian bytes.
    278  */
    279 INLINE 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  */
    288 INLINE 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  */
    299 INLINE 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  */
    314 INLINE 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  */
    323 INLINE 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  */
    334 INLINE 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  */
    349 INLINE 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