1 //===- LEB128.h -----------------------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef MCLD_SUPPORT_LEB128_H_
10 #define MCLD_SUPPORT_LEB128_H_
11 
12 #include <stdint.h>
13 #include <sys/types.h>
14 
15 namespace mcld {
16 
17 namespace leb128 {
18 
19 typedef unsigned char ByteType;
20 
21 /* Forward declarations */
22 template <typename IntType>
23 size_t encode(ByteType*& pBuf, IntType pValue);
24 
25 template <typename IntType>
26 IntType decode(const ByteType* pBuf, size_t& pSize);
27 
28 template <typename IntType>
29 IntType decode(const ByteType*& pBuf);
30 
31 /*
32  * Given an integer, this function returns the number of bytes required to
33  * encode it in ULEB128 format.
34  */
35 template <typename IntType>
size(IntType pValue)36 size_t size(IntType pValue) {
37   size_t size = 1;
38   while (pValue > 0x80) {
39     pValue >>= 7;
40     ++size;
41   }
42   return size;
43 }
44 
45 /*
46  * Write an unsigned integer in ULEB128 to the given buffer. The client should
47  * ensure there's enough space in the buffer to hold the result. Update the
48  * given buffer pointer to the point just past the end of the write value and
49  * return the number of bytes being written.
50  */
51 template <>
52 size_t encode<uint64_t>(ByteType*& pBuf, uint64_t pValue);
53 
54 template <>
55 size_t encode<uint32_t>(ByteType*& pBuf, uint32_t pValue);
56 
57 /*
58  * Encoding functions for signed LEB128.
59  */
60 template <>
61 size_t encode<int64_t>(ByteType*& pBuf, int64_t pValue);
62 
63 template <>
64 size_t encode<int32_t>(ByteType*& pBuf, int32_t pValue);
65 
66 /*
67  * Read an integer encoded in ULEB128 format from the given buffer. pSize will
68  * contain the number of bytes used in the buffer to encode the returned
69  * integer.
70  */
71 template <>
72 uint64_t decode<uint64_t>(const ByteType* pBuf, size_t& pSize);
73 
74 /*
75  * Read an integer encoded in ULEB128 format from the given buffer. Update the
76  * given buffer pointer to the point just past the end of the read value.
77  */
78 template <>
79 uint64_t decode<uint64_t>(const ByteType*& pBuf);
80 
81 /*
82  * Decoding functions for signed LEB128.
83  */
84 template <>
85 int64_t decode<int64_t>(const ByteType* pBuf, size_t& pSize);
86 
87 template <>
88 int64_t decode<int64_t>(const ByteType*& pBuf);
89 
90 /*
91  * The functions below handle the signed byte stream. This helps the user to get
92  * rid of annoying type conversions when using the LEB128 encoding/decoding APIs
93  * defined above.
94  */
95 template <typename IntType>
encode(char * & pBuf,IntType pValue)96 size_t encode(char*& pBuf, IntType pValue) {
97   return encode<IntType>(reinterpret_cast<ByteType*&>(pBuf), pValue);
98 }
99 
100 template <typename IntType>
decode(const char * pBuf,size_t & pSize)101 IntType decode(const char* pBuf, size_t& pSize) {
102   return decode<IntType>(reinterpret_cast<const ByteType*>(pBuf), pSize);
103 }
104 
105 template <typename IntType>
decode(const char * & pBuf)106 IntType decode(const char*& pBuf) {
107   return decode<IntType>(reinterpret_cast<const ByteType*&>(pBuf));
108 }
109 
110 }  // namespace leb128
111 }  // namespace mcld
112 
113 #endif  // MCLD_SUPPORT_LEB128_H_
114