Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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 #ifndef ART_RUNTIME_LEB128_H_
     18 #define ART_RUNTIME_LEB128_H_
     19 
     20 #include "globals.h"
     21 
     22 namespace art {
     23 
     24 // Reads an unsigned LEB128 value, updating the given pointer to point
     25 // just past the end of the read value. This function tolerates
     26 // non-zero high-order bits in the fifth encoded byte.
     27 static inline uint32_t DecodeUnsignedLeb128(const uint8_t** data) {
     28   const uint8_t* ptr = *data;
     29   int result = *(ptr++);
     30   if (result > 0x7f) {
     31     int cur = *(ptr++);
     32     result = (result & 0x7f) | ((cur & 0x7f) << 7);
     33     if (cur > 0x7f) {
     34       cur = *(ptr++);
     35       result |= (cur & 0x7f) << 14;
     36       if (cur > 0x7f) {
     37         cur = *(ptr++);
     38         result |= (cur & 0x7f) << 21;
     39         if (cur > 0x7f) {
     40           // Note: We don't check to see if cur is out of range here,
     41           // meaning we tolerate garbage in the four high-order bits.
     42           cur = *(ptr++);
     43           result |= cur << 28;
     44         }
     45       }
     46     }
     47   }
     48   *data = ptr;
     49   return static_cast<uint32_t>(result);
     50 }
     51 
     52 // Reads an unsigned LEB128 + 1 value. updating the given pointer to point
     53 // just past the end of the read value. This function tolerates
     54 // non-zero high-order bits in the fifth encoded byte.
     55 // It is possible for this function to return -1.
     56 static inline int32_t DecodeUnsignedLeb128P1(const uint8_t** data) {
     57   return DecodeUnsignedLeb128(data) - 1;
     58 }
     59 
     60 // Reads a signed LEB128 value, updating the given pointer to point
     61 // just past the end of the read value. This function tolerates
     62 // non-zero high-order bits in the fifth encoded byte.
     63 static inline int32_t DecodeSignedLeb128(const uint8_t** data) {
     64   const uint8_t* ptr = *data;
     65   int32_t result = *(ptr++);
     66   if (result <= 0x7f) {
     67     result = (result << 25) >> 25;
     68   } else {
     69     int cur = *(ptr++);
     70     result = (result & 0x7f) | ((cur & 0x7f) << 7);
     71     if (cur <= 0x7f) {
     72       result = (result << 18) >> 18;
     73     } else {
     74       cur = *(ptr++);
     75       result |= (cur & 0x7f) << 14;
     76       if (cur <= 0x7f) {
     77         result = (result << 11) >> 11;
     78       } else {
     79         cur = *(ptr++);
     80         result |= (cur & 0x7f) << 21;
     81         if (cur <= 0x7f) {
     82           result = (result << 4) >> 4;
     83         } else {
     84           // Note: We don't check to see if cur is out of range here,
     85           // meaning we tolerate garbage in the four high-order bits.
     86           cur = *(ptr++);
     87           result |= cur << 28;
     88         }
     89       }
     90     }
     91   }
     92   *data = ptr;
     93   return result;
     94 }
     95 
     96 // Returns the number of bytes needed to encode the value in unsigned LEB128.
     97 static inline uint32_t UnsignedLeb128Size(uint32_t data) {
     98   uint32_t count = 0;
     99   do {
    100     data >>= 7;
    101     count++;
    102   } while (data != 0);
    103   return count;
    104 }
    105 
    106 }  // namespace art
    107 
    108 #endif  // ART_RUNTIME_LEB128_H_
    109