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 20e2ae97f2SGreg Clayton SBStream::SBStream () : 21f6eaba85SJohnny Chen m_opaque_ap (new StreamString()), 22e2ae97f2SGreg Clayton m_is_file (false) 23e2ae97f2SGreg Clayton { 24e2ae97f2SGreg Clayton } 25e2ae97f2SGreg Clayton 26*0817da88SGreg Clayton SBStream::SBStream (SBStream &&rhs) : 27*0817da88SGreg Clayton m_opaque_ap (std::move(rhs.m_opaque_ap)), 28*0817da88SGreg Clayton m_is_file (rhs.m_is_file) 29*0817da88SGreg Clayton { 30*0817da88SGreg Clayton } 31*0817da88SGreg Clayton 32*0817da88SGreg Clayton 33e2ae97f2SGreg Clayton SBStream::~SBStream () 34e2ae97f2SGreg Clayton { 35e2ae97f2SGreg Clayton } 36e2ae97f2SGreg Clayton 37e2ae97f2SGreg Clayton bool 38e2ae97f2SGreg Clayton SBStream::IsValid() const 39e2ae97f2SGreg Clayton { 40e2ae97f2SGreg Clayton return (m_opaque_ap.get() != NULL); 41e2ae97f2SGreg Clayton } 42e2ae97f2SGreg Clayton 43e2ae97f2SGreg Clayton // If this stream is not redirected to a file, it will maintain a local 44e2ae97f2SGreg Clayton // cache for the stream data which can be accessed using this accessor. 45e2ae97f2SGreg Clayton const char * 46e2ae97f2SGreg Clayton SBStream::GetData () 47e2ae97f2SGreg Clayton { 48e2ae97f2SGreg Clayton if (m_is_file || m_opaque_ap.get() == NULL) 49e2ae97f2SGreg Clayton return NULL; 50e2ae97f2SGreg Clayton 51e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 52e2ae97f2SGreg Clayton } 53e2ae97f2SGreg Clayton 54e2ae97f2SGreg Clayton // If this stream is not redirected to a file, it will maintain a local 55e2ae97f2SGreg Clayton // cache for the stream output whose length can be accessed using this 56e2ae97f2SGreg Clayton // accessor. 57e2ae97f2SGreg Clayton size_t 58e2ae97f2SGreg Clayton SBStream::GetSize() 59e2ae97f2SGreg Clayton { 60e2ae97f2SGreg Clayton if (m_is_file || m_opaque_ap.get() == NULL) 6160fd91ffSBill Wendling return 0; 62e2ae97f2SGreg Clayton 63e2ae97f2SGreg Clayton return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 64e2ae97f2SGreg Clayton } 65e2ae97f2SGreg Clayton 66e2ae97f2SGreg Clayton void 67e2ae97f2SGreg Clayton SBStream::Printf (const char *format, ...) 68e2ae97f2SGreg Clayton { 694f8189bcSJohnny Chen if (!format) 704f8189bcSJohnny Chen return; 71e2ae97f2SGreg Clayton va_list args; 72e2ae97f2SGreg Clayton va_start (args, format); 73e2ae97f2SGreg Clayton ref().PrintfVarArg (format, args); 74e2ae97f2SGreg Clayton va_end (args); 75e2ae97f2SGreg Clayton } 76e2ae97f2SGreg Clayton 77e2ae97f2SGreg Clayton void 78e2ae97f2SGreg Clayton SBStream::RedirectToFile (const char *path, bool append) 79e2ae97f2SGreg Clayton { 80e2dcbd00SZachary Turner if (path == nullptr) 81e2dcbd00SZachary Turner return; 82e2dcbd00SZachary Turner 83e2ae97f2SGreg Clayton std::string local_data; 84e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 85e2ae97f2SGreg Clayton { 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) 89e2ae97f2SGreg Clayton local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 90e2ae97f2SGreg Clayton } 9151b1e2d2SGreg Clayton StreamFile *stream_file = new StreamFile; 9251b1e2d2SGreg Clayton uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 9351b1e2d2SGreg Clayton if (append) 9451b1e2d2SGreg Clayton open_options |= File::eOpenOptionAppend; 9506357c93SGreg Clayton else 9606357c93SGreg Clayton open_options |= File::eOpenOptionTruncate; 97fbb76349SGreg Clayton stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault); 9851b1e2d2SGreg Clayton 9951b1e2d2SGreg Clayton m_opaque_ap.reset (stream_file); 100e2ae97f2SGreg Clayton 101e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 102e2ae97f2SGreg Clayton { 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()); 109e2ae97f2SGreg Clayton } 110e2ae97f2SGreg Clayton else 111e2ae97f2SGreg Clayton m_is_file = false; 112e2ae97f2SGreg Clayton } 113e2ae97f2SGreg Clayton 114e2ae97f2SGreg Clayton void 115e2ae97f2SGreg Clayton SBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership) 116e2ae97f2SGreg Clayton { 117e2dcbd00SZachary Turner if (fh == nullptr) 118e2dcbd00SZachary Turner return; 119e2dcbd00SZachary Turner 120e2ae97f2SGreg Clayton std::string local_data; 121e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 122e2ae97f2SGreg Clayton { 123e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 124e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 125e2ae97f2SGreg Clayton if (!m_is_file) 126e2ae97f2SGreg Clayton local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 127e2ae97f2SGreg Clayton } 128e2ae97f2SGreg Clayton m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership)); 129e2ae97f2SGreg Clayton 130e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 131e2ae97f2SGreg Clayton { 132e2ae97f2SGreg Clayton m_is_file = true; 133e2ae97f2SGreg Clayton 134e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 135e2ae97f2SGreg Clayton // the to new file we are redirecting to. 136e2ae97f2SGreg Clayton if (!local_data.empty()) 137e2ae97f2SGreg Clayton m_opaque_ap->Write (&local_data[0], local_data.size()); 138e2ae97f2SGreg Clayton } 139e2ae97f2SGreg Clayton else 140e2ae97f2SGreg Clayton m_is_file = false; 141e2ae97f2SGreg Clayton } 142e2ae97f2SGreg Clayton 143e2ae97f2SGreg Clayton void 144e2ae97f2SGreg Clayton SBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership) 145e2ae97f2SGreg Clayton { 146e2ae97f2SGreg Clayton std::string local_data; 147e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 148e2ae97f2SGreg Clayton { 149e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 150e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 151e2ae97f2SGreg Clayton if (!m_is_file) 152e2ae97f2SGreg Clayton local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 153e2ae97f2SGreg Clayton } 154e2ae97f2SGreg Clayton 155e2ae97f2SGreg Clayton m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership)); 156e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 157e2ae97f2SGreg Clayton { 158e2ae97f2SGreg Clayton m_is_file = true; 159e2ae97f2SGreg Clayton 160e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 161e2ae97f2SGreg Clayton // the to new file we are redirecting to. 162e2ae97f2SGreg Clayton if (!local_data.empty()) 163e2ae97f2SGreg Clayton m_opaque_ap->Write (&local_data[0], local_data.size()); 164e2ae97f2SGreg Clayton } 165e2ae97f2SGreg Clayton else 166e2ae97f2SGreg Clayton m_is_file = false; 167e2ae97f2SGreg Clayton 168e2ae97f2SGreg Clayton } 169e2ae97f2SGreg Clayton 170e2ae97f2SGreg Clayton lldb_private::Stream * 171e2ae97f2SGreg Clayton SBStream::operator->() 172e2ae97f2SGreg Clayton { 173e2ae97f2SGreg Clayton return m_opaque_ap.get(); 174e2ae97f2SGreg Clayton } 175e2ae97f2SGreg Clayton 176e2ae97f2SGreg Clayton lldb_private::Stream * 177e2ae97f2SGreg Clayton SBStream::get() 178e2ae97f2SGreg Clayton { 179e2ae97f2SGreg Clayton return m_opaque_ap.get(); 180e2ae97f2SGreg Clayton } 181e2ae97f2SGreg Clayton 182e2ae97f2SGreg Clayton lldb_private::Stream & 183e2ae97f2SGreg Clayton SBStream::ref() 184e2ae97f2SGreg Clayton { 185e2ae97f2SGreg Clayton if (m_opaque_ap.get() == NULL) 186e2ae97f2SGreg Clayton m_opaque_ap.reset (new StreamString()); 187e2ae97f2SGreg Clayton return *m_opaque_ap.get(); 188e2ae97f2SGreg Clayton } 189e2ae97f2SGreg Clayton 190e2ae97f2SGreg Clayton void 191e2ae97f2SGreg Clayton SBStream::Clear () 192e2ae97f2SGreg Clayton { 193e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 194e2ae97f2SGreg Clayton { 195e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 196e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 197e2ae97f2SGreg Clayton if (m_is_file) 198e2ae97f2SGreg Clayton m_opaque_ap.reset(); 199e2ae97f2SGreg Clayton else 200e2ae97f2SGreg Clayton static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear(); 201e2ae97f2SGreg Clayton } 202e2ae97f2SGreg Clayton } 203