blob: 11479d521bb408a96467037bb0107ba06de54b7b [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
Greg Claytone2ae97f2010-09-17 17:42:16 +000011#include "lldb/Core/StreamFile.h"
Jonas Devlieghere50bc1ed2018-11-02 22:34:51 +000012#include "lldb/Host/FileSystem.h"
Zachary Turner97206d52017-05-12 04:51:55 +000013#include "lldb/Utility/Status.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000014#include "lldb/Utility/Stream.h"
15#include "lldb/Utility/StreamString.h"
Greg Claytone2ae97f2010-09-17 17:42:16 +000016
17using namespace lldb;
18using namespace lldb_private;
19
Jonas Devlieghered5b44032019-02-13 06:25:41 +000020SBStream::SBStream() : m_opaque_up(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)
Jonas Devlieghered5b44032019-02-13 06:25:41 +000023 : m_opaque_up(std::move(rhs.m_opaque_up)), 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
Jonas Devlieghered5b44032019-02-13 06:25:41 +000027bool SBStream::IsValid() const { return (m_opaque_up != NULL); }
Greg Claytone2ae97f2010-09-17 17:42:16 +000028
Adrian Prantl05097242018-04-30 16:49:04 +000029// If this stream is not redirected to a file, it will maintain a local cache
30// for the stream data which can be accessed using this accessor.
Kate Stoneb9c1b512016-09-06 20:57:50 +000031const char *SBStream::GetData() {
Jonas Devlieghered5b44032019-02-13 06:25:41 +000032 if (m_is_file || m_opaque_up == NULL)
Kate Stoneb9c1b512016-09-06 20:57:50 +000033 return NULL;
34
Jonas Devlieghered5b44032019-02-13 06:25:41 +000035 return static_cast<StreamString *>(m_opaque_up.get())->GetData();
Greg Claytone2ae97f2010-09-17 17:42:16 +000036}
37
Adrian Prantl05097242018-04-30 16:49:04 +000038// If this stream is not redirected to a file, it will maintain a local cache
39// for the stream output whose length can be accessed using this accessor.
Kate Stoneb9c1b512016-09-06 20:57:50 +000040size_t SBStream::GetSize() {
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 0;
43
Jonas Devlieghered5b44032019-02-13 06:25:41 +000044 return static_cast<StreamString *>(m_opaque_up.get())->GetSize();
Greg Claytone2ae97f2010-09-17 17:42:16 +000045}
46
Kate Stoneb9c1b512016-09-06 20:57:50 +000047void SBStream::Printf(const char *format, ...) {
48 if (!format)
49 return;
50 va_list args;
51 va_start(args, format);
52 ref().PrintfVarArg(format, args);
53 va_end(args);
Greg Claytone2ae97f2010-09-17 17:42:16 +000054}
55
Kate Stoneb9c1b512016-09-06 20:57:50 +000056void SBStream::RedirectToFile(const char *path, bool append) {
57 if (path == nullptr)
58 return;
Zachary Turnere2dcbd02015-01-14 18:34:35 +000059
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 std::string local_data;
Jonas Devlieghered5b44032019-02-13 06:25:41 +000061 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 // See if we have any locally backed data. If so, copy it so we can then
63 // redirect it to the file so we don't lose the data
64 if (!m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +000065 local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 }
67 StreamFile *stream_file = new StreamFile;
68 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
69 if (append)
70 open_options |= File::eOpenOptionAppend;
71 else
72 open_options |= File::eOpenOptionTruncate;
Kate Stoneb9c1b512016-09-06 20:57:50 +000073
Jonas Devlieghere50bc1ed2018-11-02 22:34:51 +000074 FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path),
75 open_options);
Jonas Devlieghered5b44032019-02-13 06:25:41 +000076 m_opaque_up.reset(stream_file);
Kate Stoneb9c1b512016-09-06 20:57:50 +000077
Jonas Devlieghered5b44032019-02-13 06:25:41 +000078 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 m_is_file = true;
80
81 // If we had any data locally in our StreamString, then pass that along to
82 // the to new file we are redirecting to.
83 if (!local_data.empty())
Jonas Devlieghered5b44032019-02-13 06:25:41 +000084 m_opaque_up->Write(&local_data[0], local_data.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 } else
86 m_is_file = false;
87}
88
89void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
90 if (fh == nullptr)
91 return;
92
93 std::string local_data;
Jonas Devlieghered5b44032019-02-13 06:25:41 +000094 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 // See if we have any locally backed data. If so, copy it so we can then
96 // redirect it to the file so we don't lose the data
97 if (!m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +000098 local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +000099 }
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000100 m_opaque_up.reset(new StreamFile(fh, transfer_fh_ownership));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000102 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103 m_is_file = true;
104
105 // If we had any data locally in our StreamString, then pass that along to
106 // the to new file we are redirecting to.
107 if (!local_data.empty())
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000108 m_opaque_up->Write(&local_data[0], local_data.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 } else
110 m_is_file = false;
111}
112
113void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
114 std::string local_data;
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000115 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 // See if we have any locally backed data. If so, copy it so we can then
117 // redirect it to the file so we don't lose the data
118 if (!m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000119 local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 }
121
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000122 m_opaque_up.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
123 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 m_is_file = true;
125
126 // If we had any data locally in our StreamString, then pass that along to
127 // the to new file we are redirecting to.
128 if (!local_data.empty())
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000129 m_opaque_up->Write(&local_data[0], local_data.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130 } else
131 m_is_file = false;
132}
133
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000134lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000136lldb_private::Stream *SBStream::get() { return m_opaque_up.get(); }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137
138lldb_private::Stream &SBStream::ref() {
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000139 if (m_opaque_up == NULL)
140 m_opaque_up.reset(new StreamString());
141 return *m_opaque_up;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142}
143
144void SBStream::Clear() {
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000145 if (m_opaque_up) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 // See if we have any locally backed data. If so, copy it so we can then
147 // redirect it to the file so we don't lose the data
148 if (m_is_file)
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000149 m_opaque_up.reset();
Greg Clayton06357c92014-07-30 17:38:47 +0000150 else
Jonas Devlieghered5b44032019-02-13 06:25:41 +0000151 static_cast<StreamString *>(m_opaque_up.get())->Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152 }
Greg Claytone2ae97f2010-09-17 17:42:16 +0000153}