File indexing completed on 2026-05-10 08:44:28
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_SUPPORT_BINARYSTREAMREF_H
0010 #define LLVM_SUPPORT_BINARYSTREAMREF_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/Support/BinaryStream.h"
0014 #include "llvm/Support/BinaryStreamError.h"
0015 #include "llvm/Support/Error.h"
0016 #include <cstdint>
0017 #include <memory>
0018 #include <optional>
0019
0020 namespace llvm {
0021
0022
0023 template <class RefType, class StreamType> class BinaryStreamRefBase {
0024 protected:
0025 BinaryStreamRefBase() = default;
0026 explicit BinaryStreamRefBase(StreamType &BorrowedImpl)
0027 : BorrowedImpl(&BorrowedImpl), ViewOffset(0) {
0028 if (!(BorrowedImpl.getFlags() & BSF_Append))
0029 Length = BorrowedImpl.getLength();
0030 }
0031
0032 BinaryStreamRefBase(std::shared_ptr<StreamType> SharedImpl, uint64_t Offset,
0033 std::optional<uint64_t> Length)
0034 : SharedImpl(SharedImpl), BorrowedImpl(SharedImpl.get()),
0035 ViewOffset(Offset), Length(Length) {}
0036 BinaryStreamRefBase(StreamType &BorrowedImpl, uint64_t Offset,
0037 std::optional<uint64_t> Length)
0038 : BorrowedImpl(&BorrowedImpl), ViewOffset(Offset), Length(Length) {}
0039 BinaryStreamRefBase(const BinaryStreamRefBase &Other) = default;
0040 BinaryStreamRefBase &operator=(const BinaryStreamRefBase &Other) = default;
0041
0042 BinaryStreamRefBase &operator=(BinaryStreamRefBase &&Other) = default;
0043 BinaryStreamRefBase(BinaryStreamRefBase &&Other) = default;
0044
0045 public:
0046 llvm::endianness getEndian() const { return BorrowedImpl->getEndian(); }
0047
0048 uint64_t getLength() const {
0049 if (Length)
0050 return *Length;
0051
0052 return BorrowedImpl ? (BorrowedImpl->getLength() - ViewOffset) : 0;
0053 }
0054
0055
0056
0057
0058 RefType drop_front(uint64_t N) const {
0059 if (!BorrowedImpl)
0060 return RefType();
0061
0062 N = std::min(N, getLength());
0063 RefType Result(static_cast<const RefType &>(*this));
0064 if (N == 0)
0065 return Result;
0066
0067 Result.ViewOffset += N;
0068 if (Result.Length)
0069 *Result.Length -= N;
0070 return Result;
0071 }
0072
0073
0074
0075
0076 RefType drop_back(uint64_t N) const {
0077 if (!BorrowedImpl)
0078 return RefType();
0079
0080 RefType Result(static_cast<const RefType &>(*this));
0081 N = std::min(N, getLength());
0082
0083 if (N == 0)
0084 return Result;
0085
0086
0087
0088 if (!Result.Length)
0089 Result.Length = getLength();
0090
0091 *Result.Length -= N;
0092 return Result;
0093 }
0094
0095
0096 RefType keep_front(uint64_t N) const {
0097 assert(N <= getLength());
0098 return drop_back(getLength() - N);
0099 }
0100
0101
0102 RefType keep_back(uint64_t N) const {
0103 assert(N <= getLength());
0104 return drop_front(getLength() - N);
0105 }
0106
0107
0108
0109 RefType drop_symmetric(uint64_t N) const {
0110 return drop_front(N).drop_back(N);
0111 }
0112
0113
0114
0115 RefType slice(uint64_t Offset, uint64_t Len) const {
0116 return drop_front(Offset).keep_front(Len);
0117 }
0118
0119 bool valid() const { return BorrowedImpl != nullptr; }
0120
0121 friend bool operator==(const RefType &LHS, const RefType &RHS) {
0122 if (LHS.BorrowedImpl != RHS.BorrowedImpl)
0123 return false;
0124 if (LHS.ViewOffset != RHS.ViewOffset)
0125 return false;
0126 if (LHS.Length != RHS.Length)
0127 return false;
0128 return true;
0129 }
0130
0131 protected:
0132 Error checkOffsetForRead(uint64_t Offset, uint64_t DataSize) const {
0133 if (Offset > getLength())
0134 return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
0135 if (getLength() < DataSize + Offset)
0136 return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
0137 return Error::success();
0138 }
0139
0140 std::shared_ptr<StreamType> SharedImpl;
0141 StreamType *BorrowedImpl = nullptr;
0142 uint64_t ViewOffset = 0;
0143 std::optional<uint64_t> Length;
0144 };
0145
0146
0147
0148
0149
0150
0151
0152
0153 class BinaryStreamRef
0154 : public BinaryStreamRefBase<BinaryStreamRef, BinaryStream> {
0155 friend BinaryStreamRefBase<BinaryStreamRef, BinaryStream>;
0156 friend class WritableBinaryStreamRef;
0157 BinaryStreamRef(std::shared_ptr<BinaryStream> Impl, uint64_t ViewOffset,
0158 std::optional<uint64_t> Length)
0159 : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
0160
0161 public:
0162 BinaryStreamRef() = default;
0163 BinaryStreamRef(BinaryStream &Stream);
0164 BinaryStreamRef(BinaryStream &Stream, uint64_t Offset,
0165 std::optional<uint64_t> Length);
0166 explicit BinaryStreamRef(ArrayRef<uint8_t> Data, llvm::endianness Endian);
0167 explicit BinaryStreamRef(StringRef Data, llvm::endianness Endian);
0168
0169 BinaryStreamRef(const BinaryStreamRef &Other) = default;
0170 BinaryStreamRef &operator=(const BinaryStreamRef &Other) = default;
0171 BinaryStreamRef(BinaryStreamRef &&Other) = default;
0172 BinaryStreamRef &operator=(BinaryStreamRef &&Other) = default;
0173
0174
0175 BinaryStreamRef(BinaryStreamRef &S, uint64_t Offset,
0176 uint64_t Length) = delete;
0177
0178
0179
0180
0181
0182
0183
0184 Error readBytes(uint64_t Offset, uint64_t Size,
0185 ArrayRef<uint8_t> &Buffer) const;
0186
0187
0188
0189
0190
0191
0192 Error readLongestContiguousChunk(uint64_t Offset,
0193 ArrayRef<uint8_t> &Buffer) const;
0194 };
0195
0196 struct BinarySubstreamRef {
0197 uint64_t Offset = 0;
0198 BinaryStreamRef StreamData;
0199
0200 BinarySubstreamRef slice(uint64_t Off, uint64_t Size) const {
0201 BinaryStreamRef SubSub = StreamData.slice(Off, Size);
0202 return {Off + Offset, SubSub};
0203 }
0204 BinarySubstreamRef drop_front(uint64_t N) const {
0205 return slice(N, size() - N);
0206 }
0207 BinarySubstreamRef keep_front(uint64_t N) const { return slice(0, N); }
0208
0209 std::pair<BinarySubstreamRef, BinarySubstreamRef> split(uint64_t Off) const {
0210 return std::make_pair(keep_front(Off), drop_front(Off));
0211 }
0212
0213 uint64_t size() const { return StreamData.getLength(); }
0214 bool empty() const { return size() == 0; }
0215 };
0216
0217 class WritableBinaryStreamRef
0218 : public BinaryStreamRefBase<WritableBinaryStreamRef,
0219 WritableBinaryStream> {
0220 friend BinaryStreamRefBase<WritableBinaryStreamRef, WritableBinaryStream>;
0221 WritableBinaryStreamRef(std::shared_ptr<WritableBinaryStream> Impl,
0222 uint64_t ViewOffset, std::optional<uint64_t> Length)
0223 : BinaryStreamRefBase(Impl, ViewOffset, Length) {}
0224
0225 Error checkOffsetForWrite(uint64_t Offset, uint64_t DataSize) const {
0226 if (!(BorrowedImpl->getFlags() & BSF_Append))
0227 return checkOffsetForRead(Offset, DataSize);
0228
0229 if (Offset > getLength())
0230 return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
0231 return Error::success();
0232 }
0233
0234 public:
0235 WritableBinaryStreamRef() = default;
0236 WritableBinaryStreamRef(WritableBinaryStream &Stream);
0237 WritableBinaryStreamRef(WritableBinaryStream &Stream, uint64_t Offset,
0238 std::optional<uint64_t> Length);
0239 explicit WritableBinaryStreamRef(MutableArrayRef<uint8_t> Data,
0240 llvm::endianness Endian);
0241 WritableBinaryStreamRef(const WritableBinaryStreamRef &Other) = default;
0242 WritableBinaryStreamRef &
0243 operator=(const WritableBinaryStreamRef &Other) = default;
0244
0245 WritableBinaryStreamRef(WritableBinaryStreamRef &&Other) = default;
0246 WritableBinaryStreamRef &operator=(WritableBinaryStreamRef &&Other) = default;
0247
0248
0249 WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint64_t Offset,
0250 uint64_t Length) = delete;
0251
0252
0253
0254
0255
0256
0257
0258 Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Data) const;
0259
0260
0261 operator BinaryStreamRef() const;
0262
0263
0264 Error commit();
0265 };
0266
0267 }
0268
0269 #endif