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