xref: /src/contrib/llvm-project/lldb/source/API/SBStream.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- SBStream.cpp ------------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/API/SBStream.h"
10f034231aSEd Maste 
11ead24645SDimitry Andric #include "lldb/API/SBFile.h"
1294994d37SDimitry Andric #include "lldb/Host/FileSystem.h"
13b1c73532SDimitry Andric #include "lldb/Host/StreamFile.h"
146f8fc217SDimitry Andric #include "lldb/Utility/Instrumentation.h"
15145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
16b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
1774a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
1874a628f7SDimitry Andric #include "lldb/Utility/StreamString.h"
19f034231aSEd Maste 
20f034231aSEd Maste using namespace lldb;
21f034231aSEd Maste using namespace lldb_private;
22f034231aSEd Maste 
SBStream()23344a3780SDimitry Andric SBStream::SBStream() : m_opaque_up(new StreamString()) {
246f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
255f29bb8aSDimitry Andric }
26f034231aSEd Maste 
SBStream(SBStream && rhs)2714f1b3e8SDimitry Andric SBStream::SBStream(SBStream &&rhs)
285f29bb8aSDimitry Andric     : m_opaque_up(std::move(rhs.m_opaque_up)), m_is_file(rhs.m_is_file) {}
29e81d9d49SDimitry Andric 
30cfca06d7SDimitry Andric SBStream::~SBStream() = default;
31e81d9d49SDimitry Andric 
IsValid() const325f29bb8aSDimitry Andric bool SBStream::IsValid() const {
336f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
345f29bb8aSDimitry Andric   return this->operator bool();
355f29bb8aSDimitry Andric }
operator bool() const365f29bb8aSDimitry Andric SBStream::operator bool() const {
376f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
385f29bb8aSDimitry Andric 
395f29bb8aSDimitry Andric   return (m_opaque_up != nullptr);
405f29bb8aSDimitry Andric }
41f034231aSEd Maste 
42f73363f1SDimitry Andric // If this stream is not redirected to a file, it will maintain a local cache
43f73363f1SDimitry Andric // for the stream data which can be accessed using this accessor.
GetData()4414f1b3e8SDimitry Andric const char *SBStream::GetData() {
456f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
46f034231aSEd Maste 
475f29bb8aSDimitry Andric   if (m_is_file || m_opaque_up == nullptr)
485f29bb8aSDimitry Andric     return nullptr;
495f29bb8aSDimitry Andric 
507fa27ce4SDimitry Andric   return ConstString(static_cast<StreamString *>(m_opaque_up.get())->GetData())
517fa27ce4SDimitry Andric       .GetCString();
52f034231aSEd Maste }
53f034231aSEd Maste 
54f73363f1SDimitry Andric // If this stream is not redirected to a file, it will maintain a local cache
55f73363f1SDimitry Andric // for the stream output whose length can be accessed using this accessor.
GetSize()5614f1b3e8SDimitry Andric size_t SBStream::GetSize() {
576f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
585f29bb8aSDimitry Andric 
595f29bb8aSDimitry Andric   if (m_is_file || m_opaque_up == nullptr)
60f034231aSEd Maste     return 0;
61f034231aSEd Maste 
625f29bb8aSDimitry Andric   return static_cast<StreamString *>(m_opaque_up.get())->GetSize();
63f034231aSEd Maste }
64f034231aSEd Maste 
Print(const char * str)65cfca06d7SDimitry Andric void SBStream::Print(const char *str) {
666f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, str);
67cfca06d7SDimitry Andric 
68cfca06d7SDimitry Andric   Printf("%s", str);
69cfca06d7SDimitry Andric }
70cfca06d7SDimitry Andric 
Printf(const char * format,...)7114f1b3e8SDimitry Andric void SBStream::Printf(const char *format, ...) {
72f034231aSEd Maste   if (!format)
73f034231aSEd Maste     return;
74f034231aSEd Maste   va_list args;
75f034231aSEd Maste   va_start(args, format);
76f034231aSEd Maste   ref().PrintfVarArg(format, args);
77f034231aSEd Maste   va_end(args);
78f034231aSEd Maste }
79f034231aSEd Maste 
RedirectToFile(const char * path,bool append)8014f1b3e8SDimitry Andric void SBStream::RedirectToFile(const char *path, bool append) {
816f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, path, append);
825f29bb8aSDimitry Andric 
8312bd4897SEd Maste   if (path == nullptr)
8412bd4897SEd Maste     return;
8512bd4897SEd Maste 
86f034231aSEd Maste   std::string local_data;
875f29bb8aSDimitry Andric   if (m_opaque_up) {
88f034231aSEd Maste     // See if we have any locally backed data. If so, copy it so we can then
89f034231aSEd Maste     // redirect it to the file so we don't lose the data
90f034231aSEd Maste     if (!m_is_file)
91cfca06d7SDimitry Andric       local_data = std::string(
92cfca06d7SDimitry Andric           static_cast<StreamString *>(m_opaque_up.get())->GetString());
93f034231aSEd Maste   }
94c0981da4SDimitry Andric   auto open_options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
95f034231aSEd Maste   if (append)
96f034231aSEd Maste     open_options |= File::eOpenOptionAppend;
970cac4ca3SEd Maste   else
980cac4ca3SEd Maste     open_options |= File::eOpenOptionTruncate;
99f034231aSEd Maste 
100ead24645SDimitry Andric   llvm::Expected<FileUP> file =
101ead24645SDimitry Andric       FileSystem::Instance().Open(FileSpec(path), open_options);
102ead24645SDimitry Andric   if (!file) {
103145449b1SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::API), file.takeError(),
104ead24645SDimitry Andric                    "Cannot open {1}: {0}", path);
105ead24645SDimitry Andric     return;
106ead24645SDimitry Andric   }
107f034231aSEd Maste 
108ead24645SDimitry Andric   m_opaque_up = std::make_unique<StreamFile>(std::move(file.get()));
109f034231aSEd Maste   m_is_file = true;
110f034231aSEd Maste 
111f034231aSEd Maste   // If we had any data locally in our StreamString, then pass that along to
112f034231aSEd Maste   // the to new file we are redirecting to.
113f034231aSEd Maste   if (!local_data.empty())
1145f29bb8aSDimitry Andric     m_opaque_up->Write(&local_data[0], local_data.size());
115f034231aSEd Maste }
116f034231aSEd Maste 
RedirectToFileHandle(FILE * fh,bool transfer_fh_ownership)11714f1b3e8SDimitry Andric void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
1186f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, fh, transfer_fh_ownership);
119ead24645SDimitry Andric   FileSP file = std::make_unique<NativeFile>(fh, transfer_fh_ownership);
120ead24645SDimitry Andric   return RedirectToFile(file);
121ead24645SDimitry Andric }
1225f29bb8aSDimitry Andric 
RedirectToFile(SBFile file)123ead24645SDimitry Andric void SBStream::RedirectToFile(SBFile file) {
1246f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, file)
125ead24645SDimitry Andric   RedirectToFile(file.GetFile());
126ead24645SDimitry Andric }
127ead24645SDimitry Andric 
RedirectToFile(FileSP file_sp)128ead24645SDimitry Andric void SBStream::RedirectToFile(FileSP file_sp) {
1296f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, file_sp);
130ead24645SDimitry Andric 
131ead24645SDimitry Andric   if (!file_sp || !file_sp->IsValid())
13212bd4897SEd Maste     return;
13312bd4897SEd Maste 
134f034231aSEd Maste   std::string local_data;
1355f29bb8aSDimitry Andric   if (m_opaque_up) {
136f034231aSEd Maste     // See if we have any locally backed data. If so, copy it so we can then
137f034231aSEd Maste     // redirect it to the file so we don't lose the data
138f034231aSEd Maste     if (!m_is_file)
139cfca06d7SDimitry Andric       local_data = std::string(
140cfca06d7SDimitry Andric           static_cast<StreamString *>(m_opaque_up.get())->GetString());
141f034231aSEd Maste   }
142f034231aSEd Maste 
143ead24645SDimitry Andric   m_opaque_up = std::make_unique<StreamFile>(file_sp);
144f034231aSEd Maste   m_is_file = true;
145f034231aSEd Maste 
146f034231aSEd Maste   // If we had any data locally in our StreamString, then pass that along to
147f034231aSEd Maste   // the to new file we are redirecting to.
148f034231aSEd Maste   if (!local_data.empty())
1495f29bb8aSDimitry Andric     m_opaque_up->Write(&local_data[0], local_data.size());
150f034231aSEd Maste }
151f034231aSEd Maste 
RedirectToFileDescriptor(int fd,bool transfer_fh_ownership)15214f1b3e8SDimitry Andric void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
1536f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this, fd, transfer_fh_ownership);
1545f29bb8aSDimitry Andric 
155f034231aSEd Maste   std::string local_data;
1565f29bb8aSDimitry Andric   if (m_opaque_up) {
157f034231aSEd Maste     // See if we have any locally backed data. If so, copy it so we can then
158f034231aSEd Maste     // redirect it to the file so we don't lose the data
159f034231aSEd Maste     if (!m_is_file)
160cfca06d7SDimitry Andric       local_data = std::string(
161cfca06d7SDimitry Andric           static_cast<StreamString *>(m_opaque_up.get())->GetString());
162f034231aSEd Maste   }
163f034231aSEd Maste 
164ead24645SDimitry Andric   m_opaque_up = std::make_unique<StreamFile>(fd, transfer_fh_ownership);
165f034231aSEd Maste   m_is_file = true;
166f034231aSEd Maste 
167f034231aSEd Maste   // If we had any data locally in our StreamString, then pass that along to
168f034231aSEd Maste   // the to new file we are redirecting to.
169f034231aSEd Maste   if (!local_data.empty())
1705f29bb8aSDimitry Andric     m_opaque_up->Write(&local_data[0], local_data.size());
171f034231aSEd Maste }
172f034231aSEd Maste 
operator ->()1735f29bb8aSDimitry Andric lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); }
174f034231aSEd Maste 
get()1755f29bb8aSDimitry Andric lldb_private::Stream *SBStream::get() { return m_opaque_up.get(); }
176f034231aSEd Maste 
ref()17714f1b3e8SDimitry Andric lldb_private::Stream &SBStream::ref() {
1785f29bb8aSDimitry Andric   if (m_opaque_up == nullptr)
179cfca06d7SDimitry Andric     m_opaque_up = std::make_unique<StreamString>();
1805f29bb8aSDimitry Andric   return *m_opaque_up;
181f034231aSEd Maste }
182f034231aSEd Maste 
Clear()18314f1b3e8SDimitry Andric void SBStream::Clear() {
1846f8fc217SDimitry Andric   LLDB_INSTRUMENT_VA(this);
1855f29bb8aSDimitry Andric 
1865f29bb8aSDimitry Andric   if (m_opaque_up) {
187f034231aSEd Maste     // See if we have any locally backed data. If so, copy it so we can then
188f034231aSEd Maste     // redirect it to the file so we don't lose the data
189f034231aSEd Maste     if (m_is_file)
1905f29bb8aSDimitry Andric       m_opaque_up.reset();
191f034231aSEd Maste     else
1925f29bb8aSDimitry Andric       static_cast<StreamString *>(m_opaque_up.get())->Clear();
1935f29bb8aSDimitry Andric   }
1945f29bb8aSDimitry Andric }
195