Home | History | Annotate | Line # | Download | only in Support
      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 }
    104