blob: c1fc455a6872ba20a204113f42d3d7cce06d69d0 [file] [log] [blame]
Greg Claytone2ae97f2010-09-17 17:42:16 +00001//===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Greg Claytone2ae97f2010-09-17 17:42:16 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/API/SBStream.h"
10
Jonas Devliegherebaf56642019-03-06 00:06:00 +000011#include "SBReproducerPrivate.h"
Greg Claytone2ae97f2010-09-17 17:42:16 +000012#include "lldb/Core/StreamFile.h"
Jonas Devlieghere50bc1ed2018-11-02 22:34:51 +000013#include "lldb/Host/FileSystem.h"
Zachary Turner97206d52017-05-12 04:51:55 +000014#include "lldb/Utility/Status.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000015#include "lldb/Utility/Stream.h"
16#include "lldb/Utility/StreamString.h"
Greg Claytone2ae97f2010-09-17 17:42:16 +000017
18using namespace lldb;
19using namespace lldb_private;
20
Jonas Devliegherebaf56642019-03-06 00:06:00 +000021SBStream::SBStream() : m_opaque_up(new StreamString()), m_is_file(false) {
22 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBStream);
23}
Greg Claytone2ae97f2010-09-17 17:42:16 +000024
Kate Stoneb9c1b512016-09-06 20:57:50 +000025SBStream::SBStream(SBStream &&rhs)
Jonas Devlieghered5b44032019-02-13 06:25:41 +000026 : m_opaque_up(std::move(rhs.m_opaque_up)), m_is_file(rhs.m_is_file) {}
Greg Clayton0817da82015-12-15 23:03:22 +000027
Kate Stoneb9c1b512016-09-06 20:57:50 +000028SBStream::~SBStream() {}
Greg Clayton0817da82015-12-15 23:03:22 +000029
Jonas Devliegherebaf56642019-03-06 00:06:00 +000030bool SBStream::IsValid() const {
31 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStream, IsValid);
32
33 return (m_opaque_up != NULL);
34}
Greg Claytone2ae97f2010-09-17 17:42:16 +000035
Adrian Prantl05097242018-04-30 16:49:04 +000036// If this stream is not redirected to a file, it will maintain a local cache
37// for the stream data which can be accessed using this accessor.
Kate Stoneb9c1b512016-09-06 20:57:50 +000038const char *SBStream::GetData() {
Jonas Devliegherebaf56642019-03-06 00:06:00 +000039 LLDB_RECORD_METHOD_NO_ARGS(const char *, SBStream, GetData);
40
Jonas Devlieghered5b44032019-02-13 06:25:41 +000041 if (m_is_file || m_opaque_up == NULL)
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 return NULL;
43
Jonas Devlieghered5b44032019-02-13 06:25:41 +000044 return static_cast<StreamString *>(m_opaque_up.get())->GetData();
Greg Claytone2ae97f2010-09-17 17:42:16 +000045}
46
Adrian Prantl05097242018-04-30 16:49:04 +000047// If this stream is not redirected to a file, it will maintain a local cache
48// for the stream output whose length can be accessed using this accessor.
Kate Stoneb9c1b512016-09-06 20:57:50 +000049size_t SBStream::GetSize() {
Jonas Devliegherebaf56642019-03-06 00:06:00 +000050 LLDB_RECORD_METHOD_NO_ARGS(size_t, SBStream, GetSize);
51
Jonas Devlieghered5b44032019-02-13 06:25:41 +000052 if (m_is_file || m_opaque_up == NULL)
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 return 0;
54
Jonas Devlieghered5b44032019-02-13 06:25:41 +000055 return static_cast<StreamString *>(m_opaque_up.get())->GetSize();
Greg Claytone2ae97f2010-09-17 17:42:16 +000056}
57
Kate Stoneb9c1b512016-09-06 20:57:50 +000058void SBStream::Printf(const char *format, ...) {
59 if (!format)
60 return;
61 va_list args;
62 va_start(args, format);
63 ref().PrintfVarArg(format, args);
64 va_end(args);
Greg Claytone2ae97f2010-09-17 17:42:16 +000065}
66
Kate Stoneb9c1b512016-09-06 20:57:50 +000067void SBStream::RedirectToFile(const char *path, bool append) {
Jonas Devliegherebaf56642019-03-06 00:06:00 +000068 LLDB_RECORD_METHOD(void, SBStream, RedirectToFile, (const char *, bool), path,
69 append);
70
Kate Stoneb9c1b512016-09-06 20:57:50 +000071 if (path == nullptr)
72 return;
Zachary Turnere2dcbd02015-01-14 18:34:35 +000073
Kate Stoneb9c1b512016-09-06 20:57:50 +000074 std::string local_data;
Jonas Devlieghered5b44032019-02-13 06:25:41 +000075 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 // See if we have any locally backed data. If so, copy it so we can then
77 // redirect it to the file so we don't lose the data
78 if (!m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +000079 local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 }
81 StreamFile *stream_file = new StreamFile;
82 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
83 if (append)
84 open_options |= File::eOpenOptionAppend;
85 else
86 open_options |= File::eOpenOptionTruncate;
Kate Stoneb9c1b512016-09-06 20:57:50 +000087
Jonas Devlieghere50bc1ed2018-11-02 22:34:51 +000088 FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path),
89 open_options);
Jonas Devlieghered5b44032019-02-13 06:25:41 +000090 m_opaque_up.reset(stream_file);
Kate Stoneb9c1b512016-09-06 20:57:50 +000091
Jonas Devlieghered5b44032019-02-13 06:25:41 +000092 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 m_is_file = true;
94
95 // If we had any data locally in our StreamString, then pass that along to
96 // the to new file we are redirecting to.
97 if (!local_data.empty())
Jonas Devlieghered5b44032019-02-13 06:25:41 +000098 m_opaque_up->Write(&local_data[0], local_data.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +000099 } else
100 m_is_file = false;
101}
102
103void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
Jonas Devliegherebaf56642019-03-06 00:06:00 +0000104 LLDB_RECORD_METHOD(void, SBStream, RedirectToFileHandle, (FILE *, bool), fh,
105 transfer_fh_ownership);
106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 if (fh == nullptr)
108 return;
109
110 std::string local_data;
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000111 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 // See if we have any locally backed data. If so, copy it so we can then
113 // redirect it to the file so we don't lose the data
114 if (!m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000115 local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 }
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000117 m_opaque_up.reset(new StreamFile(fh, transfer_fh_ownership));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000119 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 m_is_file = true;
121
122 // If we had any data locally in our StreamString, then pass that along to
123 // the to new file we are redirecting to.
124 if (!local_data.empty())
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000125 m_opaque_up->Write(&local_data[0], local_data.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 } else
127 m_is_file = false;
128}
129
130void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
Jonas Devliegherebaf56642019-03-06 00:06:00 +0000131 LLDB_RECORD_METHOD(void, SBStream, RedirectToFileDescriptor, (int, bool), fd,
132 transfer_fh_ownership);
133
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134 std::string local_data;
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000135 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136 // See if we have any locally backed data. If so, copy it so we can then
137 // redirect it to the file so we don't lose the data
138 if (!m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000139 local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 }
141
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000142 m_opaque_up.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
143 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 m_is_file = true;
145
146 // If we had any data locally in our StreamString, then pass that along to
147 // the to new file we are redirecting to.
148 if (!local_data.empty())
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000149 m_opaque_up->Write(&local_data[0], local_data.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150 } else
151 m_is_file = false;
152}
153
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000154lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000156lldb_private::Stream *SBStream::get() { return m_opaque_up.get(); }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157
158lldb_private::Stream &SBStream::ref() {
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000159 if (m_opaque_up == NULL)
160 m_opaque_up.reset(new StreamString());
161 return *m_opaque_up;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162}
163
164void SBStream::Clear() {
Jonas Devliegherebaf56642019-03-06 00:06:00 +0000165 LLDB_RECORD_METHOD_NO_ARGS(void, SBStream, Clear);
166
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000167 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 // See if we have any locally backed data. If so, copy it so we can then
169 // redirect it to the file so we don't lose the data
170 if (m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000171 m_opaque_up.reset();
Greg Clayton06357c92014-07-30 17:38:47 +0000172 else
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000173 static_cast<StreamString *>(m_opaque_up.get())->Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 }
Greg Claytone2ae97f2010-09-17 17:42:16 +0000175}