Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- C++-*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_SUPPORT_BINARYSTREAMWRITER_H
  10. #define LLVM_SUPPORT_BINARYSTREAMWRITER_H
  11.  
  12. #include "llvm/ADT/ArrayRef.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/Support/BinaryStreamArray.h"
  15. #include "llvm/Support/BinaryStreamError.h"
  16. #include "llvm/Support/BinaryStreamRef.h"
  17. #include "llvm/Support/Endian.h"
  18. #include "llvm/Support/Error.h"
  19. #include <cstdint>
  20. #include <type_traits>
  21. #include <utility>
  22.  
  23. namespace llvm {
  24.  
  25. /// Provides write only access to a subclass of `WritableBinaryStream`.
  26. /// Provides bounds checking and helpers for writing certain common data types
  27. /// such as null-terminated strings, integers in various flavors of endianness,
  28. /// etc.  Can be subclassed to provide reading and writing of custom datatypes,
  29. /// although no methods are overridable.
  30. class BinaryStreamWriter {
  31. public:
  32.   BinaryStreamWriter() = default;
  33.   explicit BinaryStreamWriter(WritableBinaryStreamRef Ref);
  34.   explicit BinaryStreamWriter(WritableBinaryStream &Stream);
  35.   explicit BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
  36.                               llvm::support::endianness Endian);
  37.  
  38.   BinaryStreamWriter(const BinaryStreamWriter &Other) = default;
  39.  
  40.   BinaryStreamWriter &operator=(const BinaryStreamWriter &Other) = default;
  41.  
  42.   virtual ~BinaryStreamWriter() = default;
  43.  
  44.   /// Write the bytes specified in \p Buffer to the underlying stream.
  45.   /// On success, updates the offset so that subsequent writes will occur
  46.   /// at the next unwritten position.
  47.   ///
  48.   /// \returns a success error code if the data was successfully written,
  49.   /// otherwise returns an appropriate error code.
  50.   Error writeBytes(ArrayRef<uint8_t> Buffer);
  51.  
  52.   /// Write the integer \p Value to the underlying stream in the
  53.   /// specified endianness.  On success, updates the offset so that
  54.   /// subsequent writes occur at the next unwritten position.
  55.   ///
  56.   /// \returns a success error code if the data was successfully written,
  57.   /// otherwise returns an appropriate error code.
  58.   template <typename T> Error writeInteger(T Value) {
  59.     static_assert(std::is_integral_v<T>,
  60.                   "Cannot call writeInteger with non-integral value!");
  61.     uint8_t Buffer[sizeof(T)];
  62.     llvm::support::endian::write<T, llvm::support::unaligned>(
  63.         Buffer, Value, Stream.getEndian());
  64.     return writeBytes(Buffer);
  65.   }
  66.  
  67.   /// Similar to writeInteger
  68.   template <typename T> Error writeEnum(T Num) {
  69.     static_assert(std::is_enum<T>::value,
  70.                   "Cannot call writeEnum with non-Enum type");
  71.  
  72.     using U = std::underlying_type_t<T>;
  73.     return writeInteger<U>(static_cast<U>(Num));
  74.   }
  75.  
  76.   /// Write the unsigned integer Value to the underlying stream using ULEB128
  77.   /// encoding.
  78.   ///
  79.   /// \returns a success error code if the data was successfully written,
  80.   /// otherwise returns an appropriate error code.
  81.   Error writeULEB128(uint64_t Value);
  82.  
  83.   /// Write the unsigned integer Value to the underlying stream using ULEB128
  84.   /// encoding.
  85.   ///
  86.   /// \returns a success error code if the data was successfully written,
  87.   /// otherwise returns an appropriate error code.
  88.   Error writeSLEB128(int64_t Value);
  89.  
  90.   /// Write the string \p Str to the underlying stream followed by a null
  91.   /// terminator.  On success, updates the offset so that subsequent writes
  92.   /// occur at the next unwritten position.  \p Str need not be null terminated
  93.   /// on input.
  94.   ///
  95.   /// \returns a success error code if the data was successfully written,
  96.   /// otherwise returns an appropriate error code.
  97.   Error writeCString(StringRef Str);
  98.  
  99.   /// Write the string \p Str to the underlying stream without a null
  100.   /// terminator.  On success, updates the offset so that subsequent writes
  101.   /// occur at the next unwritten position.
  102.   ///
  103.   /// \returns a success error code if the data was successfully written,
  104.   /// otherwise returns an appropriate error code.
  105.   Error writeFixedString(StringRef Str);
  106.  
  107.   /// Efficiently reads all data from \p Ref, and writes it to this stream.
  108.   /// This operation will not invoke any copies of the source data, regardless
  109.   /// of the source stream's implementation.
  110.   ///
  111.   /// \returns a success error code if the data was successfully written,
  112.   /// otherwise returns an appropriate error code.
  113.   Error writeStreamRef(BinaryStreamRef Ref);
  114.  
  115.   /// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
  116.   /// This operation will not invoke any copies of the source data, regardless
  117.   /// of the source stream's implementation.
  118.   ///
  119.   /// \returns a success error code if the data was successfully written,
  120.   /// otherwise returns an appropriate error code.
  121.   Error writeStreamRef(BinaryStreamRef Ref, uint64_t Size);
  122.  
  123.   /// Writes the object \p Obj to the underlying stream, as if by using memcpy.
  124.   /// It is up to the caller to ensure that type of \p Obj can be safely copied
  125.   /// in this fashion, as no checks are made to ensure that this is safe.
  126.   ///
  127.   /// \returns a success error code if the data was successfully written,
  128.   /// otherwise returns an appropriate error code.
  129.   template <typename T> Error writeObject(const T &Obj) {
  130.     static_assert(!std::is_pointer<T>::value,
  131.                   "writeObject should not be used with pointers, to write "
  132.                   "the pointed-to value dereference the pointer before calling "
  133.                   "writeObject");
  134.     return writeBytes(
  135.         ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
  136.   }
  137.  
  138.   /// Writes an array of objects of type T to the underlying stream, as if by
  139.   /// using memcpy.  It is up to the caller to ensure that type of \p Obj can
  140.   /// be safely copied in this fashion, as no checks are made to ensure that
  141.   /// this is safe.
  142.   ///
  143.   /// \returns a success error code if the data was successfully written,
  144.   /// otherwise returns an appropriate error code.
  145.   template <typename T> Error writeArray(ArrayRef<T> Array) {
  146.     if (Array.empty())
  147.       return Error::success();
  148.     if (Array.size() > UINT32_MAX / sizeof(T))
  149.       return make_error<BinaryStreamError>(
  150.           stream_error_code::invalid_array_size);
  151.  
  152.     return writeBytes(
  153.         ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
  154.                           Array.size() * sizeof(T)));
  155.   }
  156.  
  157.   /// Writes all data from the array \p Array to the underlying stream.
  158.   ///
  159.   /// \returns a success error code if the data was successfully written,
  160.   /// otherwise returns an appropriate error code.
  161.   template <typename T, typename U>
  162.   Error writeArray(VarStreamArray<T, U> Array) {
  163.     return writeStreamRef(Array.getUnderlyingStream());
  164.   }
  165.  
  166.   /// Writes all elements from the array \p Array to the underlying stream.
  167.   ///
  168.   /// \returns a success error code if the data was successfully written,
  169.   /// otherwise returns an appropriate error code.
  170.   template <typename T> Error writeArray(FixedStreamArray<T> Array) {
  171.     return writeStreamRef(Array.getUnderlyingStream());
  172.   }
  173.  
  174.   /// Splits the Writer into two Writers at a given offset.
  175.   std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint64_t Off) const;
  176.  
  177.   void setOffset(uint64_t Off) { Offset = Off; }
  178.   uint64_t getOffset() const { return Offset; }
  179.   uint64_t getLength() const { return Stream.getLength(); }
  180.   uint64_t bytesRemaining() const { return getLength() - getOffset(); }
  181.   Error padToAlignment(uint32_t Align);
  182.  
  183. protected:
  184.   WritableBinaryStreamRef Stream;
  185.   uint64_t Offset = 0;
  186. };
  187.  
  188. } // end namespace llvm
  189.  
  190. #endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H
  191.