1e2ae97f2SGreg Clayton //===-- SBStream.cpp ----------------------------------------*- C++ -*-===// 2e2ae97f2SGreg Clayton // 3e2ae97f2SGreg Clayton // The LLVM Compiler Infrastructure 4e2ae97f2SGreg Clayton // 5e2ae97f2SGreg Clayton // This file is distributed under the University of Illinois Open Source 6e2ae97f2SGreg Clayton // License. See LICENSE.TXT for details. 7e2ae97f2SGreg Clayton // 8e2ae97f2SGreg Clayton //===----------------------------------------------------------------------===// 9e2ae97f2SGreg Clayton 10e2ae97f2SGreg Clayton #include "lldb/API/SBStream.h" 11e2ae97f2SGreg Clayton 12e2ae97f2SGreg Clayton #include "lldb/Core/StreamFile.h" 13*50bc1ed2SJonas Devlieghere #include "lldb/Host/FileSystem.h" 1497206d57SZachary Turner #include "lldb/Utility/Status.h" 15bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 16bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 17e2ae97f2SGreg Clayton 18e2ae97f2SGreg Clayton using namespace lldb; 19e2ae97f2SGreg Clayton using namespace lldb_private; 20e2ae97f2SGreg Clayton 21b9c1b51eSKate Stone SBStream::SBStream() : m_opaque_ap(new StreamString()), m_is_file(false) {} 22e2ae97f2SGreg Clayton 23b9c1b51eSKate Stone SBStream::SBStream(SBStream &&rhs) 24b9c1b51eSKate Stone : m_opaque_ap(std::move(rhs.m_opaque_ap)), m_is_file(rhs.m_is_file) {} 250817da88SGreg Clayton 26b9c1b51eSKate Stone SBStream::~SBStream() {} 270817da88SGreg Clayton 28b9c1b51eSKate Stone bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); } 29e2ae97f2SGreg Clayton 3005097246SAdrian Prantl // If this stream is not redirected to a file, it will maintain a local cache 3105097246SAdrian Prantl // for the stream data which can be accessed using this accessor. 32b9c1b51eSKate Stone const char *SBStream::GetData() { 33e2ae97f2SGreg Clayton if (m_is_file || m_opaque_ap.get() == NULL) 34e2ae97f2SGreg Clayton return NULL; 35e2ae97f2SGreg Clayton 36e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 37e2ae97f2SGreg Clayton } 38e2ae97f2SGreg Clayton 3905097246SAdrian Prantl // If this stream is not redirected to a file, it will maintain a local cache 4005097246SAdrian Prantl // for the stream output whose length can be accessed using this accessor. 41b9c1b51eSKate Stone size_t SBStream::GetSize() { 42e2ae97f2SGreg Clayton if (m_is_file || m_opaque_ap.get() == NULL) 4360fd91ffSBill Wendling return 0; 44e2ae97f2SGreg Clayton 45e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 46e2ae97f2SGreg Clayton } 47e2ae97f2SGreg Clayton 48b9c1b51eSKate Stone void SBStream::Printf(const char *format, ...) { 494f8189bcSJohnny Chen if (!format) 504f8189bcSJohnny Chen return; 51e2ae97f2SGreg Clayton va_list args; 52e2ae97f2SGreg Clayton va_start(args, format); 53e2ae97f2SGreg Clayton ref().PrintfVarArg(format, args); 54e2ae97f2SGreg Clayton va_end(args); 55e2ae97f2SGreg Clayton } 56e2ae97f2SGreg Clayton 57b9c1b51eSKate Stone void SBStream::RedirectToFile(const char *path, bool append) { 58e2dcbd00SZachary Turner if (path == nullptr) 59e2dcbd00SZachary Turner return; 60e2dcbd00SZachary Turner 61e2ae97f2SGreg Clayton std::string local_data; 62b9c1b51eSKate Stone if (m_opaque_ap.get()) { 63e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 64e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 65e2ae97f2SGreg Clayton if (!m_is_file) 66c156427dSZachary Turner local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 67e2ae97f2SGreg Clayton } 6851b1e2d2SGreg Clayton StreamFile *stream_file = new StreamFile; 6951b1e2d2SGreg Clayton uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 7051b1e2d2SGreg Clayton if (append) 7151b1e2d2SGreg Clayton open_options |= File::eOpenOptionAppend; 7206357c93SGreg Clayton else 7306357c93SGreg Clayton open_options |= File::eOpenOptionTruncate; 7451b1e2d2SGreg Clayton 75*50bc1ed2SJonas Devlieghere FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path), 76*50bc1ed2SJonas Devlieghere open_options); 7751b1e2d2SGreg Clayton m_opaque_ap.reset(stream_file); 78e2ae97f2SGreg Clayton 79b9c1b51eSKate Stone if (m_opaque_ap.get()) { 80e2ae97f2SGreg Clayton m_is_file = true; 81e2ae97f2SGreg Clayton 82e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 83e2ae97f2SGreg Clayton // the to new file we are redirecting to. 84e2ae97f2SGreg Clayton if (!local_data.empty()) 85e2ae97f2SGreg Clayton m_opaque_ap->Write(&local_data[0], local_data.size()); 86b9c1b51eSKate Stone } else 87e2ae97f2SGreg Clayton m_is_file = false; 88e2ae97f2SGreg Clayton } 89e2ae97f2SGreg Clayton 90b9c1b51eSKate Stone void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { 91e2dcbd00SZachary Turner if (fh == nullptr) 92e2dcbd00SZachary Turner return; 93e2dcbd00SZachary Turner 94e2ae97f2SGreg Clayton std::string local_data; 95b9c1b51eSKate Stone if (m_opaque_ap.get()) { 96e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 97e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 98e2ae97f2SGreg Clayton if (!m_is_file) 99c156427dSZachary Turner local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 100e2ae97f2SGreg Clayton } 101e2ae97f2SGreg Clayton m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership)); 102e2ae97f2SGreg Clayton 103b9c1b51eSKate Stone if (m_opaque_ap.get()) { 104e2ae97f2SGreg Clayton m_is_file = true; 105e2ae97f2SGreg Clayton 106e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 107e2ae97f2SGreg Clayton // the to new file we are redirecting to. 108e2ae97f2SGreg Clayton if (!local_data.empty()) 109e2ae97f2SGreg Clayton m_opaque_ap->Write(&local_data[0], local_data.size()); 110b9c1b51eSKate Stone } else 111e2ae97f2SGreg Clayton m_is_file = false; 112e2ae97f2SGreg Clayton } 113e2ae97f2SGreg Clayton 114b9c1b51eSKate Stone void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { 115e2ae97f2SGreg Clayton std::string local_data; 116b9c1b51eSKate Stone if (m_opaque_ap.get()) { 117e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 118e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 119e2ae97f2SGreg Clayton if (!m_is_file) 120c156427dSZachary Turner local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 121e2ae97f2SGreg Clayton } 122e2ae97f2SGreg Clayton 123e2ae97f2SGreg Clayton m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership)); 124b9c1b51eSKate Stone if (m_opaque_ap.get()) { 125e2ae97f2SGreg Clayton m_is_file = true; 126e2ae97f2SGreg Clayton 127e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 128e2ae97f2SGreg Clayton // the to new file we are redirecting to. 129e2ae97f2SGreg Clayton if (!local_data.empty()) 130e2ae97f2SGreg Clayton m_opaque_ap->Write(&local_data[0], local_data.size()); 131b9c1b51eSKate Stone } else 132e2ae97f2SGreg Clayton m_is_file = false; 133e2ae97f2SGreg Clayton } 134e2ae97f2SGreg Clayton 135b9c1b51eSKate Stone lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); } 136e2ae97f2SGreg Clayton 137b9c1b51eSKate Stone lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); } 138e2ae97f2SGreg Clayton 139b9c1b51eSKate Stone lldb_private::Stream &SBStream::ref() { 140e2ae97f2SGreg Clayton if (m_opaque_ap.get() == NULL) 141e2ae97f2SGreg Clayton m_opaque_ap.reset(new StreamString()); 142e2ae97f2SGreg Clayton return *m_opaque_ap.get(); 143e2ae97f2SGreg Clayton } 144e2ae97f2SGreg Clayton 145b9c1b51eSKate Stone void SBStream::Clear() { 146b9c1b51eSKate Stone if (m_opaque_ap.get()) { 147e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 148e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 149e2ae97f2SGreg Clayton if (m_is_file) 150e2ae97f2SGreg Clayton m_opaque_ap.reset(); 151e2ae97f2SGreg Clayton else 152c156427dSZachary Turner static_cast<StreamString *>(m_opaque_ap.get())->Clear(); 153e2ae97f2SGreg Clayton } 154e2ae97f2SGreg Clayton } 155