| Index: include/leb128.h
|
| diff --git a/include/leb128.h b/include/leb128.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f584f72e5a9af9b8a9a2dcb2bd959d894a0f9238
|
| --- /dev/null
|
| +++ b/include/leb128.h
|
| @@ -0,0 +1,136 @@
|
| +/* Utilities for reading leb128 values.
|
| + Copyright (C) 2012 Free Software Foundation, Inc.
|
| +
|
| +This file is part of the libiberty library.
|
| +Libiberty is free software; you can redistribute it and/or
|
| +modify it under the terms of the GNU Library General Public
|
| +License as published by the Free Software Foundation; either
|
| +version 2 of the License, or (at your option) any later version.
|
| +
|
| +Libiberty is distributed in the hope that it will be useful,
|
| +but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
| +Library General Public License for more details.
|
| +
|
| +You should have received a copy of the GNU Library General Public
|
| +License along with libiberty; see the file COPYING.LIB. If not, write
|
| +to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
|
| +Boston, MA 02110-1301, USA. */
|
| +
|
| +/* The functions defined here can be speed critical.
|
| + Since they are all pretty small we keep things simple and just define
|
| + them all as "static inline".
|
| +
|
| + WARNING: This file is used by GDB which is stuck at C90. :-(
|
| + Though it can use stdint.h, inttypes.h.
|
| + Therefore if you want to add support for "long long" you need
|
| + to wrap it in #ifdef CC_HAS_LONG_LONG. */
|
| +
|
| +#ifndef LEB128_H
|
| +#define LEB128_H
|
| +
|
| +/* Get a definition for inline. */
|
| +#include "ansidecl.h"
|
| +
|
| +/* Get a definition for NULL, size_t. */
|
| +#include <stddef.h>
|
| +
|
| +#ifdef HAVE_STDINT_H
|
| +#include <stdint.h>
|
| +#endif
|
| +#ifdef HAVE_INTTYPES_H
|
| +#include <inttypes.h>
|
| +#endif
|
| +
|
| +/* Decode the unsigned LEB128 constant at BUF into the variable pointed to
|
| + by R, and return the number of bytes read.
|
| + If we read off the end of the buffer, zero is returned,
|
| + and nothing is stored in R.
|
| +
|
| + Note: The result is an int instead of a pointer to the next byte to be
|
| + read to avoid const-vs-non-const problems. */
|
| +
|
| +static inline size_t
|
| +read_uleb128_to_uint64 (const unsigned char *buf, const unsigned char *buf_end,
|
| + uint64_t *r)
|
| +{
|
| + const unsigned char *p = buf;
|
| + unsigned int shift = 0;
|
| + uint64_t result = 0;
|
| + unsigned char byte;
|
| +
|
| + while (1)
|
| + {
|
| + if (p >= buf_end)
|
| + return 0;
|
| +
|
| + byte = *p++;
|
| + result |= ((uint64_t) (byte & 0x7f)) << shift;
|
| + if ((byte & 0x80) == 0)
|
| + break;
|
| + shift += 7;
|
| + }
|
| +
|
| + *r = result;
|
| + return p - buf;
|
| +}
|
| +
|
| +/* Decode the signed LEB128 constant at BUF into the variable pointed to
|
| + by R, and return the number of bytes read.
|
| + If we read off the end of the buffer, zero is returned,
|
| + and nothing is stored in R.
|
| +
|
| + Note: The result is an int instead of a pointer to the next byte to be
|
| + read to avoid const-vs-non-const problems. */
|
| +
|
| +static inline size_t
|
| +read_sleb128_to_int64 (const unsigned char *buf, const unsigned char *buf_end,
|
| + int64_t *r)
|
| +{
|
| + const unsigned char *p = buf;
|
| + unsigned int shift = 0;
|
| + int64_t result = 0;
|
| + unsigned char byte;
|
| +
|
| + while (1)
|
| + {
|
| + if (p >= buf_end)
|
| + return 0;
|
| +
|
| + byte = *p++;
|
| + result |= ((uint64_t) (byte & 0x7f)) << shift;
|
| + shift += 7;
|
| + if ((byte & 0x80) == 0)
|
| + break;
|
| + }
|
| + if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
|
| + result |= -(((uint64_t) 1) << shift);
|
| +
|
| + *r = result;
|
| + return p - buf;
|
| +}
|
| +
|
| +/* Return the number of bytes to read to skip past an LEB128 number in BUF.
|
| + If the end isn't found before reaching BUF_END, return zero.
|
| +
|
| + Note: The result is an int instead of a pointer to the next byte to be
|
| + read to avoid const-vs-non-const problems. */
|
| +
|
| +static inline size_t
|
| +skip_leb128 (const unsigned char *buf, const unsigned char *buf_end)
|
| +{
|
| + const unsigned char *p = buf;
|
| + unsigned char byte;
|
| +
|
| + while (1)
|
| + {
|
| + if (p == buf_end)
|
| + return 0;
|
| +
|
| + byte = *p++;
|
| + if ((byte & 0x80) == 0)
|
| + return p - buf;
|
| + }
|
| +}
|
| +
|
| +#endif /* LEB128_H */
|
|
|