180814287SRaphael Isemann //===-- SBStream.cpp ------------------------------------------------------===// 2e2ae97f2SGreg Clayton // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e2ae97f2SGreg Clayton // 7e2ae97f2SGreg Clayton //===----------------------------------------------------------------------===// 8e2ae97f2SGreg Clayton 9e2ae97f2SGreg Clayton #include "lldb/API/SBStream.h" 10e2ae97f2SGreg Clayton 1130cf6095SLawrence D'Anna #include "lldb/API/SBFile.h" 12e2ae97f2SGreg Clayton #include "lldb/Core/StreamFile.h" 1350bc1ed2SJonas Devlieghere #include "lldb/Host/FileSystem.h" 141755f5b1SJonas Devlieghere #include "lldb/Utility/Instrumentation.h" 1597206d57SZachary Turner #include "lldb/Utility/Status.h" 16bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 17bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 18e2ae97f2SGreg Clayton 19e2ae97f2SGreg Clayton using namespace lldb; 20e2ae97f2SGreg Clayton using namespace lldb_private; 21e2ae97f2SGreg Clayton 229494c510SJonas Devlieghere SBStream::SBStream() : m_opaque_up(new StreamString()) { 231755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this); 24baf5664fSJonas Devlieghere } 25e2ae97f2SGreg Clayton 26b9c1b51eSKate Stone SBStream::SBStream(SBStream &&rhs) 27d5b44036SJonas Devlieghere : m_opaque_up(std::move(rhs.m_opaque_up)), m_is_file(rhs.m_is_file) {} 280817da88SGreg Clayton 29866b7a65SJonas Devlieghere SBStream::~SBStream() = default; 300817da88SGreg Clayton 31baf5664fSJonas Devlieghere bool SBStream::IsValid() const { 321755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this); 337f5237bcSPavel Labath return this->operator bool(); 347f5237bcSPavel Labath } 357f5237bcSPavel Labath SBStream::operator bool() const { 361755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this); 37baf5664fSJonas Devlieghere 38248a1305SKonrad Kleine return (m_opaque_up != nullptr); 39baf5664fSJonas Devlieghere } 40e2ae97f2SGreg Clayton 4105097246SAdrian Prantl // If this stream is not redirected to a file, it will maintain a local cache 4205097246SAdrian Prantl // for the stream data which can be accessed using this accessor. 43b9c1b51eSKate Stone const char *SBStream::GetData() { 441755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this); 45baf5664fSJonas Devlieghere 46248a1305SKonrad Kleine if (m_is_file || m_opaque_up == nullptr) 47248a1305SKonrad Kleine return nullptr; 48e2ae97f2SGreg Clayton 49d5b44036SJonas Devlieghere return static_cast<StreamString *>(m_opaque_up.get())->GetData(); 50e2ae97f2SGreg Clayton } 51e2ae97f2SGreg Clayton 5205097246SAdrian Prantl // If this stream is not redirected to a file, it will maintain a local cache 5305097246SAdrian Prantl // for the stream output whose length can be accessed using this accessor. 54b9c1b51eSKate Stone size_t SBStream::GetSize() { 551755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this); 56baf5664fSJonas Devlieghere 57248a1305SKonrad Kleine if (m_is_file || m_opaque_up == nullptr) 5860fd91ffSBill Wendling return 0; 59e2ae97f2SGreg Clayton 60d5b44036SJonas Devlieghere return static_cast<StreamString *>(m_opaque_up.get())->GetSize(); 61e2ae97f2SGreg Clayton } 62e2ae97f2SGreg Clayton 63bfb27837SJonas Devlieghere void SBStream::Print(const char *str) { 641755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this, str); 65bfb27837SJonas Devlieghere 66bfb27837SJonas Devlieghere Printf("%s", str); 67bfb27837SJonas Devlieghere } 68bfb27837SJonas Devlieghere 69b9c1b51eSKate Stone void SBStream::Printf(const char *format, ...) { 704f8189bcSJohnny Chen if (!format) 714f8189bcSJohnny Chen return; 72e2ae97f2SGreg Clayton va_list args; 73e2ae97f2SGreg Clayton va_start(args, format); 74e2ae97f2SGreg Clayton ref().PrintfVarArg(format, args); 75e2ae97f2SGreg Clayton va_end(args); 76e2ae97f2SGreg Clayton } 77e2ae97f2SGreg Clayton 78b9c1b51eSKate Stone void SBStream::RedirectToFile(const char *path, bool append) { 791755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this, path, append); 80baf5664fSJonas Devlieghere 81e2dcbd00SZachary Turner if (path == nullptr) 82e2dcbd00SZachary Turner return; 83e2dcbd00SZachary Turner 84e2ae97f2SGreg Clayton std::string local_data; 85d5b44036SJonas Devlieghere if (m_opaque_up) { 86e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 87e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 88e2ae97f2SGreg Clayton if (!m_is_file) 89adcd0268SBenjamin Kramer local_data = std::string( 90adcd0268SBenjamin Kramer static_cast<StreamString *>(m_opaque_up.get())->GetString()); 91e2ae97f2SGreg Clayton } 9214735cabSMichał Górny auto open_options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate; 9351b1e2d2SGreg Clayton if (append) 9451b1e2d2SGreg Clayton open_options |= File::eOpenOptionAppend; 9506357c93SGreg Clayton else 9606357c93SGreg Clayton open_options |= File::eOpenOptionTruncate; 9751b1e2d2SGreg Clayton 982fce1137SLawrence D'Anna llvm::Expected<FileUP> file = 992fce1137SLawrence D'Anna FileSystem::Instance().Open(FileSpec(path), open_options); 1002fce1137SLawrence D'Anna if (!file) { 101*a007a6d8SPavel Labath LLDB_LOG_ERROR(GetLog(LLDBLog::API), file.takeError(), 1022fce1137SLawrence D'Anna "Cannot open {1}: {0}", path); 1032fce1137SLawrence D'Anna return; 1042fce1137SLawrence D'Anna } 105e2ae97f2SGreg Clayton 1062fce1137SLawrence D'Anna m_opaque_up = std::make_unique<StreamFile>(std::move(file.get())); 107e2ae97f2SGreg Clayton m_is_file = true; 108e2ae97f2SGreg Clayton 109e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 110e2ae97f2SGreg Clayton // the to new file we are redirecting to. 111e2ae97f2SGreg Clayton if (!local_data.empty()) 112d5b44036SJonas Devlieghere m_opaque_up->Write(&local_data[0], local_data.size()); 113e2ae97f2SGreg Clayton } 114e2ae97f2SGreg Clayton 115b9c1b51eSKate Stone void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { 1161755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this, fh, transfer_fh_ownership); 11730cf6095SLawrence D'Anna FileSP file = std::make_unique<NativeFile>(fh, transfer_fh_ownership); 11830cf6095SLawrence D'Anna return RedirectToFile(file); 11930cf6095SLawrence D'Anna } 120baf5664fSJonas Devlieghere 12130cf6095SLawrence D'Anna void SBStream::RedirectToFile(SBFile file) { 1221755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this, file) 12330cf6095SLawrence D'Anna RedirectToFile(file.GetFile()); 12430cf6095SLawrence D'Anna } 12530cf6095SLawrence D'Anna 12630cf6095SLawrence D'Anna void SBStream::RedirectToFile(FileSP file_sp) { 1271755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this, file_sp); 12830cf6095SLawrence D'Anna 12930cf6095SLawrence D'Anna if (!file_sp || !file_sp->IsValid()) 130e2dcbd00SZachary Turner return; 131e2dcbd00SZachary Turner 132e2ae97f2SGreg Clayton std::string local_data; 133d5b44036SJonas Devlieghere if (m_opaque_up) { 134e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 135e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 136e2ae97f2SGreg Clayton if (!m_is_file) 137adcd0268SBenjamin Kramer local_data = std::string( 138adcd0268SBenjamin Kramer static_cast<StreamString *>(m_opaque_up.get())->GetString()); 139e2ae97f2SGreg Clayton } 140e2ae97f2SGreg Clayton 14130cf6095SLawrence D'Anna m_opaque_up = std::make_unique<StreamFile>(file_sp); 142e2ae97f2SGreg Clayton m_is_file = true; 143e2ae97f2SGreg Clayton 144e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 145e2ae97f2SGreg Clayton // the to new file we are redirecting to. 146e2ae97f2SGreg Clayton if (!local_data.empty()) 147d5b44036SJonas Devlieghere m_opaque_up->Write(&local_data[0], local_data.size()); 148e2ae97f2SGreg Clayton } 149e2ae97f2SGreg Clayton 150b9c1b51eSKate Stone void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { 1511755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this, fd, transfer_fh_ownership); 152baf5664fSJonas Devlieghere 153e2ae97f2SGreg Clayton std::string local_data; 154d5b44036SJonas Devlieghere if (m_opaque_up) { 155e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 156e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 157e2ae97f2SGreg Clayton if (!m_is_file) 158adcd0268SBenjamin Kramer local_data = std::string( 159adcd0268SBenjamin Kramer static_cast<StreamString *>(m_opaque_up.get())->GetString()); 160e2ae97f2SGreg Clayton } 161e2ae97f2SGreg Clayton 1622fce1137SLawrence D'Anna m_opaque_up = std::make_unique<StreamFile>(fd, transfer_fh_ownership); 163e2ae97f2SGreg Clayton m_is_file = true; 164e2ae97f2SGreg Clayton 165e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 166e2ae97f2SGreg Clayton // the to new file we are redirecting to. 167e2ae97f2SGreg Clayton if (!local_data.empty()) 168d5b44036SJonas Devlieghere m_opaque_up->Write(&local_data[0], local_data.size()); 169e2ae97f2SGreg Clayton } 170e2ae97f2SGreg Clayton 171d5b44036SJonas Devlieghere lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); } 172e2ae97f2SGreg Clayton 173d5b44036SJonas Devlieghere lldb_private::Stream *SBStream::get() { return m_opaque_up.get(); } 174e2ae97f2SGreg Clayton 175b9c1b51eSKate Stone lldb_private::Stream &SBStream::ref() { 176248a1305SKonrad Kleine if (m_opaque_up == nullptr) 1771c0bbe43SJonas Devlieghere m_opaque_up = std::make_unique<StreamString>(); 178d5b44036SJonas Devlieghere return *m_opaque_up; 179e2ae97f2SGreg Clayton } 180e2ae97f2SGreg Clayton 181b9c1b51eSKate Stone void SBStream::Clear() { 1821755f5b1SJonas Devlieghere LLDB_INSTRUMENT_VA(this); 183baf5664fSJonas Devlieghere 184d5b44036SJonas Devlieghere if (m_opaque_up) { 185e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 186e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 187e2ae97f2SGreg Clayton if (m_is_file) 188d5b44036SJonas Devlieghere m_opaque_up.reset(); 189e2ae97f2SGreg Clayton else 190d5b44036SJonas Devlieghere static_cast<StreamString *>(m_opaque_up.get())->Clear(); 191e2ae97f2SGreg Clayton } 192e2ae97f2SGreg Clayton } 193