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