summaryrefslogtreecommitdiff
path: root/include/llvm/Support/BinaryStreamArray.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-02 18:30:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-02 18:30:13 +0000
commita303c417bbdb53703c2c17398b08486bde78f1f6 (patch)
tree98366d6b93d863cefdc53f16c66c0c5ae7fb2261 /include/llvm/Support/BinaryStreamArray.h
parent12f3ca4cdb95b193af905a00e722a4dcb40b3de3 (diff)
Notes
Diffstat (limited to 'include/llvm/Support/BinaryStreamArray.h')
-rw-r--r--include/llvm/Support/BinaryStreamArray.h99
1 files changed, 53 insertions, 46 deletions
diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h
index 21b2474660f2c..748a62be231e4 100644
--- a/include/llvm/Support/BinaryStreamArray.h
+++ b/include/llvm/Support/BinaryStreamArray.h
@@ -42,10 +42,12 @@ namespace llvm {
/// having to specify a second template argument to VarStreamArray (documented
/// below).
template <typename T> struct VarStreamArrayExtractor {
+ typedef void Context;
+
// Method intentionally deleted. You must provide an explicit specialization
// with the following method implemented.
- Error operator()(BinaryStreamRef Stream, uint32_t &Len,
- T &Item) const = delete;
+ static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item,
+ Context *Ctx) = delete;
};
/// VarStreamArray represents an array of variable length records backed by a
@@ -64,82 +66,87 @@ template <typename T> struct VarStreamArrayExtractor {
/// 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);
+/// The default extractor type is stateless, but by specializing
+/// VarStreamArrayExtractor or defining your own custom extractor type and
+/// adding the appropriate ContextType typedef to the class, you can pass a
+/// context field during construction of the VarStreamArray that will be
+/// passed to each call to extract.
///
-template <typename ValueType, typename Extractor> class VarStreamArrayIterator;
+template <typename ValueType, typename ExtractorType>
+class VarStreamArrayIterator;
template <typename ValueType,
- typename Extractor = VarStreamArrayExtractor<ValueType>>
-
+ typename ExtractorType = VarStreamArrayExtractor<ValueType>>
class VarStreamArray {
- friend class VarStreamArrayIterator<ValueType, Extractor>;
-
public:
- typedef VarStreamArrayIterator<ValueType, Extractor> Iterator;
+ typedef typename ExtractorType::ContextType ContextType;
+ typedef VarStreamArrayIterator<ValueType, ExtractorType> Iterator;
+ friend Iterator;
VarStreamArray() = default;
- explicit VarStreamArray(const Extractor &E) : E(E) {}
- explicit VarStreamArray(BinaryStreamRef Stream) : Stream(Stream) {}
- VarStreamArray(BinaryStreamRef Stream, const Extractor &E)
- : Stream(Stream), E(E) {}
+ explicit VarStreamArray(BinaryStreamRef Stream,
+ ContextType *Context = nullptr)
+ : Stream(Stream), Context(Context) {}
- VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other)
- : Stream(Other.Stream), E(Other.E) {}
+ VarStreamArray(const VarStreamArray<ValueType, ExtractorType> &Other)
+ : Stream(Other.Stream), Context(Other.Context) {}
Iterator begin(bool *HadError = nullptr) const {
- return Iterator(*this, E, HadError);
+ if (empty())
+ return end();
+
+ return Iterator(*this, Context, HadError);
}
- Iterator end() const { return Iterator(E); }
+ Iterator end() const { return Iterator(); }
- const Extractor &getExtractor() const { return E; }
+ bool empty() const { return Stream.getLength() == 0; }
+
+ /// \brief 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 {
+ return Iterator(*this, Context, Stream.drop_front(Offset), nullptr);
+ }
BinaryStreamRef getUnderlyingStream() const { return Stream; }
private:
BinaryStreamRef Stream;
- Extractor E;
+ ContextType *Context = nullptr;
};
-template <typename ValueType, typename Extractor>
+template <typename ValueType, typename ExtractorType>
class VarStreamArrayIterator
- : public iterator_facade_base<VarStreamArrayIterator<ValueType, Extractor>,
- std::forward_iterator_tag, ValueType> {
- typedef VarStreamArrayIterator<ValueType, Extractor> IterType;
- typedef VarStreamArray<ValueType, Extractor> ArrayType;
+ : public iterator_facade_base<
+ VarStreamArrayIterator<ValueType, ExtractorType>,
+ std::forward_iterator_tag, ValueType> {
+ typedef typename ExtractorType::ContextType ContextType;
+ typedef VarStreamArrayIterator<ValueType, ExtractorType> IterType;
+ typedef VarStreamArray<ValueType, ExtractorType> ArrayType;
public:
- VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
- bool *HadError = nullptr)
- : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) {
+ VarStreamArrayIterator(const ArrayType &Array, ContextType *Context,
+ BinaryStreamRef Stream, bool *HadError = nullptr)
+ : IterRef(Stream), Context(Context), Array(&Array), HadError(HadError) {
if (IterRef.getLength() == 0)
moveToEnd();
else {
- auto EC = Extract(IterRef, ThisLen, ThisValue);
+ auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context);
if (EC) {
consumeError(std::move(EC));
markError();
}
}
}
+
+ VarStreamArrayIterator(const ArrayType &Array, ContextType *Context,
+ bool *HadError = nullptr)
+ : VarStreamArrayIterator(Array, Context, Array.Stream, HadError) {}
+
VarStreamArrayIterator() = default;
- explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {}
~VarStreamArrayIterator() = default;
bool operator==(const IterType &R) const {
@@ -178,7 +185,7 @@ public:
moveToEnd();
} else {
// There is some data after the current record.
- auto EC = Extract(IterRef, ThisLen, ThisValue);
+ auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context);
if (EC) {
consumeError(std::move(EC));
markError();
@@ -205,11 +212,11 @@ private:
ValueType ThisValue;
BinaryStreamRef IterRef;
+ ContextType *Context{nullptr};
const ArrayType *Array{nullptr};
uint32_t ThisLen{0};
bool HasError{false};
bool *HadError{nullptr};
- Extractor Extract;
};
template <typename T> class FixedStreamArrayIterator;