1 //===- BinaryStreamWriter.cpp - Writes objects to a BinaryStream ----------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/BinaryStreamWriter.h"
11 #include "llvm/Support/BinaryStreamError.h"
12 #include "llvm/Support/BinaryStreamReader.h"
13 #include "llvm/Support/BinaryStreamRef.h"
14 #include "llvm/Support/LEB128.h"
18 BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStreamRef Ref
)
21 BinaryStreamWriter::BinaryStreamWriter(WritableBinaryStream
&Stream
)
24 BinaryStreamWriter::BinaryStreamWriter(MutableArrayRef
<uint8_t> Data
,
25 llvm::support::endianness Endian
)
26 : Stream(Data
, Endian
) {}
28 Error
BinaryStreamWriter::writeBytes(ArrayRef
<uint8_t> Buffer
) {
29 if (auto EC
= Stream
.writeBytes(Offset
, Buffer
))
31 Offset
+= Buffer
.size();
32 return Error::success();
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
});
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
});
47 Error
BinaryStreamWriter::writeCString(StringRef Str
) {
48 if (auto EC
= writeFixedString(Str
))
50 if (auto EC
= writeObject('\0'))
53 return Error::success();
56 Error
BinaryStreamWriter::writeFixedString(StringRef Str
) {
58 return writeBytes(arrayRefFromStringRef(Str
));
61 Error
BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref
) {
62 return writeStreamRef(Ref
, Ref
.getLength());
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
))
76 if (auto EC
= writeBytes(Chunk
))
79 return Error::success();
82 std::pair
<BinaryStreamWriter
, BinaryStreamWriter
>
83 BinaryStreamWriter::split(uint32_t Off
) const {
84 assert(getLength() >= Off
);
86 WritableBinaryStreamRef First
= Stream
.drop_front(Offset
);
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
);
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'))
102 return Error::success();