1254721Semaste//===-- SBStream.cpp ----------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/API/SBStream.h" 11254721Semaste 12254721Semaste#include "lldb/Core/Error.h" 13254721Semaste#include "lldb/Core/Stream.h" 14254721Semaste#include "lldb/Core/StreamFile.h" 15254721Semaste#include "lldb/Core/StreamString.h" 16254721Semaste 17254721Semasteusing namespace lldb; 18254721Semasteusing namespace lldb_private; 19254721Semaste 20254721SemasteSBStream::SBStream () : 21254721Semaste m_opaque_ap (new StreamString()), 22254721Semaste m_is_file (false) 23254721Semaste{ 24254721Semaste} 25254721Semaste 26254721SemasteSBStream::~SBStream () 27254721Semaste{ 28254721Semaste} 29254721Semaste 30254721Semastebool 31254721SemasteSBStream::IsValid() const 32254721Semaste{ 33254721Semaste return (m_opaque_ap.get() != NULL); 34254721Semaste} 35254721Semaste 36254721Semaste// If this stream is not redirected to a file, it will maintain a local 37254721Semaste// cache for the stream data which can be accessed using this accessor. 38254721Semasteconst char * 39254721SemasteSBStream::GetData () 40254721Semaste{ 41254721Semaste if (m_is_file || m_opaque_ap.get() == NULL) 42254721Semaste return NULL; 43254721Semaste 44254721Semaste return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 45254721Semaste} 46254721Semaste 47254721Semaste// If this stream is not redirected to a file, it will maintain a local 48254721Semaste// cache for the stream output whose length can be accessed using this 49254721Semaste// accessor. 50254721Semastesize_t 51254721SemasteSBStream::GetSize() 52254721Semaste{ 53254721Semaste if (m_is_file || m_opaque_ap.get() == NULL) 54254721Semaste return 0; 55254721Semaste 56254721Semaste return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 57254721Semaste} 58254721Semaste 59254721Semastevoid 60254721SemasteSBStream::Printf (const char *format, ...) 61254721Semaste{ 62254721Semaste if (!format) 63254721Semaste return; 64254721Semaste va_list args; 65254721Semaste va_start (args, format); 66254721Semaste ref().PrintfVarArg (format, args); 67254721Semaste va_end (args); 68254721Semaste} 69254721Semaste 70254721Semastevoid 71254721SemasteSBStream::RedirectToFile (const char *path, bool append) 72254721Semaste{ 73254721Semaste std::string local_data; 74254721Semaste if (m_opaque_ap.get()) 75254721Semaste { 76254721Semaste // See if we have any locally backed data. If so, copy it so we can then 77254721Semaste // redirect it to the file so we don't lose the data 78254721Semaste if (!m_is_file) 79254721Semaste local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 80254721Semaste } 81254721Semaste StreamFile *stream_file = new StreamFile; 82254721Semaste uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 83254721Semaste if (append) 84254721Semaste open_options |= File::eOpenOptionAppend; 85263367Semaste stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault); 86254721Semaste 87254721Semaste m_opaque_ap.reset (stream_file); 88254721Semaste 89254721Semaste if (m_opaque_ap.get()) 90254721Semaste { 91254721Semaste m_is_file = true; 92254721Semaste 93254721Semaste // If we had any data locally in our StreamString, then pass that along to 94254721Semaste // the to new file we are redirecting to. 95254721Semaste if (!local_data.empty()) 96254721Semaste m_opaque_ap->Write (&local_data[0], local_data.size()); 97254721Semaste } 98254721Semaste else 99254721Semaste m_is_file = false; 100254721Semaste} 101254721Semaste 102254721Semastevoid 103254721SemasteSBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership) 104254721Semaste{ 105254721Semaste std::string local_data; 106254721Semaste if (m_opaque_ap.get()) 107254721Semaste { 108254721Semaste // See if we have any locally backed data. If so, copy it so we can then 109254721Semaste // redirect it to the file so we don't lose the data 110254721Semaste if (!m_is_file) 111254721Semaste local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 112254721Semaste } 113254721Semaste m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership)); 114254721Semaste 115254721Semaste if (m_opaque_ap.get()) 116254721Semaste { 117254721Semaste m_is_file = true; 118254721Semaste 119254721Semaste // If we had any data locally in our StreamString, then pass that along to 120254721Semaste // the to new file we are redirecting to. 121254721Semaste if (!local_data.empty()) 122254721Semaste m_opaque_ap->Write (&local_data[0], local_data.size()); 123254721Semaste } 124254721Semaste else 125254721Semaste m_is_file = false; 126254721Semaste} 127254721Semaste 128254721Semastevoid 129254721SemasteSBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership) 130254721Semaste{ 131254721Semaste std::string local_data; 132254721Semaste if (m_opaque_ap.get()) 133254721Semaste { 134254721Semaste // See if we have any locally backed data. If so, copy it so we can then 135254721Semaste // redirect it to the file so we don't lose the data 136254721Semaste if (!m_is_file) 137254721Semaste local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 138254721Semaste } 139254721Semaste 140254721Semaste m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership)); 141254721Semaste if (m_opaque_ap.get()) 142254721Semaste { 143254721Semaste m_is_file = true; 144254721Semaste 145254721Semaste // If we had any data locally in our StreamString, then pass that along to 146254721Semaste // the to new file we are redirecting to. 147254721Semaste if (!local_data.empty()) 148254721Semaste m_opaque_ap->Write (&local_data[0], local_data.size()); 149254721Semaste } 150254721Semaste else 151254721Semaste m_is_file = false; 152254721Semaste 153254721Semaste} 154254721Semaste 155254721Semastelldb_private::Stream * 156254721SemasteSBStream::operator->() 157254721Semaste{ 158254721Semaste return m_opaque_ap.get(); 159254721Semaste} 160254721Semaste 161254721Semastelldb_private::Stream * 162254721SemasteSBStream::get() 163254721Semaste{ 164254721Semaste return m_opaque_ap.get(); 165254721Semaste} 166254721Semaste 167254721Semastelldb_private::Stream & 168254721SemasteSBStream::ref() 169254721Semaste{ 170254721Semaste if (m_opaque_ap.get() == NULL) 171254721Semaste m_opaque_ap.reset (new StreamString()); 172254721Semaste return *m_opaque_ap.get(); 173254721Semaste} 174254721Semaste 175254721Semastevoid 176254721SemasteSBStream::Clear () 177254721Semaste{ 178254721Semaste if (m_opaque_ap.get()) 179254721Semaste { 180254721Semaste // See if we have any locally backed data. If so, copy it so we can then 181254721Semaste // redirect it to the file so we don't lose the data 182254721Semaste if (m_is_file) 183254721Semaste m_opaque_ap.reset(); 184254721Semaste else 185254721Semaste static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear(); 186254721Semaste } 187254721Semaste} 188