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 1251b1e2d2SGreg Clayton #include "lldb/Core/Error.h" 13e2ae97f2SGreg Clayton #include "lldb/Core/Stream.h" 14e2ae97f2SGreg Clayton #include "lldb/Core/StreamFile.h" 15e2ae97f2SGreg Clayton #include "lldb/Core/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 27b9c1b51eSKate Stone bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); } 28e2ae97f2SGreg Clayton 29e2ae97f2SGreg Clayton // If this stream is not redirected to a file, it will maintain a local 30e2ae97f2SGreg Clayton // cache for the stream data which can be accessed using this accessor. 31b9c1b51eSKate Stone const char *SBStream::GetData() { 32e2ae97f2SGreg Clayton if (m_is_file || m_opaque_ap.get() == NULL) 33e2ae97f2SGreg Clayton return NULL; 34e2ae97f2SGreg Clayton 35e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 36e2ae97f2SGreg Clayton } 37e2ae97f2SGreg Clayton 38e2ae97f2SGreg Clayton // If this stream is not redirected to a file, it will maintain a local 39e2ae97f2SGreg Clayton // cache for the stream output whose length can be accessed using this 40e2ae97f2SGreg Clayton // 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) 66*c156427dSZachary 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; 74b9c1b51eSKate Stone stream_file->GetFile().Open(path, open_options, 75b9c1b51eSKate Stone lldb::eFilePermissionsFileDefault); 7651b1e2d2SGreg Clayton 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) 99*c156427dSZachary 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) 120*c156427dSZachary 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 152*c156427dSZachary Turner static_cast<StreamString *>(m_opaque_ap.get())->Clear(); 153e2ae97f2SGreg Clayton } 154e2ae97f2SGreg Clayton } 155