xref: /dflybsd-src/contrib/binutils-2.27/include/leb128.h (revision e656dc90e3d65d744d534af2f5ea88cf8101ebcf)
1*a9fa9459Szrj /* Utilities for reading leb128 values.
2*a9fa9459Szrj    Copyright (C) 2012-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj 
4*a9fa9459Szrj This file is part of the libiberty library.
5*a9fa9459Szrj Libiberty is free software; you can redistribute it and/or
6*a9fa9459Szrj modify it under the terms of the GNU Library General Public
7*a9fa9459Szrj License as published by the Free Software Foundation; either
8*a9fa9459Szrj version 2 of the License, or (at your option) any later version.
9*a9fa9459Szrj 
10*a9fa9459Szrj Libiberty is distributed in the hope that it will be useful,
11*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
12*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*a9fa9459Szrj Library General Public License for more details.
14*a9fa9459Szrj 
15*a9fa9459Szrj You should have received a copy of the GNU Library General Public
16*a9fa9459Szrj License along with libiberty; see the file COPYING.LIB.  If not, write
17*a9fa9459Szrj to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18*a9fa9459Szrj Boston, MA 02110-1301, USA.  */
19*a9fa9459Szrj 
20*a9fa9459Szrj /* The functions defined here can be speed critical.
21*a9fa9459Szrj    Since they are all pretty small we keep things simple and just define
22*a9fa9459Szrj    them all as "static inline".
23*a9fa9459Szrj 
24*a9fa9459Szrj    WARNING: This file is used by GDB which is stuck at C90. :-(
25*a9fa9459Szrj    Though it can use stdint.h, inttypes.h.
26*a9fa9459Szrj    Therefore if you want to add support for "long long" you need
27*a9fa9459Szrj    to wrap it in #ifdef CC_HAS_LONG_LONG.  */
28*a9fa9459Szrj 
29*a9fa9459Szrj #ifndef LEB128_H
30*a9fa9459Szrj #define LEB128_H
31*a9fa9459Szrj 
32*a9fa9459Szrj /* Get a definition for inline.  */
33*a9fa9459Szrj #include "ansidecl.h"
34*a9fa9459Szrj 
35*a9fa9459Szrj /* Get a definition for NULL, size_t.  */
36*a9fa9459Szrj #include <stddef.h>
37*a9fa9459Szrj 
38*a9fa9459Szrj #ifdef HAVE_STDINT_H
39*a9fa9459Szrj #include <stdint.h>
40*a9fa9459Szrj #endif
41*a9fa9459Szrj #ifdef HAVE_INTTYPES_H
42*a9fa9459Szrj #include <inttypes.h>
43*a9fa9459Szrj #endif
44*a9fa9459Szrj 
45*a9fa9459Szrj /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
46*a9fa9459Szrj    by R, and return the number of bytes read.
47*a9fa9459Szrj    If we read off the end of the buffer, zero is returned,
48*a9fa9459Szrj    and nothing is stored in R.
49*a9fa9459Szrj 
50*a9fa9459Szrj    Note: The result is an int instead of a pointer to the next byte to be
51*a9fa9459Szrj    read to avoid const-vs-non-const problems.  */
52*a9fa9459Szrj 
53*a9fa9459Szrj static inline size_t
read_uleb128_to_uint64(const unsigned char * buf,const unsigned char * buf_end,uint64_t * r)54*a9fa9459Szrj read_uleb128_to_uint64 (const unsigned char *buf, const unsigned char *buf_end,
55*a9fa9459Szrj 			uint64_t *r)
56*a9fa9459Szrj {
57*a9fa9459Szrj   const unsigned char *p = buf;
58*a9fa9459Szrj   unsigned int shift = 0;
59*a9fa9459Szrj   uint64_t result = 0;
60*a9fa9459Szrj   unsigned char byte;
61*a9fa9459Szrj 
62*a9fa9459Szrj   while (1)
63*a9fa9459Szrj     {
64*a9fa9459Szrj       if (p >= buf_end)
65*a9fa9459Szrj 	return 0;
66*a9fa9459Szrj 
67*a9fa9459Szrj       byte = *p++;
68*a9fa9459Szrj       result |= ((uint64_t) (byte & 0x7f)) << shift;
69*a9fa9459Szrj       if ((byte & 0x80) == 0)
70*a9fa9459Szrj 	break;
71*a9fa9459Szrj       shift += 7;
72*a9fa9459Szrj     }
73*a9fa9459Szrj 
74*a9fa9459Szrj   *r = result;
75*a9fa9459Szrj   return p - buf;
76*a9fa9459Szrj }
77*a9fa9459Szrj 
78*a9fa9459Szrj /* Decode the signed LEB128 constant at BUF into the variable pointed to
79*a9fa9459Szrj    by R, and return the number of bytes read.
80*a9fa9459Szrj    If we read off the end of the buffer, zero is returned,
81*a9fa9459Szrj    and nothing is stored in R.
82*a9fa9459Szrj 
83*a9fa9459Szrj    Note: The result is an int instead of a pointer to the next byte to be
84*a9fa9459Szrj    read to avoid const-vs-non-const problems.  */
85*a9fa9459Szrj 
86*a9fa9459Szrj static inline size_t
read_sleb128_to_int64(const unsigned char * buf,const unsigned char * buf_end,int64_t * r)87*a9fa9459Szrj read_sleb128_to_int64 (const unsigned char *buf, const unsigned char *buf_end,
88*a9fa9459Szrj 		       int64_t *r)
89*a9fa9459Szrj {
90*a9fa9459Szrj   const unsigned char *p = buf;
91*a9fa9459Szrj   unsigned int shift = 0;
92*a9fa9459Szrj   int64_t result = 0;
93*a9fa9459Szrj   unsigned char byte;
94*a9fa9459Szrj 
95*a9fa9459Szrj   while (1)
96*a9fa9459Szrj     {
97*a9fa9459Szrj       if (p >= buf_end)
98*a9fa9459Szrj 	return 0;
99*a9fa9459Szrj 
100*a9fa9459Szrj       byte = *p++;
101*a9fa9459Szrj       result |= ((uint64_t) (byte & 0x7f)) << shift;
102*a9fa9459Szrj       shift += 7;
103*a9fa9459Szrj       if ((byte & 0x80) == 0)
104*a9fa9459Szrj 	break;
105*a9fa9459Szrj     }
106*a9fa9459Szrj   if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
107*a9fa9459Szrj     result |= -(((uint64_t) 1) << shift);
108*a9fa9459Szrj 
109*a9fa9459Szrj   *r = result;
110*a9fa9459Szrj   return p - buf;
111*a9fa9459Szrj }
112*a9fa9459Szrj 
113*a9fa9459Szrj /* Return the number of bytes to read to skip past an LEB128 number in BUF.
114*a9fa9459Szrj    If the end isn't found before reaching BUF_END, return zero.
115*a9fa9459Szrj 
116*a9fa9459Szrj    Note: The result is an int instead of a pointer to the next byte to be
117*a9fa9459Szrj    read to avoid const-vs-non-const problems.  */
118*a9fa9459Szrj 
119*a9fa9459Szrj static inline size_t
skip_leb128(const unsigned char * buf,const unsigned char * buf_end)120*a9fa9459Szrj skip_leb128 (const unsigned char *buf, const unsigned char *buf_end)
121*a9fa9459Szrj {
122*a9fa9459Szrj   const unsigned char *p = buf;
123*a9fa9459Szrj   unsigned char byte;
124*a9fa9459Szrj 
125*a9fa9459Szrj   while (1)
126*a9fa9459Szrj     {
127*a9fa9459Szrj       if (p == buf_end)
128*a9fa9459Szrj 	return 0;
129*a9fa9459Szrj 
130*a9fa9459Szrj       byte = *p++;
131*a9fa9459Szrj       if ((byte & 0x80) == 0)
132*a9fa9459Szrj 	return p - buf;
133*a9fa9459Szrj     }
134*a9fa9459Szrj }
135*a9fa9459Szrj 
136*a9fa9459Szrj #endif /* LEB128_H */
137