Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:28

0001 //===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- C++-*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_SUPPORT_BINARYSTREAMWRITER_H
0010 #define LLVM_SUPPORT_BINARYSTREAMWRITER_H
0011 
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/Support/BinaryStreamArray.h"
0015 #include "llvm/Support/BinaryStreamError.h"
0016 #include "llvm/Support/BinaryStreamRef.h"
0017 #include "llvm/Support/Endian.h"
0018 #include "llvm/Support/Error.h"
0019 #include <cstdint>
0020 #include <type_traits>
0021 #include <utility>
0022 
0023 namespace llvm {
0024 
0025 /// Provides write only access to a subclass of `WritableBinaryStream`.
0026 /// Provides bounds checking and helpers for writing certain common data types
0027 /// such as null-terminated strings, integers in various flavors of endianness,
0028 /// etc.  Can be subclassed to provide reading and writing of custom datatypes,
0029 /// although no methods are overridable.
0030 class BinaryStreamWriter {
0031 public:
0032   BinaryStreamWriter() = default;
0033   explicit BinaryStreamWriter(WritableBinaryStreamRef Ref);
0034   explicit BinaryStreamWriter(WritableBinaryStream &Stream);
0035   explicit BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
0036                               llvm::endianness Endian);
0037 
0038   BinaryStreamWriter(const BinaryStreamWriter &Other) = default;
0039 
0040   BinaryStreamWriter &operator=(const BinaryStreamWriter &Other) = default;
0041 
0042   virtual ~BinaryStreamWriter() = default;
0043 
0044   /// Write the bytes specified in \p Buffer to the underlying stream.
0045   /// On success, updates the offset so that subsequent writes will occur
0046   /// at the next unwritten position.
0047   ///
0048   /// \returns a success error code if the data was successfully written,
0049   /// otherwise returns an appropriate error code.
0050   Error writeBytes(ArrayRef<uint8_t> Buffer);
0051 
0052   /// Write the integer \p Value to the underlying stream in the
0053   /// specified endianness.  On success, updates the offset so that
0054   /// subsequent writes occur at the next unwritten position.
0055   ///
0056   /// \returns a success error code if the data was successfully written,
0057   /// otherwise returns an appropriate error code.
0058   template <typename T> Error writeInteger(T Value) {
0059     static_assert(std::is_integral_v<T>,
0060                   "Cannot call writeInteger with non-integral value!");
0061     uint8_t Buffer[sizeof(T)];
0062     llvm::support::endian::write<T>(Buffer, Value, Stream.getEndian());
0063     return writeBytes(Buffer);
0064   }
0065 
0066   /// Similar to writeInteger
0067   template <typename T> Error writeEnum(T Num) {
0068     static_assert(std::is_enum<T>::value,
0069                   "Cannot call writeEnum with non-Enum type");
0070 
0071     using U = std::underlying_type_t<T>;
0072     return writeInteger<U>(static_cast<U>(Num));
0073   }
0074 
0075   /// Write the unsigned integer Value to the underlying stream using ULEB128
0076   /// encoding.
0077   ///
0078   /// \returns a success error code if the data was successfully written,
0079   /// otherwise returns an appropriate error code.
0080   Error writeULEB128(uint64_t Value);
0081 
0082   /// Write the unsigned integer Value to the underlying stream using ULEB128
0083   /// encoding.
0084   ///
0085   /// \returns a success error code if the data was successfully written,
0086   /// otherwise returns an appropriate error code.
0087   Error writeSLEB128(int64_t Value);
0088 
0089   /// Write the string \p Str to the underlying stream followed by a null
0090   /// terminator.  On success, updates the offset so that subsequent writes
0091   /// occur at the next unwritten position.  \p Str need not be null terminated
0092   /// on input.
0093   ///
0094   /// \returns a success error code if the data was successfully written,
0095   /// otherwise returns an appropriate error code.
0096   Error writeCString(StringRef Str);
0097 
0098   /// Write the string \p Str to the underlying stream without a null
0099   /// terminator.  On success, updates the offset so that subsequent writes
0100   /// occur at the next unwritten position.
0101   ///
0102   /// \returns a success error code if the data was successfully written,
0103   /// otherwise returns an appropriate error code.
0104   Error writeFixedString(StringRef Str);
0105 
0106   /// Efficiently reads all data from \p Ref, and writes it to this stream.
0107   /// This operation will not invoke any copies of the source data, regardless
0108   /// of the source stream's implementation.
0109   ///
0110   /// \returns a success error code if the data was successfully written,
0111   /// otherwise returns an appropriate error code.
0112   Error writeStreamRef(BinaryStreamRef Ref);
0113 
0114   /// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
0115   /// This operation will not invoke any copies of the source data, regardless
0116   /// of the source stream's implementation.
0117   ///
0118   /// \returns a success error code if the data was successfully written,
0119   /// otherwise returns an appropriate error code.
0120   Error writeStreamRef(BinaryStreamRef Ref, uint64_t Size);
0121 
0122   /// Writes the object \p Obj to the underlying stream, as if by using memcpy.
0123   /// It is up to the caller to ensure that type of \p Obj can be safely copied
0124   /// in this fashion, as no checks are made to ensure that this is safe.
0125   ///
0126   /// \returns a success error code if the data was successfully written,
0127   /// otherwise returns an appropriate error code.
0128   template <typename T> Error writeObject(const T &Obj) {
0129     static_assert(!std::is_pointer<T>::value,
0130                   "writeObject should not be used with pointers, to write "
0131                   "the pointed-to value dereference the pointer before calling "
0132                   "writeObject");
0133     return writeBytes(
0134         ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
0135   }
0136 
0137   /// Writes an array of objects of type T to the underlying stream, as if by
0138   /// using memcpy.  It is up to the caller to ensure that type of \p Obj can
0139   /// be safely copied in this fashion, as no checks are made to ensure that
0140   /// this is safe.
0141   ///
0142   /// \returns a success error code if the data was successfully written,
0143   /// otherwise returns an appropriate error code.
0144   template <typename T> Error writeArray(ArrayRef<T> Array) {
0145     if (Array.empty())
0146       return Error::success();
0147     if (Array.size() > UINT32_MAX / sizeof(T))
0148       return make_error<BinaryStreamError>(
0149           stream_error_code::invalid_array_size);
0150 
0151     return writeBytes(
0152         ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
0153                           Array.size() * sizeof(T)));
0154   }
0155 
0156   /// Writes all data from the array \p Array to the underlying stream.
0157   ///
0158   /// \returns a success error code if the data was successfully written,
0159   /// otherwise returns an appropriate error code.
0160   template <typename T, typename U>
0161   Error writeArray(VarStreamArray<T, U> Array) {
0162     return writeStreamRef(Array.getUnderlyingStream());
0163   }
0164 
0165   /// Writes all elements from the array \p Array to the underlying stream.
0166   ///
0167   /// \returns a success error code if the data was successfully written,
0168   /// otherwise returns an appropriate error code.
0169   template <typename T> Error writeArray(FixedStreamArray<T> Array) {
0170     return writeStreamRef(Array.getUnderlyingStream());
0171   }
0172 
0173   /// Splits the Writer into two Writers at a given offset.
0174   std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint64_t Off) const;
0175 
0176   void setOffset(uint64_t Off) { Offset = Off; }
0177   uint64_t getOffset() const { return Offset; }
0178   uint64_t getLength() const { return Stream.getLength(); }
0179   uint64_t bytesRemaining() const { return getLength() - getOffset(); }
0180   Error padToAlignment(uint32_t Align);
0181 
0182 protected:
0183   WritableBinaryStreamRef Stream;
0184   uint64_t Offset = 0;
0185 };
0186 
0187 } // end namespace llvm
0188 
0189 #endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H