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