103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file.
403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#ifndef CRAZY_LINKER_LEB128_H
603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define CRAZY_LINKER_LEB128_H
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <stdint.h>
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Helper classes for decoding LEB128, used in packed relocation data.
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// http://en.wikipedia.org/wiki/LEB128
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace crazy {
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class Leb128Decoder {
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public:
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  explicit Leb128Decoder(const uint8_t* encoding)
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      : encoding_(encoding), cursor_(0) { }
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t Dequeue() {
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uint32_t value = 0;
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    size_t shift = 0;
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uint8_t byte;
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    do {
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      byte = encoding_[cursor_++];
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      value |= static_cast<uint32_t>(byte & 127) << shift;
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      shift += 7;
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } while (byte & 128);
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return value;
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private:
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8_t* encoding_;
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t cursor_;
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class Sleb128Decoder {
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public:
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  explicit Sleb128Decoder(const uint8_t* encoding)
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      : encoding_(encoding), cursor_(0) { }
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ssize_t Dequeue() {
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ssize_t value = 0;
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    static const size_t size = CHAR_BIT * sizeof(value);
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    size_t shift = 0;
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uint8_t byte;
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    do {
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      byte = encoding_[cursor_++];
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      value |= (static_cast<ssize_t>(byte & 127) << shift);
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      shift += 7;
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    } while (byte & 128);
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (shift < size && (byte & 64))
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      value |= -(static_cast<ssize_t>(1) << shift);
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return value;
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) private:
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8_t* encoding_;
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t cursor_;
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace crazy
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif  // CRAZY_LINKER_LEB128_H
72