llvm.org GIT mirror llvm / 67e6ece
[Support] Make BinaryStreamArray extractors stateless. Instead, we now pass a context memeber through the extraction process. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301556 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 3 years ago
8 changed file(s) with 77 addition(s) and 82 deletion(s). Raw diff Collapse all Expand all
4949
5050 template
5151 struct VarStreamArrayExtractor> {
52 Error operator()(BinaryStreamRef Stream, uint32_t &Len,
53 codeview::CVRecord &Item) const {
52 typedef void ContextType;
53
54 static Error extract(BinaryStreamRef Stream, uint32_t &Len,
55 codeview::CVRecord &Item, void *Ctx) {
5456 using namespace codeview;
5557 const RecordPrefix *Prefix = nullptr;
5658 BinaryStreamReader Reader(Stream);
7373 } // namespace codeview
7474
7575 template <> struct VarStreamArrayExtractor {
76 Error operator()(BinaryStreamRef Stream, uint32_t &Length,
77 codeview::ModuleDebugFragment &Info) const {
76 typedef void ContextType;
77
78 static Error extract(BinaryStreamRef Stream, uint32_t &Length,
79 codeview::ModuleDebugFragment &Info, void *Ctx) {
7880 if (auto EC = codeview::ModuleDebugFragment::initialize(Stream, Info))
7981 return EC;
8082 Length = Info.getRecordLength();
7070
7171 template <> class VarStreamArrayExtractor {
7272 public:
73 VarStreamArrayExtractor(const codeview::LineFragmentHeader *Header)
74 : Header(Header) {}
73 typedef const codeview::LineFragmentHeader ContextType;
7574
76 Error operator()(BinaryStreamRef Stream, uint32_t &Len,
77 codeview::LineColumnEntry &Item) const {
75 static Error extract(BinaryStreamRef Stream, uint32_t &Len,
76 codeview::LineColumnEntry &Item, ContextType *Header) {
7877 using namespace codeview;
7978 const LineBlockFragmentHeader *BlockHeader;
8079 BinaryStreamReader Reader(Stream);
103102 }
104103 return Error::success();
105104 }
106
107 private:
108 const codeview::LineFragmentHeader *Header;
109105 };
110106
111107 template <> class VarStreamArrayExtractor {
112108 public:
113 Error operator()(BinaryStreamRef Stream, uint32_t &Len,
114 codeview::FileChecksumEntry &Item) const {
109 typedef void ContextType;
110
111 static Error extract(BinaryStreamRef Stream, uint32_t &Len,
112 codeview::FileChecksumEntry &Item, void *Ctx) {
115113 using namespace codeview;
116114 const FileChecksum *Header;
117115 BinaryStreamReader Reader(Stream);
6363 } // end namespace pdb
6464
6565 template <> struct VarStreamArrayExtractor {
66 Error operator()(BinaryStreamRef Stream, uint32_t &Length,
67 pdb::DbiModuleDescriptor &Info) const {
66 typedef void ContextType;
67 static Error extract(BinaryStreamRef Stream, uint32_t &Length,
68 pdb::DbiModuleDescriptor &Info, void *Ctx) {
6869 if (auto EC = pdb::DbiModuleDescriptor::initialize(Stream, Info))
6970 return EC;
7071 Length = Info.getRecordLength();
4141 /// having to specify a second template argument to VarStreamArray (documented
4242 /// below).
4343 template struct VarStreamArrayExtractor {
44 typedef void Context;
45
4446 // Method intentionally deleted. You must provide an explicit specialization
4547 // with the following method implemented.
46 Error operator()(BinaryStreamRef Stream, uint32_t &Len,
47 T &Item) const = delete;
48 static Error extract(BinaryStreamRef Stream, uint32_t &Len, T &Item,
49 Context *Ctx) = delete;
4850 };
4951
5052 /// VarStreamArray represents an array of variable length records backed by a
6365 /// If you do not specify an Extractor type, you are expected to specialize
6466 /// VarStreamArrayExtractor for your ValueType.
6567 ///
66 /// By default an Extractor is default constructed in the class, but in some
67 /// cases you might find it useful for an Extractor to maintain state across
68 /// extractions. In this case you can provide your own Extractor through a
69 /// secondary constructor. The following examples show various ways of
70 /// creating a VarStreamArray.
71 ///
72 /// // Will use VarStreamArrayExtractor as the extractor.
73 /// VarStreamArray MyTypeArray;
74 ///
75 /// // Will use a default-constructed MyExtractor as the extractor.
76 /// VarStreamArray MyTypeArray2;
77 ///
78 /// // Will use the specific instance of MyExtractor provided.
79 /// // MyExtractor need not be default-constructible in this case.
80 /// MyExtractor E(SomeContext);
81 /// VarStreamArray MyTypeArray3(E);
82 ///
83 template class VarStreamArrayIterator;
68 /// The default extractor type is stateless, but by specializing
69 /// VarStreamArrayExtractor or defining your own custom extractor type and
70 /// adding the appropriate ContextType typedef to the class, you can pass a
71 /// context field during construction of the VarStreamArray that will be
72 /// passed to each call to extract.
73 ///
74 template
75 class VarStreamArrayIterator;
8476
8577 template
86 typename Extractor = VarStreamArrayExtractor>
87
78 typename ExtractorType = VarStreamArrayExtractor>
8879 class VarStreamArray {
89 friend class VarStreamArrayIterator;
90
9180 public:
92 typedef VarStreamArrayIterator Iterator;
81 typedef typename ExtractorType::ContextType ContextType;
82 typedef VarStreamArrayIterator Iterator;
83 friend Iterator;
9384
9485 VarStreamArray() = default;
95 explicit VarStreamArray(const Extractor &E) : E(E) {}
96
97 explicit VarStreamArray(BinaryStreamRef Stream) : Stream(Stream) {}
98 VarStreamArray(BinaryStreamRef Stream, const Extractor &E)
99 : Stream(Stream), E(E) {}
100
101 VarStreamArray(const VarStreamArray &Other)
102 : Stream(Other.Stream), E(Other.E) {}
86
87 explicit VarStreamArray(BinaryStreamRef Stream,
88 ContextType *Context = nullptr)
89 : Stream(Stream), Context(Context) {}
90
91 VarStreamArray(const VarStreamArray &Other)
92 : Stream(Other.Stream), Context(Other.Context) {}
10393
10494 Iterator begin(bool *HadError = nullptr) const {
105 return Iterator(*this, E, HadError);
106 }
107
108 Iterator end() const { return Iterator(E); }
109
110 const Extractor &getExtractor() const { return E; }
95 return Iterator(*this, Context, HadError);
96 }
97
98 Iterator end() const { return Iterator(); }
11199
112100 BinaryStreamRef getUnderlyingStream() const { return Stream; }
101 void setUnderlyingStream(BinaryStreamRef Stream) { this->Stream = Stream; }
113102
114103 private:
115104 BinaryStreamRef Stream;
116 Extractor E;
117 };
118
119 template
105 ContextType *Context = nullptr;
106 };
107
108 template
120109 class VarStreamArrayIterator
121 : public iterator_facade_base,
122 std::forward_iterator_tag, ValueType> {
123 typedef VarStreamArrayIterator IterType;
124 typedef VarStreamArray ArrayType;
110 : public iterator_facade_base<
111 VarStreamArrayIterator,
112 std::forward_iterator_tag, ValueType> {
113 typedef typename ExtractorType::ContextType ContextType;
114 typedef VarStreamArrayIterator IterType;
115 typedef VarStreamArray ArrayType;
125116
126117 public:
127 VarStreamArrayIterator(const ArrayType &Array, const Extractor &E,
118 VarStreamArrayIterator(const ArrayType &Array, ContextType *Context,
128119 bool *HadError = nullptr)
129 : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) {
120 : IterRef(Array.Stream), Context(Context), Array(&Array),
121 HadError(HadError) {
130122 if (IterRef.getLength() == 0)
131123 moveToEnd();
132124 else {
133 auto EC = Extract(IterRef, ThisLen, ThisValue);
125 auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context);
134126 if (EC) {
135127 consumeError(std::move(EC));
136128 markError();
138130 }
139131 }
140132 VarStreamArrayIterator() = default;
141 explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {}
142133 ~VarStreamArrayIterator() = default;
143134
144135 bool operator==(const IterType &R) const {
177168 moveToEnd();
178169 } else {
179170 // There is some data after the current record.
180 auto EC = Extract(IterRef, ThisLen, ThisValue);
171 auto EC = ExtractorType::extract(IterRef, ThisLen, ThisValue, Context);
181172 if (EC) {
182173 consumeError(std::move(EC));
183174 markError();
204195
205196 ValueType ThisValue;
206197 BinaryStreamRef IterRef;
198 ContextType *Context{nullptr};
207199 const ArrayType *Array{nullptr};
208200 uint32_t ThisLen{0};
209201 bool HasError{false};
210202 bool *HadError{nullptr};
211 Extractor Extract;
212203 };
213204
214205 template class FixedStreamArrayIterator;
171171 /// \returns a success error code if the data was successfully read, otherwise
172172 /// returns an appropriate error code.
173173 template
174 Error readArray(VarStreamArray &Array, uint32_t Size) {
174 Error
175 readArray(VarStreamArray &Array, uint32_t Size,
176 typename VarStreamArray::ContextType *Context = nullptr) {
175177 BinaryStreamRef S;
176178 if (auto EC = readStreamRef(S, Size))
177179 return EC;
178 Array = VarStreamArray(S, Array.getExtractor());
180 Array = VarStreamArray(S, Context);
179181 return Error::success();
180182 }
181183
6767 const LineFragmentHeader *Header;
6868 if (auto EC = Reader.readObject(Header))
6969 return EC;
70 VarStreamArrayExtractor E(Header);
71 LineInfoArray LineInfos(E);
72 if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining()))
70 LineInfoArray LineInfos;
71 if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining(), Header))
7372 return EC;
7473 return V.visitLines(R.getRecordData(), Header, LineInfos);
7574 }
357357
358358 struct StringExtractor {
359359 public:
360 Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) {
361 if (Index == 0)
360 typedef uint32_t ContextType;
361 static Error extract(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item,
362 uint32_t *Index) {
363 if (*Index == 0)
362364 Len = strlen("1. Test");
363 else if (Index == 1)
365 else if (*Index == 1)
364366 Len = strlen("2. Longer Test");
365 else if (Index == 2)
367 else if (*Index == 2)
366368 Len = strlen("3. Really Long Test");
367369 else
368370 Len = strlen("4. Super Extra Longest Test Of All");
371373 return EC;
372374 Item =
373375 StringRef(reinterpret_cast(Bytes.data()), Bytes.size());
374 ++Index;
376 ++(*Index);
375377 return Error::success();
376378 }
377
378 private:
379 uint32_t Index = 0;
380379 };
381380
382381 for (auto &Stream : Streams) {
383 VarStreamArray Array(*Stream.Input);
382 uint32_t Context = 0;
383 VarStreamArray Array(*Stream.Input, &Context);
384384 auto Iter = Array.begin();
385385 ASSERT_EQ("1. Test", *Iter++);
386386 ASSERT_EQ("2. Longer Test", *Iter++);