aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/include/llvm/Support/BinaryItemStream.h
blob: 334d6252c7e6fc2637482194d199f5bd12e04253 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#pragma once 
 
#ifdef __GNUC__ 
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wunused-parameter" 
#endif 
 
//===- BinaryItemStream.h ---------------------------------------*- C++ -*-===// 
// 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
// See https://llvm.org/LICENSE.txt for license information. 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
// 
//===----------------------------------------------------------------------===// 
 
#ifndef LLVM_SUPPORT_BINARYITEMSTREAM_H 
#define LLVM_SUPPORT_BINARYITEMSTREAM_H 
 
#include "llvm/ADT/ArrayRef.h" 
#include "llvm/Support/BinaryStream.h" 
#include "llvm/Support/BinaryStreamError.h" 
#include "llvm/Support/Error.h" 
#include <cstddef> 
#include <cstdint> 
 
namespace llvm { 
 
template <typename T> struct BinaryItemTraits { 
  static size_t length(const T &Item) = delete; 
  static ArrayRef<uint8_t> bytes(const T &Item) = delete; 
}; 
 
/// BinaryItemStream represents a sequence of objects stored in some kind of 
/// external container but for which it is useful to view as a stream of 
/// contiguous bytes.  An example of this might be if you have a collection of 
/// records and you serialize each one into a buffer, and store these serialized 
/// records in a container.  The pointers themselves are not laid out 
/// contiguously in memory, but we may wish to read from or write to these 
/// records as if they were. 
template <typename T, typename Traits = BinaryItemTraits<T>> 
class BinaryItemStream : public BinaryStream { 
public: 
  explicit BinaryItemStream(llvm::support::endianness Endian) 
      : Endian(Endian) {} 
 
  llvm::support::endianness getEndian() const override { return Endian; } 
 
  Error readBytes(uint32_t Offset, uint32_t Size, 
                  ArrayRef<uint8_t> &Buffer) override { 
    auto ExpectedIndex = translateOffsetIndex(Offset); 
    if (!ExpectedIndex) 
      return ExpectedIndex.takeError(); 
    const auto &Item = Items[*ExpectedIndex]; 
    if (auto EC = checkOffsetForRead(Offset, Size)) 
      return EC; 
    if (Size > Traits::length(Item)) 
      return make_error<BinaryStreamError>(stream_error_code::stream_too_short); 
    Buffer = Traits::bytes(Item).take_front(Size); 
    return Error::success(); 
  } 
 
  Error readLongestContiguousChunk(uint32_t Offset, 
                                   ArrayRef<uint8_t> &Buffer) override { 
    auto ExpectedIndex = translateOffsetIndex(Offset); 
    if (!ExpectedIndex) 
      return ExpectedIndex.takeError(); 
    Buffer = Traits::bytes(Items[*ExpectedIndex]); 
    return Error::success(); 
  } 
 
  void setItems(ArrayRef<T> ItemArray) { 
    Items = ItemArray; 
    computeItemOffsets(); 
  } 
 
  uint32_t getLength() override { 
    return ItemEndOffsets.empty() ? 0 : ItemEndOffsets.back(); 
  } 
 
private: 
  void computeItemOffsets() { 
    ItemEndOffsets.clear(); 
    ItemEndOffsets.reserve(Items.size()); 
    uint32_t CurrentOffset = 0; 
    for (const auto &Item : Items) { 
      uint32_t Len = Traits::length(Item); 
      assert(Len > 0 && "no empty items"); 
      CurrentOffset += Len; 
      ItemEndOffsets.push_back(CurrentOffset); 
    } 
  } 
 
  Expected<uint32_t> translateOffsetIndex(uint32_t Offset) { 
    // Make sure the offset is somewhere in our items array. 
    if (Offset >= getLength()) 
      return make_error<BinaryStreamError>(stream_error_code::stream_too_short); 
    ++Offset; 
    auto Iter = llvm::lower_bound(ItemEndOffsets, Offset);
    size_t Idx = std::distance(ItemEndOffsets.begin(), Iter); 
    assert(Idx < Items.size() && "binary search for offset failed"); 
    return Idx; 
  } 
 
  llvm::support::endianness Endian; 
  ArrayRef<T> Items; 
 
  // Sorted vector of offsets to accelerate lookup. 
  std::vector<uint32_t> ItemEndOffsets; 
}; 
 
} // end namespace llvm 
 
#endif // LLVM_SUPPORT_BINARYITEMSTREAM_H 
 
#ifdef __GNUC__ 
#pragma GCC diagnostic pop 
#endif