1e2ae97f2SGreg Clayton //===-- SBStream.cpp ----------------------------------------*- C++ -*-===// 2e2ae97f2SGreg Clayton // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler 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 11e2ae97f2SGreg Clayton #include "lldb/Core/StreamFile.h" 1250bc1ed2SJonas Devlieghere #include "lldb/Host/FileSystem.h" 1397206d57SZachary Turner #include "lldb/Utility/Status.h" 14bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 15bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 16e2ae97f2SGreg Clayton 17e2ae97f2SGreg Clayton using namespace lldb; 18e2ae97f2SGreg Clayton using namespace lldb_private; 19e2ae97f2SGreg Clayton 20b9c1b51eSKate Stone SBStream::SBStream() : m_opaque_ap(new StreamString()), m_is_file(false) {} 21e2ae97f2SGreg Clayton 22b9c1b51eSKate Stone SBStream::SBStream(SBStream &&rhs) 23b9c1b51eSKate Stone : m_opaque_ap(std::move(rhs.m_opaque_ap)), m_is_file(rhs.m_is_file) {} 240817da88SGreg Clayton 25b9c1b51eSKate Stone SBStream::~SBStream() {} 260817da88SGreg Clayton 273447077aSJonas Devlieghere bool SBStream::IsValid() const { return (m_opaque_ap != NULL); } 28e2ae97f2SGreg Clayton 2905097246SAdrian Prantl // If this stream is not redirected to a file, it will maintain a local cache 3005097246SAdrian Prantl // for the stream data which can be accessed using this accessor. 31b9c1b51eSKate Stone const char *SBStream::GetData() { 323447077aSJonas Devlieghere if (m_is_file || m_opaque_ap == NULL) 33e2ae97f2SGreg Clayton return NULL; 34e2ae97f2SGreg Clayton 35e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 36e2ae97f2SGreg Clayton } 37e2ae97f2SGreg Clayton 3805097246SAdrian Prantl // If this stream is not redirected to a file, it will maintain a local cache 3905097246SAdrian Prantl // for the stream output whose length can be accessed using this accessor. 40b9c1b51eSKate Stone size_t SBStream::GetSize() { 413447077aSJonas Devlieghere if (m_is_file || m_opaque_ap == NULL) 4260fd91ffSBill Wendling return 0; 43e2ae97f2SGreg Clayton 44e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 45e2ae97f2SGreg Clayton } 46e2ae97f2SGreg Clayton 47b9c1b51eSKate Stone void SBStream::Printf(const char *format, ...) { 484f8189bcSJohnny Chen if (!format) 494f8189bcSJohnny Chen return; 50e2ae97f2SGreg Clayton va_list args; 51e2ae97f2SGreg Clayton va_start(args, format); 52e2ae97f2SGreg Clayton ref().PrintfVarArg(format, args); 53e2ae97f2SGreg Clayton va_end(args); 54e2ae97f2SGreg Clayton } 55e2ae97f2SGreg Clayton 56b9c1b51eSKate Stone void SBStream::RedirectToFile(const char *path, bool append) { 57e2dcbd00SZachary Turner if (path == nullptr) 58e2dcbd00SZachary Turner return; 59e2dcbd00SZachary Turner 60e2ae97f2SGreg Clayton std::string local_data; 613447077aSJonas Devlieghere if (m_opaque_ap) { 62e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 63e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 64e2ae97f2SGreg Clayton if (!m_is_file) 65c156427dSZachary Turner local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 66e2ae97f2SGreg Clayton } 6751b1e2d2SGreg Clayton StreamFile *stream_file = new StreamFile; 6851b1e2d2SGreg Clayton uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 6951b1e2d2SGreg Clayton if (append) 7051b1e2d2SGreg Clayton open_options |= File::eOpenOptionAppend; 7106357c93SGreg Clayton else 7206357c93SGreg Clayton open_options |= File::eOpenOptionTruncate; 7351b1e2d2SGreg Clayton 7450bc1ed2SJonas Devlieghere FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path), 7550bc1ed2SJonas Devlieghere open_options); 7651b1e2d2SGreg Clayton m_opaque_ap.reset(stream_file); 77e2ae97f2SGreg Clayton 783447077aSJonas Devlieghere if (m_opaque_ap) { 79e2ae97f2SGreg Clayton m_is_file = true; 80e2ae97f2SGreg Clayton 81e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 82e2ae97f2SGreg Clayton // the to new file we are redirecting to. 83e2ae97f2SGreg Clayton if (!local_data.empty()) 84e2ae97f2SGreg Clayton m_opaque_ap->Write(&local_data[0], local_data.size()); 85b9c1b51eSKate Stone } else 86e2ae97f2SGreg Clayton m_is_file = false; 87e2ae97f2SGreg Clayton } 88e2ae97f2SGreg Clayton 89b9c1b51eSKate Stone void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { 90e2dcbd00SZachary Turner if (fh == nullptr) 91e2dcbd00SZachary Turner return; 92e2dcbd00SZachary Turner 93e2ae97f2SGreg Clayton std::string local_data; 943447077aSJonas Devlieghere if (m_opaque_ap) { 95e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 96e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 97e2ae97f2SGreg Clayton if (!m_is_file) 98c156427dSZachary Turner local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 99e2ae97f2SGreg Clayton } 100e2ae97f2SGreg Clayton m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership)); 101e2ae97f2SGreg Clayton 1023447077aSJonas Devlieghere if (m_opaque_ap) { 103e2ae97f2SGreg Clayton m_is_file = true; 104e2ae97f2SGreg Clayton 105e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 106e2ae97f2SGreg Clayton // the to new file we are redirecting to. 107e2ae97f2SGreg Clayton if (!local_data.empty()) 108e2ae97f2SGreg Clayton m_opaque_ap->Write(&local_data[0], local_data.size()); 109b9c1b51eSKate Stone } else 110e2ae97f2SGreg Clayton m_is_file = false; 111e2ae97f2SGreg Clayton } 112e2ae97f2SGreg Clayton 113b9c1b51eSKate Stone void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { 114e2ae97f2SGreg Clayton std::string local_data; 1153447077aSJonas Devlieghere if (m_opaque_ap) { 116e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 117e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 118e2ae97f2SGreg Clayton if (!m_is_file) 119c156427dSZachary Turner local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 120e2ae97f2SGreg Clayton } 121e2ae97f2SGreg Clayton 122e2ae97f2SGreg Clayton m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership)); 1233447077aSJonas Devlieghere if (m_opaque_ap) { 124e2ae97f2SGreg Clayton m_is_file = true; 125e2ae97f2SGreg Clayton 126e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 127e2ae97f2SGreg Clayton // the to new file we are redirecting to. 128e2ae97f2SGreg Clayton if (!local_data.empty()) 129e2ae97f2SGreg Clayton m_opaque_ap->Write(&local_data[0], local_data.size()); 130b9c1b51eSKate Stone } else 131e2ae97f2SGreg Clayton m_is_file = false; 132e2ae97f2SGreg Clayton } 133e2ae97f2SGreg Clayton 134b9c1b51eSKate Stone lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); } 135e2ae97f2SGreg Clayton 136b9c1b51eSKate Stone lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); } 137e2ae97f2SGreg Clayton 138b9c1b51eSKate Stone lldb_private::Stream &SBStream::ref() { 1393447077aSJonas Devlieghere if (m_opaque_ap == NULL) 140e2ae97f2SGreg Clayton m_opaque_ap.reset(new StreamString()); 1413447077aSJonas Devlieghere return *m_opaque_ap; 142e2ae97f2SGreg Clayton } 143e2ae97f2SGreg Clayton 144b9c1b51eSKate Stone void SBStream::Clear() { 1453447077aSJonas Devlieghere if (m_opaque_ap) { 146e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 147e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 148e2ae97f2SGreg Clayton if (m_is_file) 149e2ae97f2SGreg Clayton m_opaque_ap.reset(); 150e2ae97f2SGreg Clayton else 151c156427dSZachary Turner static_cast<StreamString *>(m_opaque_ap.get())->Clear(); 152e2ae97f2SGreg Clayton } 153e2ae97f2SGreg Clayton } 154