//===- BinaryStreamArray.h - Array backed by an arbitrary stream *- 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 // //===----------------------------------------------------------------------===// /// /// \file /// Lightweight arrays that are backed by an arbitrary BinaryStream. This file /// provides two different array implementations. /// /// VarStreamArray - Arrays of variable length records. The user specifies /// an Extractor type that can extract a record from a given offset and /// return the number of bytes consumed by the record. /// /// FixedStreamArray - Arrays of fixed length records. This is similar in /// spirit to ArrayRef<T>, but since it is backed by a BinaryStream, the /// elements of the array need not be laid out in contiguous memory. /// #ifndef LLVM_SUPPORT_BINARYSTREAMARRAY_H #define LLVM_SUPPORT_BINARYSTREAMARRAY_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/iterator.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Error.h" #include <cassert> #include <cstdint> namespace llvm { /// VarStreamArrayExtractor is intended to be specialized to provide customized /// extraction logic. On input it receives a BinaryStreamRef pointing to the /// beginning of the next record, but where the length of the record is not yet /// known. Upon completion, it should return an appropriate Error instance if /// a record could not be extracted, or if one could be extracted it should /// return success and set Len to the number of bytes this record occupied in /// the underlying stream, and it should fill out the fields of the value type /// Item appropriately to represent the current record. /// /// You can specialize this template for your own custom value types to avoid /// having to specify a second template argument to VarStreamArray (documented /// below). template <typename T> struct VarStreamArrayExtractor { … }; /// VarStreamArray represents an array of variable length records backed by a /// stream. This could be a contiguous sequence of bytes in memory, it could /// be a file on disk, or it could be a PDB stream where bytes are stored as /// discontiguous blocks in a file. Usually it is desirable to treat arrays /// as contiguous blocks of memory, but doing so with large PDB files, for /// example, could mean allocating huge amounts of memory just to allow /// re-ordering of stream data to be contiguous before iterating over it. By /// abstracting this out, we need not duplicate this memory, and we can /// iterate over arrays in arbitrarily formatted streams. Elements are parsed /// lazily on iteration, so there is no upfront cost associated with building /// or copying a VarStreamArray, no matter how large it may be. /// /// You create a VarStreamArray by specifying a ValueType and an Extractor type. /// If you do not specify an Extractor type, you are expected to specialize /// VarStreamArrayExtractor<T> for your ValueType. /// /// By default an Extractor is default constructed in the class, but in some /// cases you might find it useful for an Extractor to maintain state across /// extractions. In this case you can provide your own Extractor through a /// secondary constructor. The following examples show various ways of /// creating a VarStreamArray. /// /// // Will use VarStreamArrayExtractor<MyType> as the extractor. /// VarStreamArray<MyType> MyTypeArray; /// /// // Will use a default-constructed MyExtractor as the extractor. /// VarStreamArray<MyType, MyExtractor> MyTypeArray2; /// /// // Will use the specific instance of MyExtractor provided. /// // MyExtractor need not be default-constructible in this case. /// MyExtractor E(SomeContext); /// VarStreamArray<MyType, MyExtractor> MyTypeArray3(E); /// template <typename ValueType, typename Extractor> class VarStreamArrayIterator; template <typename ValueType, typename Extractor = VarStreamArrayExtractor<ValueType>> class VarStreamArray { friend class VarStreamArrayIterator<ValueType, Extractor>; public: typedef VarStreamArrayIterator<ValueType, Extractor> Iterator; VarStreamArray() = default; explicit VarStreamArray(const Extractor &E) : … { … } explicit VarStreamArray(BinaryStreamRef Stream, uint32_t Skew = 0) : … { … } VarStreamArray(BinaryStreamRef Stream, const Extractor &E, uint32_t Skew = 0) : … { … } Iterator begin(bool *HadError = nullptr) const { … } bool valid() const { … } bool isOffsetValid(uint32_t Offset) const { … } uint32_t skew() const { … } Iterator end() const { … } bool empty() const { … } VarStreamArray<ValueType, Extractor> substream(uint32_t Begin, uint32_t End) const { … } /// given an offset into the array's underlying stream, return an /// iterator to the record at that offset. This is considered unsafe /// since the behavior is undefined if \p Offset does not refer to the /// beginning of a valid record. Iterator at(uint32_t Offset) const { … } const Extractor &getExtractor() const { … } Extractor &getExtractor() { … } BinaryStreamRef getUnderlyingStream() const { … } void setUnderlyingStream(BinaryStreamRef NewStream, uint32_t NewSkew = 0) { … } void drop_front() { … } private: BinaryStreamRef Stream; Extractor E; uint32_t Skew = 0; }; template <typename ValueType, typename Extractor> class VarStreamArrayIterator : public iterator_facade_base<VarStreamArrayIterator<ValueType, Extractor>, std::forward_iterator_tag, const ValueType> { … }; template <typename T> class FixedStreamArrayIterator; /// FixedStreamArray is similar to VarStreamArray, except with each record /// having a fixed-length. As with VarStreamArray, there is no upfront /// cost associated with building or copying a FixedStreamArray, as the /// memory for each element is not read from the backing stream until that /// element is iterated. template <typename T> class FixedStreamArray { … }; template <typename T> class FixedStreamArrayIterator : public iterator_facade_base<FixedStreamArrayIterator<T>, std::random_access_iterator_tag, const T> { … }; } // namespace llvm #endif // LLVM_SUPPORT_BINARYSTREAMARRAY_H