• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
DecodeUnsignedLeb128(const uint8_t ** data)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.
DecodeUnsignedLeb128P1(const uint8_t ** data)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.
DecodeSignedLeb128(const uint8_t ** data)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.
UnsignedLeb128Size(uint32_t data)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