summaryrefslogtreecommitdiff
path: root/include/llvm/Support/BinaryItemStream.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-07-19 07:02:10 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-07-19 07:02:10 +0000
commit93c91e39b29142dec1d03a30df9f6e757f56c193 (patch)
tree33a9b014a327e64450b3c9ed46d8c5bdb78ad345 /include/llvm/Support/BinaryItemStream.h
parentca089b24d48ef6fa8da2d0bb8c25bb802c4a95c0 (diff)
Notes
Diffstat (limited to 'include/llvm/Support/BinaryItemStream.h')
-rw-r--r--include/llvm/Support/BinaryItemStream.h39
1 files changed, 26 insertions, 13 deletions
diff --git a/include/llvm/Support/BinaryItemStream.h b/include/llvm/Support/BinaryItemStream.h
index f4b319217819e..fe7e6caeaafb7 100644
--- a/include/llvm/Support/BinaryItemStream.h
+++ b/include/llvm/Support/BinaryItemStream.h
@@ -62,32 +62,45 @@ public:
return Error::success();
}
- void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
+ void setItems(ArrayRef<T> ItemArray) {
+ Items = ItemArray;
+ computeItemOffsets();
+ }
uint32_t getLength() override {
- uint32_t Size = 0;
- for (const auto &Item : Items)
- Size += Traits::length(Item);
- return Size;
+ return ItemEndOffsets.empty() ? 0 : ItemEndOffsets.back();
}
private:
- Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const {
+ void computeItemOffsets() {
+ ItemEndOffsets.clear();
+ ItemEndOffsets.reserve(Items.size());
uint32_t CurrentOffset = 0;
- uint32_t CurrentIndex = 0;
for (const auto &Item : Items) {
- if (CurrentOffset >= Offset)
- break;
- CurrentOffset += Traits::length(Item);
- ++CurrentIndex;
+ uint32_t Len = Traits::length(Item);
+ assert(Len > 0 && "no empty items");
+ CurrentOffset += Len;
+ ItemEndOffsets.push_back(CurrentOffset);
}
- if (CurrentOffset != Offset)
+ }
+
+ 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);
- return CurrentIndex;
+ ++Offset;
+ auto Iter =
+ std::lower_bound(ItemEndOffsets.begin(), ItemEndOffsets.end(), 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