[llvm] r301556 - [Support] Make BinaryStreamArray extractors stateless.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 27 09:11:48 PDT 2017


Author: zturner
Date: Thu Apr 27 11:11:47 2017
New Revision: 301556

URL: http://llvm.org/viewvc/llvm-project?rev=301556&view=rev
Log:
[Support] Make BinaryStreamArray extractors stateless.

Instead, we now pass a context memeber through the extraction
process.

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
    llvm/trunk/include/llvm/Support/BinaryStreamArray.h
    llvm/trunk/include/llvm/Support/BinaryStreamReader.h
    llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp
    llvm/trunk/unittests/Support/BinaryStreamTest.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h Thu Apr 27 11:11:47 2017
@@ -50,8 +50,10 @@ public:
 
 template <typename Kind>
 struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
-  Error operator()(BinaryStreamRef Stream, uint32_t &Len,
-                   codeview::CVRecord<Kind> &Item) const {
+  typedef void ContextType;
+
+  static Error extract(BinaryStreamRef Stream, uint32_t &Len,
+                       codeview::CVRecord<Kind> &Item, void *Ctx) {
     using namespace codeview;
     const RecordPrefix *Prefix = nullptr;
     BinaryStreamReader Reader(Stream);

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h Thu Apr 27 11:11:47 2017
@@ -74,8 +74,10 @@ typedef VarStreamArray<ModuleDebugFragme
 } // namespace codeview
 
 template <> struct VarStreamArrayExtractor<codeview::ModuleDebugFragment> {
-  Error operator()(BinaryStreamRef Stream, uint32_t &Length,
-                   codeview::ModuleDebugFragment &Info) const {
+  typedef void ContextType;
+
+  static Error extract(BinaryStreamRef Stream, uint32_t &Length,
+                       codeview::ModuleDebugFragment &Info, void *Ctx) {
     if (auto EC = codeview::ModuleDebugFragment::initialize(Stream, Info))
       return EC;
     Length = Info.getRecordLength();

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h Thu Apr 27 11:11:47 2017
@@ -71,11 +71,10 @@ Error visitModuleDebugFragment(const Mod
 
 template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> {
 public:
-  VarStreamArrayExtractor(const codeview::LineFragmentHeader *Header)
-      : Header(Header) {}
+  typedef const codeview::LineFragmentHeader ContextType;
 
-  Error operator()(BinaryStreamRef Stream, uint32_t &Len,
-                   codeview::LineColumnEntry &Item) const {
+  static Error extract(BinaryStreamRef Stream, uint32_t &Len,
+                       codeview::LineColumnEntry &Item, ContextType *Header) {
     using namespace codeview;
     const LineBlockFragmentHeader *BlockHeader;
     BinaryStreamReader Reader(Stream);
@@ -104,15 +103,14 @@ public:
     }
     return Error::success();
   }
-
-private:
-  const codeview::LineFragmentHeader *Header;
 };
 
 template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> {
 public:
-  Error operator()(BinaryStreamRef Stream, uint32_t &Len,
-                   codeview::FileChecksumEntry &Item) const {
+  typedef void ContextType;
+
+  static Error extract(BinaryStreamRef Stream, uint32_t &Len,
+                       codeview::FileChecksumEntry &Item, void *Ctx) {
     using namespace codeview;
     const FileChecksum *Header;
     BinaryStreamReader Reader(Stream);

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h Thu Apr 27 11:11:47 2017
@@ -64,8 +64,9 @@ struct ModuleInfoEx {
 } // end namespace pdb
 
 template <> struct VarStreamArrayExtractor<pdb::DbiModuleDescriptor> {
-  Error operator()(BinaryStreamRef Stream, uint32_t &Length,
-                   pdb::DbiModuleDescriptor &Info) const {
+  typedef void ContextType;
+  static Error extract(BinaryStreamRef Stream, uint32_t &Length,
+                       pdb::DbiModuleDescriptor &Info, void *Ctx) {
     if (auto EC = pdb::DbiModuleDescriptor::initialize(Stream, Info))
       return EC;
     Length = Info.getRecordLength();

Modified: llvm/trunk/include/llvm/Support/BinaryStreamArray.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/BinaryStreamArray.h?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/BinaryStreamArray.h (original)
+++ llvm/trunk/include/llvm/Support/BinaryStreamArray.h Thu Apr 27 11:11:47 2017
@@ -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,74 +66,64 @@ template <typename T> struct VarStreamAr
 /// 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);
+    return Iterator(*this, Context, HadError);
   }
 
-  Iterator end() const { return Iterator(E); }
-
-  const Extractor &getExtractor() const { return E; }
+  Iterator end() const { return Iterator(); }
 
   BinaryStreamRef getUnderlyingStream() const { return Stream; }
+  void setUnderlyingStream(BinaryStreamRef Stream) { this->Stream = 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,
+  VarStreamArrayIterator(const ArrayType &Array, ContextType *Context,
                          bool *HadError = nullptr)
-      : IterRef(Array.Stream), Array(&Array), HadError(HadError), Extract(E) {
+      : IterRef(Array.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();
@@ -139,7 +131,6 @@ public:
     }
   }
   VarStreamArrayIterator() = default;
-  explicit VarStreamArrayIterator(const Extractor &E) : Extract(E) {}
   ~VarStreamArrayIterator() = default;
 
   bool operator==(const IterType &R) const {
@@ -178,7 +169,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 +196,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;

Modified: llvm/trunk/include/llvm/Support/BinaryStreamReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/BinaryStreamReader.h?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/BinaryStreamReader.h (original)
+++ llvm/trunk/include/llvm/Support/BinaryStreamReader.h Thu Apr 27 11:11:47 2017
@@ -172,11 +172,13 @@ public:
   /// \returns a success error code if the data was successfully read, otherwise
   /// returns an appropriate error code.
   template <typename T, typename U>
-  Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
+  Error
+  readArray(VarStreamArray<T, U> &Array, uint32_t Size,
+            typename VarStreamArray<T, U>::ContextType *Context = nullptr) {
     BinaryStreamRef S;
     if (auto EC = readStreamRef(S, Size))
       return EC;
-    Array = VarStreamArray<T, U>(S, Array.getExtractor());
+    Array = VarStreamArray<T, U>(S, Context);
     return Error::success();
   }
 

Modified: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp Thu Apr 27 11:11:47 2017
@@ -68,9 +68,8 @@ Error llvm::codeview::visitModuleDebugFr
     const LineFragmentHeader *Header;
     if (auto EC = Reader.readObject(Header))
       return EC;
-    VarStreamArrayExtractor<LineColumnEntry> E(Header);
-    LineInfoArray LineInfos(E);
-    if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining()))
+    LineInfoArray LineInfos;
+    if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining(), Header))
       return EC;
     return V.visitLines(R.getRecordData(), Header, LineInfos);
   }

Modified: llvm/trunk/unittests/Support/BinaryStreamTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/BinaryStreamTest.cpp?rev=301556&r1=301555&r2=301556&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/BinaryStreamTest.cpp (original)
+++ llvm/trunk/unittests/Support/BinaryStreamTest.cpp Thu Apr 27 11:11:47 2017
@@ -358,12 +358,14 @@ TEST_F(BinaryStreamTest, VarStreamArray)
 
   struct StringExtractor {
   public:
-    Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) {
-      if (Index == 0)
+    typedef uint32_t ContextType;
+    static Error extract(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item,
+                         uint32_t *Index) {
+      if (*Index == 0)
         Len = strlen("1. Test");
-      else if (Index == 1)
+      else if (*Index == 1)
         Len = strlen("2. Longer Test");
-      else if (Index == 2)
+      else if (*Index == 2)
         Len = strlen("3. Really Long Test");
       else
         Len = strlen("4. Super Extra Longest Test Of All");
@@ -372,16 +374,14 @@ TEST_F(BinaryStreamTest, VarStreamArray)
         return EC;
       Item =
           StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
-      ++Index;
+      ++(*Index);
       return Error::success();
     }
-
-  private:
-    uint32_t Index = 0;
   };
 
   for (auto &Stream : Streams) {
-    VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input);
+    uint32_t Context = 0;
+    VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input, &Context);
     auto Iter = Array.begin();
     ASSERT_EQ("1. Test", *Iter++);
     ASSERT_EQ("2. Longer Test", *Iter++);




More information about the llvm-commits mailing list