BinaryStreamWriter.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. //===- BinaryStreamWriter.cpp - Writes objects to a BinaryStream ----------===//
  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. #include "llvm/Support/BinaryStreamWriter.h"
  9. #include "llvm/Support/BinaryStreamReader.h"
  10. #include "llvm/Support/BinaryStreamRef.h"
  11. #include "llvm/Support/LEB128.h"
  12. using namespace llvm;
  13. BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef Ref)
  14. : Stream(Ref) {}
  15. BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStream &Stream)
  16. : Stream(Stream) {}
  17. BinaryStreamWriter::BinaryStreamWriter(MutableArrayRef<uint8_t> Data,
  18. llvm::support::endianness Endian)
  19. : Stream(Data, Endian) {}
  20. Error BinaryStreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
  21. if (auto EC = Stream.writeBytes(Offset, Buffer))
  22. return EC;
  23. Offset += Buffer.size();
  24. return Error::success();
  25. }
  26. Error BinaryStreamWriter::writeULEB128(uint64_t Value) {
  27. uint8_t EncodedBytes[10] = {0};
  28. unsigned Size = encodeULEB128(Value, &EncodedBytes[0]);
  29. return writeBytes({EncodedBytes, Size});
  30. }
  31. Error BinaryStreamWriter::writeSLEB128(int64_t Value) {
  32. uint8_t EncodedBytes[10] = {0};
  33. unsigned Size = encodeSLEB128(Value, &EncodedBytes[0]);
  34. return writeBytes({EncodedBytes, Size});
  35. }
  36. Error BinaryStreamWriter::writeCString(StringRef Str) {
  37. if (auto EC = writeFixedString(Str))
  38. return EC;
  39. if (auto EC = writeObject('\0'))
  40. return EC;
  41. return Error::success();
  42. }
  43. Error BinaryStreamWriter::writeFixedString(StringRef Str) {
  44. return writeBytes(arrayRefFromStringRef(Str));
  45. }
  46. Error BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref) {
  47. return writeStreamRef(Ref, Ref.getLength());
  48. }
  49. Error BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref, uint64_t Length) {
  50. BinaryStreamReader SrcReader(Ref.slice(0, Length));
  51. // This is a bit tricky. If we just call readBytes, we are requiring that it
  52. // return us the entire stream as a contiguous buffer. There is no guarantee
  53. // this can be satisfied by returning a reference straight from the buffer, as
  54. // an implementation may not store all data in a single contiguous buffer. So
  55. // we iterate over each contiguous chunk, writing each one in succession.
  56. while (SrcReader.bytesRemaining() > 0) {
  57. ArrayRef<uint8_t> Chunk;
  58. if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
  59. return EC;
  60. if (auto EC = writeBytes(Chunk))
  61. return EC;
  62. }
  63. return Error::success();
  64. }
  65. std::pair<BinaryStreamWriter, BinaryStreamWriter>
  66. BinaryStreamWriter::split(uint64_t Off) const {
  67. assert(getLength() >= Off);
  68. WritableBinaryStreamRef First = Stream.drop_front(Offset);
  69. WritableBinaryStreamRef Second = First.drop_front(Off);
  70. First = First.keep_front(Off);
  71. BinaryStreamWriter W1{First};
  72. BinaryStreamWriter W2{Second};
  73. return std::make_pair(W1, W2);
  74. }
  75. Error BinaryStreamWriter::padToAlignment(uint32_t Align) {
  76. uint64_t NewOffset = alignTo(Offset, Align);
  77. const uint64_t ZerosSize = 64;
  78. static constexpr char Zeros[ZerosSize] = {};
  79. while (Offset < NewOffset)
  80. if (auto E = writeArray(
  81. ArrayRef<char>(Zeros, std::min(ZerosSize, NewOffset - Offset))))
  82. return E;
  83. return Error::success();
  84. }