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 30 // cache 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 39 // cache for the stream output whose length can be accessed using this 40 // accessor. 41 size_t SBStream::GetSize() { 42 if (m_is_file || m_opaque_ap.get() == NULL) 43 return 0; 44 45 return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 46 } 47 48 void SBStream::Printf(const char *format, ...) { 49 if (!format) 50 return; 51 va_list args; 52 va_start(args, format); 53 ref().PrintfVarArg(format, args); 54 va_end(args); 55 } 56 57 void SBStream::RedirectToFile(const char *path, bool append) { 58 if (path == nullptr) 59 return; 60 61 std::string local_data; 62 if (m_opaque_ap.get()) { 63 // See if we have any locally backed data. If so, copy it so we can then 64 // redirect it to the file so we don't lose the data 65 if (!m_is_file) 66 local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 67 } 68 StreamFile *stream_file = new StreamFile; 69 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 70 if (append) 71 open_options |= File::eOpenOptionAppend; 72 else 73 open_options |= File::eOpenOptionTruncate; 74 stream_file->GetFile().Open(path, open_options, 75 lldb::eFilePermissionsFileDefault); 76 77 m_opaque_ap.reset(stream_file); 78 79 if (m_opaque_ap.get()) { 80 m_is_file = true; 81 82 // If we had any data locally in our StreamString, then pass that along to 83 // the to new file we are redirecting to. 84 if (!local_data.empty()) 85 m_opaque_ap->Write(&local_data[0], local_data.size()); 86 } else 87 m_is_file = false; 88 } 89 90 void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) { 91 if (fh == nullptr) 92 return; 93 94 std::string local_data; 95 if (m_opaque_ap.get()) { 96 // See if we have any locally backed data. If so, copy it so we can then 97 // redirect it to the file so we don't lose the data 98 if (!m_is_file) 99 local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 100 } 101 m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership)); 102 103 if (m_opaque_ap.get()) { 104 m_is_file = true; 105 106 // If we had any data locally in our StreamString, then pass that along to 107 // the to new file we are redirecting to. 108 if (!local_data.empty()) 109 m_opaque_ap->Write(&local_data[0], local_data.size()); 110 } else 111 m_is_file = false; 112 } 113 114 void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) { 115 std::string local_data; 116 if (m_opaque_ap.get()) { 117 // See if we have any locally backed data. If so, copy it so we can then 118 // redirect it to the file so we don't lose the data 119 if (!m_is_file) 120 local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString(); 121 } 122 123 m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership)); 124 if (m_opaque_ap.get()) { 125 m_is_file = true; 126 127 // If we had any data locally in our StreamString, then pass that along to 128 // the to new file we are redirecting to. 129 if (!local_data.empty()) 130 m_opaque_ap->Write(&local_data[0], local_data.size()); 131 } else 132 m_is_file = false; 133 } 134 135 lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); } 136 137 lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); } 138 139 lldb_private::Stream &SBStream::ref() { 140 if (m_opaque_ap.get() == NULL) 141 m_opaque_ap.reset(new StreamString()); 142 return *m_opaque_ap.get(); 143 } 144 145 void SBStream::Clear() { 146 if (m_opaque_ap.get()) { 147 // See if we have any locally backed data. If so, copy it so we can then 148 // redirect it to the file so we don't lose the data 149 if (m_is_file) 150 m_opaque_ap.reset(); 151 else 152 static_cast<StreamString *>(m_opaque_ap.get())->Clear(); 153 } 154 } 155