Line data Source code
1 : //===- SequencedItemStream.h ------------------------------------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
11 : #define LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
12 :
13 : #include "llvm/ADT/ArrayRef.h"
14 : #include "llvm/DebugInfo/MSF/MSFError.h"
15 : #include "llvm/DebugInfo/MSF/StreamInterface.h"
16 : #include "llvm/Support/Error.h"
17 : #include <cstddef>
18 : #include <cstdint>
19 :
20 : namespace llvm {
21 : namespace msf {
22 :
23 : template <typename T> struct SequencedItemTraits {
24 : static size_t length(const T &Item) = delete;
25 : static ArrayRef<uint8_t> bytes(const T &Item) = delete;
26 : };
27 :
28 : /// SequencedItemStream represents a sequence of objects stored in a
29 : /// standard container but for which it is useful to view as a stream of
30 : /// contiguous bytes. An example of this might be if you have a std::vector
31 : /// of TPI records, where each record contains a byte sequence that
32 : /// represents that one record serialized, but where each consecutive item
33 : /// might not be allocated immediately after the previous item. Using a
34 : /// SequencedItemStream, we can adapt the VarStreamArray class to trivially
35 : /// extract one item at a time, allowing the data to be used anywhere a
36 : /// VarStreamArray could be used.
37 : template <typename T, typename Traits = SequencedItemTraits<T>>
38 10 : class SequencedItemStream : public ReadableStream {
39 : public:
40 20 : SequencedItemStream() = default;
41 :
42 0 : Error readBytes(uint32_t Offset, uint32_t Size,
43 : ArrayRef<uint8_t> &Buffer) const override {
44 0 : auto ExpectedIndex = translateOffsetIndex(Offset);
45 0 : if (!ExpectedIndex)
46 0 : return ExpectedIndex.takeError();
47 0 : const auto &Item = Items[*ExpectedIndex];
48 0 : if (Size > Traits::length(Item))
49 0 : return make_error<MSFError>(msf_error_code::insufficient_buffer);
50 0 : Buffer = Traits::bytes(Item).take_front(Size);
51 0 : return Error::success();
52 : }
53 :
54 201 : Error readLongestContiguousChunk(uint32_t Offset,
55 : ArrayRef<uint8_t> &Buffer) const override {
56 402 : auto ExpectedIndex = translateOffsetIndex(Offset);
57 201 : if (!ExpectedIndex)
58 0 : return ExpectedIndex.takeError();
59 402 : Buffer = Traits::bytes(Items[*ExpectedIndex]);
60 603 : return Error::success();
61 : }
62 :
63 201 : void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
64 :
65 10 : uint32_t getLength() const override {
66 30 : uint32_t Size = 0;
67 663 : for (const auto &Item : Items)
68 603 : Size += Traits::length(Item);
69 10 : return Size;
70 : }
71 :
72 : private:
73 201 : Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const {
74 201 : uint32_t CurrentOffset = 0;
75 201 : uint32_t CurrentIndex = 0;
76 6360 : for (const auto &Item : Items) {
77 6159 : if (CurrentOffset >= Offset)
78 : break;
79 5958 : CurrentOffset += Traits::length(Item);
80 5958 : ++CurrentIndex;
81 : }
82 201 : if (CurrentOffset != Offset)
83 0 : return make_error<MSFError>(msf_error_code::insufficient_buffer);
84 : return CurrentIndex;
85 : }
86 :
87 : ArrayRef<T> Items;
88 : };
89 :
90 : } // end namespace msf
91 : } // end namespace llvm
92 :
93 : #endif // LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
|