1 //===-- SBStream.cpp ----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/API/SBStream.h" 11 12 #include "lldb/Core/StreamFile.h" 13 #include "lldb/Utility/Status.h" 14 #include "lldb/Utility/Stream.h" 15 #include "lldb/Utility/StreamString.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 SBStream::SBStream() : m_opaque_ap(new StreamString()), m_is_file(false) {} 21 22 SBStream::SBStream(SBStream &&rhs) 23 : m_opaque_ap(std::move(rhs.m_opaque_ap)), m_is_file(rhs.m_is_file) {} 24 25 SBStream::~SBStream() {} 26 27 bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); } 28 29 // If this stream is not redirected to a file, it will maintain a local cache 30 // for the stream data which can be accessed using this accessor. 31 const char *SBStream::GetData() { 32 if (m_is_file || m_opaque_ap.get() == NULL) 33 return NULL; 34 35 return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 36 } 37 38 // If this stream is not redirected to a file, it will maintain a local cache 39 // for the stream output whose length can be accessed using this accessor. 40 size_t SBStream::GetSize() { 41 if (m_is_file || m_opaque_ap.get() == NULL) 42 return 0; 43 44 return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 45 } 46 47 void SBStream::Printf(const char *format, ...) { 48 if (!format) 49 return; 50 va_list args; 51 va_start(args, format); 52 ref().PrintfVarArg(format, args); 53 va_end(args); 54 } 55 56 void SBStream::RedirectToFile(const char *path, bool append) { 57 if (path == nullptr) 58 return; 59 60 std::string local_data; 61 if (m_opaque_ap.get()) { 62 // See if we have any locally backed data. If so, copy it so we can then 63 // redirect it to the file so we don't lose the data 64 if (!m_is_file) 65 local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 66 } 67 StreamFile *stream_file = new StreamFile; 68 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 69 if (append) 70 open_options |= File::eOpenOptionAppend; 71 else 72 open_options |= File::eOpenOptionTruncate; 73 stream_file->GetFile().Open(path, open_options, 74 lldb::eFilePermissionsFileDefault); 75 76 m_opaque_ap.reset(stream_file); 77 78 if (m_opaque_ap.get()) { 79 m_is_file = true; 80 81 // If we had any data locally in our StreamString, then pass that along to 82 // the to new file we are redirecting to. 83 if (!local_data.empty()) 84 m_opaque_ap->Write(&local_data[0], local_data.size()); 85 } else 86 m_is_file = false; 87 } 88 89 void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { 90 if (fh == nullptr) 91 return; 92 93 std::string local_data; 94 if (m_opaque_ap.get()) { 95 // See if we have any locally backed data. If so, copy it so we can then 96 // redirect it to the file so we don't lose the data 97 if (!m_is_file) 98 local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 99 } 100 m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership)); 101 102 if (m_opaque_ap.get()) { 103 m_is_file = true; 104 105 // If we had any data locally in our StreamString, then pass that along to 106 // the to new file we are redirecting to. 107 if (!local_data.empty()) 108 m_opaque_ap->Write(&local_data[0], local_data.size()); 109 } else 110 m_is_file = false; 111 } 112 113 void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { 114 std::string local_data; 115 if (m_opaque_ap.get()) { 116 // See if we have any locally backed data. If so, copy it so we can then 117 // redirect it to the file so we don't lose the data 118 if (!m_is_file) 119 local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 120 } 121 122 m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership)); 123 if (m_opaque_ap.get()) { 124 m_is_file = true; 125 126 // If we had any data locally in our StreamString, then pass that along to 127 // the to new file we are redirecting to. 128 if (!local_data.empty()) 129 m_opaque_ap->Write(&local_data[0], local_data.size()); 130 } else 131 m_is_file = false; 132 } 133 134 lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); } 135 136 lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); } 137 138 lldb_private::Stream &SBStream::ref() { 139 if (m_opaque_ap.get() == NULL) 140 m_opaque_ap.reset(new StreamString()); 141 return *m_opaque_ap.get(); 142 } 143 144 void SBStream::Clear() { 145 if (m_opaque_ap.get()) { 146 // See if we have any locally backed data. If so, copy it so we can then 147 // redirect it to the file so we don't lose the data 148 if (m_is_file) 149 m_opaque_ap.reset(); 150 else 151 static_cast<StreamString *>(m_opaque_ap.get())->Clear(); 152 } 153 } 154