blob: 0ade453f84523df3797c5c0abb86b080d536334d [file] [log] [blame]
Greg Claytone2ae97f2010-09-17 17:42:16 +00001//===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
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 "lldb/API/SBStream.h"
11
Greg Clayton51b1e2d2011-02-09 01:08:52 +000012#include "lldb/Core/Error.h"
Greg Claytone2ae97f2010-09-17 17:42:16 +000013#include "lldb/Core/Stream.h"
14#include "lldb/Core/StreamFile.h"
15#include "lldb/Core/StreamString.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
Kate Stoneb9c1b512016-09-06 20:57:50 +000020SBStream::SBStream() : m_opaque_ap(new StreamString()), m_is_file(false) {}
Greg Claytone2ae97f2010-09-17 17:42:16 +000021
Kate Stoneb9c1b512016-09-06 20:57:50 +000022SBStream::SBStream(SBStream &&rhs)
23 : m_opaque_ap(std::move(rhs.m_opaque_ap)), m_is_file(rhs.m_is_file) {}
Greg Clayton0817da82015-12-15 23:03:22 +000024
Kate Stoneb9c1b512016-09-06 20:57:50 +000025SBStream::~SBStream() {}
Greg Clayton0817da82015-12-15 23:03:22 +000026
Kate Stoneb9c1b512016-09-06 20:57:50 +000027bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); }
Greg Claytone2ae97f2010-09-17 17:42:16 +000028
29// If this stream is not redirected to a file, it will maintain a local
30// cache for the stream data which can be accessed using this accessor.
Kate Stoneb9c1b512016-09-06 20:57:50 +000031const char *SBStream::GetData() {
32 if (m_is_file || m_opaque_ap.get() == NULL)
33 return NULL;
34
35 return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
Greg Claytone2ae97f2010-09-17 17:42:16 +000036}
37
38// If this stream is not redirected to a file, it will maintain a local
Kate Stoneb9c1b512016-09-06 20:57:50 +000039// cache for the stream output whose length can be accessed using this
Greg Claytone2ae97f2010-09-17 17:42:16 +000040// accessor.
Kate Stoneb9c1b512016-09-06 20:57:50 +000041size_t SBStream::GetSize() {
42 if (m_is_file || m_opaque_ap.get() == NULL)
43 return 0;
44
45 return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
Greg Claytone2ae97f2010-09-17 17:42:16 +000046}
47
Kate Stoneb9c1b512016-09-06 20:57:50 +000048void SBStream::Printf(const char *format, ...) {
49 if (!format)
50 return;
51 va_list args;
52 va_start(args, format);
53 ref().PrintfVarArg(format, args);
54 va_end(args);
Greg Claytone2ae97f2010-09-17 17:42:16 +000055}
56
Kate Stoneb9c1b512016-09-06 20:57:50 +000057void SBStream::RedirectToFile(const char *path, bool append) {
58 if (path == nullptr)
59 return;
Zachary Turnere2dcbd02015-01-14 18:34:35 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 std::string local_data;
62 if (m_opaque_ap.get()) {
63 // See if we have any locally backed data. If so, copy it so we can then
64 // redirect it to the file so we don't lose the data
65 if (!m_is_file)
66 local_data.swap(
67 static_cast<StreamString *>(m_opaque_ap.get())->GetString());
68 }
69 StreamFile *stream_file = new StreamFile;
70 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
71 if (append)
72 open_options |= File::eOpenOptionAppend;
73 else
74 open_options |= File::eOpenOptionTruncate;
75 stream_file->GetFile().Open(path, open_options,
76 lldb::eFilePermissionsFileDefault);
77
78 m_opaque_ap.reset(stream_file);
79
80 if (m_opaque_ap.get()) {
81 m_is_file = true;
82
83 // If we had any data locally in our StreamString, then pass that along to
84 // the to new file we are redirecting to.
85 if (!local_data.empty())
86 m_opaque_ap->Write(&local_data[0], local_data.size());
87 } else
88 m_is_file = false;
89}
90
91void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
92 if (fh == nullptr)
93 return;
94
95 std::string local_data;
96 if (m_opaque_ap.get()) {
97 // See if we have any locally backed data. If so, copy it so we can then
98 // redirect it to the file so we don't lose the data
99 if (!m_is_file)
100 local_data.swap(
101 static_cast<StreamString *>(m_opaque_ap.get())->GetString());
102 }
103 m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership));
104
105 if (m_opaque_ap.get()) {
106 m_is_file = true;
107
108 // If we had any data locally in our StreamString, then pass that along to
109 // the to new file we are redirecting to.
110 if (!local_data.empty())
111 m_opaque_ap->Write(&local_data[0], local_data.size());
112 } else
113 m_is_file = false;
114}
115
116void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
117 std::string local_data;
118 if (m_opaque_ap.get()) {
119 // See if we have any locally backed data. If so, copy it so we can then
120 // redirect it to the file so we don't lose the data
121 if (!m_is_file)
122 local_data.swap(
123 static_cast<StreamString *>(m_opaque_ap.get())->GetString());
124 }
125
126 m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
127 if (m_opaque_ap.get()) {
128 m_is_file = true;
129
130 // If we had any data locally in our StreamString, then pass that along to
131 // the to new file we are redirecting to.
132 if (!local_data.empty())
133 m_opaque_ap->Write(&local_data[0], local_data.size());
134 } else
135 m_is_file = false;
136}
137
138lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); }
139
140lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); }
141
142lldb_private::Stream &SBStream::ref() {
143 if (m_opaque_ap.get() == NULL)
144 m_opaque_ap.reset(new StreamString());
145 return *m_opaque_ap.get();
146}
147
148void SBStream::Clear() {
149 if (m_opaque_ap.get()) {
150 // See if we have any locally backed data. If so, copy it so we can then
151 // redirect it to the file so we don't lose the data
152 if (m_is_file)
153 m_opaque_ap.reset();
Greg Clayton06357c92014-07-30 17:38:47 +0000154 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear();
156 }
Greg Claytone2ae97f2010-09-17 17:42:16 +0000157}