1 //===- StreamRef.h - A copyable reference to a stream -----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H 11 #define LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H 12 13 #include "llvm/DebugInfo/CodeView/CodeViewError.h" 14 #include "llvm/DebugInfo/CodeView/StreamInterface.h" 15 16 namespace llvm { 17 namespace codeview { 18 19 class StreamRef { 20 public: StreamRef()21 StreamRef() : Stream(nullptr), ViewOffset(0), Length(0) {} StreamRef(const StreamInterface & Stream)22 StreamRef(const StreamInterface &Stream) 23 : Stream(&Stream), ViewOffset(0), Length(Stream.getLength()) {} StreamRef(const StreamInterface & Stream,uint32_t Offset,uint32_t Length)24 StreamRef(const StreamInterface &Stream, uint32_t Offset, uint32_t Length) 25 : Stream(&Stream), ViewOffset(Offset), Length(Length) {} 26 27 // Use StreamRef.slice() instead. 28 StreamRef(const StreamRef &S, uint32_t Offset, uint32_t Length) = delete; 29 readBytes(uint32_t Offset,uint32_t Size,ArrayRef<uint8_t> & Buffer)30 Error readBytes(uint32_t Offset, uint32_t Size, 31 ArrayRef<uint8_t> &Buffer) const { 32 if (ViewOffset + Offset < Offset) 33 return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 34 if (Size + Offset > Length) 35 return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 36 return Stream->readBytes(ViewOffset + Offset, Size, Buffer); 37 } 38 39 // Given an offset into the stream, read as much as possible without copying 40 // any data. readLongestContiguousChunk(uint32_t Offset,ArrayRef<uint8_t> & Buffer)41 Error readLongestContiguousChunk(uint32_t Offset, 42 ArrayRef<uint8_t> &Buffer) const { 43 if (Offset >= Length) 44 return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 45 46 if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer)) 47 return EC; 48 // This StreamRef might refer to a smaller window over a larger stream. In 49 // that case we will have read out more bytes than we should return, because 50 // we should not read past the end of the current view. 51 uint32_t MaxLength = Length - Offset; 52 if (Buffer.size() > MaxLength) 53 Buffer = Buffer.slice(0, MaxLength); 54 return Error::success(); 55 } 56 writeBytes(uint32_t Offset,ArrayRef<uint8_t> Data)57 Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const { 58 if (Data.size() + Offset > Length) 59 return make_error<CodeViewError>(cv_error_code::insufficient_buffer); 60 return Stream->writeBytes(ViewOffset + Offset, Data); 61 } 62 getLength()63 uint32_t getLength() const { return Length; } 64 commit()65 Error commit() const { return Stream->commit(); } 66 drop_front(uint32_t N)67 StreamRef drop_front(uint32_t N) const { 68 if (!Stream) 69 return StreamRef(); 70 71 N = std::min(N, Length); 72 return StreamRef(*Stream, ViewOffset + N, Length - N); 73 } 74 keep_front(uint32_t N)75 StreamRef keep_front(uint32_t N) const { 76 if (!Stream) 77 return StreamRef(); 78 N = std::min(N, Length); 79 return StreamRef(*Stream, ViewOffset, N); 80 } 81 slice(uint32_t Offset,uint32_t Len)82 StreamRef slice(uint32_t Offset, uint32_t Len) const { 83 return drop_front(Offset).keep_front(Len); 84 } 85 86 bool operator==(const StreamRef &Other) const { 87 if (Stream != Other.Stream) 88 return false; 89 if (ViewOffset != Other.ViewOffset) 90 return false; 91 if (Length != Other.Length) 92 return false; 93 return true; 94 } 95 96 private: 97 const StreamInterface *Stream; 98 uint32_t ViewOffset; 99 uint32_t Length; 100 }; 101 } 102 } 103 104 #endif // LLVM_DEBUGINFO_CODEVIEW_STREAMREF_H 105