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