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 { 73e2ae97f2SGreg Clayton std::string local_data; 74e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 75e2ae97f2SGreg Clayton { 76e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 77e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 78e2ae97f2SGreg Clayton if (!m_is_file) 79e2ae97f2SGreg Clayton local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 80e2ae97f2SGreg Clayton } 8151b1e2d2SGreg Clayton StreamFile *stream_file = new StreamFile; 8251b1e2d2SGreg Clayton uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 8351b1e2d2SGreg Clayton if (append) 8451b1e2d2SGreg Clayton open_options |= File::eOpenOptionAppend; 85*fbb76349SGreg Clayton stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault); 8651b1e2d2SGreg Clayton 8751b1e2d2SGreg Clayton m_opaque_ap.reset (stream_file); 88e2ae97f2SGreg Clayton 89e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 90e2ae97f2SGreg Clayton { 91e2ae97f2SGreg Clayton m_is_file = true; 92e2ae97f2SGreg Clayton 93e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 94e2ae97f2SGreg Clayton // the to new file we are redirecting to. 95e2ae97f2SGreg Clayton if (!local_data.empty()) 96e2ae97f2SGreg Clayton m_opaque_ap->Write (&local_data[0], local_data.size()); 97e2ae97f2SGreg Clayton } 98e2ae97f2SGreg Clayton else 99e2ae97f2SGreg Clayton m_is_file = false; 100e2ae97f2SGreg Clayton } 101e2ae97f2SGreg Clayton 102e2ae97f2SGreg Clayton void 103e2ae97f2SGreg Clayton SBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership) 104e2ae97f2SGreg Clayton { 105e2ae97f2SGreg Clayton std::string local_data; 106e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 107e2ae97f2SGreg Clayton { 108e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 109e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 110e2ae97f2SGreg Clayton if (!m_is_file) 111e2ae97f2SGreg Clayton local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 112e2ae97f2SGreg Clayton } 113e2ae97f2SGreg Clayton m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership)); 114e2ae97f2SGreg Clayton 115e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 116e2ae97f2SGreg Clayton { 117e2ae97f2SGreg Clayton m_is_file = true; 118e2ae97f2SGreg Clayton 119e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 120e2ae97f2SGreg Clayton // the to new file we are redirecting to. 121e2ae97f2SGreg Clayton if (!local_data.empty()) 122e2ae97f2SGreg Clayton m_opaque_ap->Write (&local_data[0], local_data.size()); 123e2ae97f2SGreg Clayton } 124e2ae97f2SGreg Clayton else 125e2ae97f2SGreg Clayton m_is_file = false; 126e2ae97f2SGreg Clayton } 127e2ae97f2SGreg Clayton 128e2ae97f2SGreg Clayton void 129e2ae97f2SGreg Clayton SBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership) 130e2ae97f2SGreg Clayton { 131e2ae97f2SGreg Clayton std::string local_data; 132e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 133e2ae97f2SGreg Clayton { 134e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 135e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 136e2ae97f2SGreg Clayton if (!m_is_file) 137e2ae97f2SGreg Clayton local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 138e2ae97f2SGreg Clayton } 139e2ae97f2SGreg Clayton 140e2ae97f2SGreg Clayton m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership)); 141e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 142e2ae97f2SGreg Clayton { 143e2ae97f2SGreg Clayton m_is_file = true; 144e2ae97f2SGreg Clayton 145e2ae97f2SGreg Clayton // If we had any data locally in our StreamString, then pass that along to 146e2ae97f2SGreg Clayton // the to new file we are redirecting to. 147e2ae97f2SGreg Clayton if (!local_data.empty()) 148e2ae97f2SGreg Clayton m_opaque_ap->Write (&local_data[0], local_data.size()); 149e2ae97f2SGreg Clayton } 150e2ae97f2SGreg Clayton else 151e2ae97f2SGreg Clayton m_is_file = false; 152e2ae97f2SGreg Clayton 153e2ae97f2SGreg Clayton } 154e2ae97f2SGreg Clayton 155e2ae97f2SGreg Clayton lldb_private::Stream * 156e2ae97f2SGreg Clayton SBStream::operator->() 157e2ae97f2SGreg Clayton { 158e2ae97f2SGreg Clayton return m_opaque_ap.get(); 159e2ae97f2SGreg Clayton } 160e2ae97f2SGreg Clayton 161e2ae97f2SGreg Clayton lldb_private::Stream * 162e2ae97f2SGreg Clayton SBStream::get() 163e2ae97f2SGreg Clayton { 164e2ae97f2SGreg Clayton return m_opaque_ap.get(); 165e2ae97f2SGreg Clayton } 166e2ae97f2SGreg Clayton 167e2ae97f2SGreg Clayton lldb_private::Stream & 168e2ae97f2SGreg Clayton SBStream::ref() 169e2ae97f2SGreg Clayton { 170e2ae97f2SGreg Clayton if (m_opaque_ap.get() == NULL) 171e2ae97f2SGreg Clayton m_opaque_ap.reset (new StreamString()); 172e2ae97f2SGreg Clayton return *m_opaque_ap.get(); 173e2ae97f2SGreg Clayton } 174e2ae97f2SGreg Clayton 175e2ae97f2SGreg Clayton void 176e2ae97f2SGreg Clayton SBStream::Clear () 177e2ae97f2SGreg Clayton { 178e2ae97f2SGreg Clayton if (m_opaque_ap.get()) 179e2ae97f2SGreg Clayton { 180e2ae97f2SGreg Clayton // See if we have any locally backed data. If so, copy it so we can then 181e2ae97f2SGreg Clayton // redirect it to the file so we don't lose the data 182e2ae97f2SGreg Clayton if (m_is_file) 183e2ae97f2SGreg Clayton m_opaque_ap.reset(); 184e2ae97f2SGreg Clayton else 185e2ae97f2SGreg Clayton static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear(); 186e2ae97f2SGreg Clayton } 187e2ae97f2SGreg Clayton } 188