1//===- StreamWrite.cpp - Writes bytes and objects to a stream -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/DebugInfo/CodeView/StreamWriter.h"
11
12#include "llvm/DebugInfo/CodeView/CodeViewError.h"
13#include "llvm/DebugInfo/CodeView/StreamReader.h"
14#include "llvm/DebugInfo/CodeView/StreamRef.h"
15
16using namespace llvm;
17using namespace llvm::codeview;
18
19StreamWriter::StreamWriter(StreamRef S) : Stream(S), Offset(0) {}
20
21Error StreamWriter::writeBytes(ArrayRef<uint8_t> Buffer) {
22  if (auto EC = Stream.writeBytes(Offset, Buffer))
23    return EC;
24  Offset += Buffer.size();
25  return Error::success();
26}
27
28Error StreamWriter::writeInteger(uint16_t Int) {
29  return writeObject(support::ulittle16_t(Int));
30}
31
32Error StreamWriter::writeInteger(uint32_t Int) {
33  return writeObject(support::ulittle32_t(Int));
34}
35
36Error StreamWriter::writeZeroString(StringRef Str) {
37  if (auto EC = writeFixedString(Str))
38    return EC;
39  if (auto EC = writeObject('\0'))
40    return EC;
41
42  return Error::success();
43}
44
45Error StreamWriter::writeFixedString(StringRef Str) {
46  ArrayRef<uint8_t> Bytes(Str.bytes_begin(), Str.bytes_end());
47  if (auto EC = Stream.writeBytes(Offset, Bytes))
48    return EC;
49
50  Offset += Str.size();
51  return Error::success();
52}
53
54Error StreamWriter::writeStreamRef(StreamRef Ref) {
55  if (auto EC = writeStreamRef(Ref, Ref.getLength()))
56    return EC;
57  Offset += Ref.getLength();
58  return Error::success();
59}
60
61Error StreamWriter::writeStreamRef(StreamRef Ref, uint32_t Length) {
62  Ref = Ref.slice(0, Length);
63
64  StreamReader SrcReader(Ref);
65  // This is a bit tricky.  If we just call readBytes, we are requiring that it
66  // return us the entire stream as a contiguous buffer.  For large streams this
67  // will allocate a huge amount of space from the pool.  Instead, iterate over
68  // each contiguous chunk until we've consumed the entire stream.
69  while (SrcReader.bytesRemaining() > 0) {
70    ArrayRef<uint8_t> Chunk;
71    if (auto EC = SrcReader.readLongestContiguousChunk(Chunk))
72      return EC;
73    if (auto EC = writeBytes(Chunk))
74      return EC;
75  }
76  return Error::success();
77}
78