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/Error.h" 13 #include "lldb/Core/Stream.h" 14 #include "lldb/Core/StreamFile.h" 15 #include "lldb/Core/StreamString.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 SBStream::SBStream () : 21 m_opaque_ap (new StreamString()), 22 m_is_file (false) 23 { 24 } 25 26 SBStream::SBStream (SBStream &&rhs) : 27 m_opaque_ap (std::move(rhs.m_opaque_ap)), 28 m_is_file (rhs.m_is_file) 29 { 30 } 31 32 33 SBStream::~SBStream () 34 { 35 } 36 37 bool 38 SBStream::IsValid() const 39 { 40 return (m_opaque_ap.get() != NULL); 41 } 42 43 // If this stream is not redirected to a file, it will maintain a local 44 // cache for the stream data which can be accessed using this accessor. 45 const char * 46 SBStream::GetData () 47 { 48 if (m_is_file || m_opaque_ap.get() == NULL) 49 return NULL; 50 51 return static_cast<StreamString *>(m_opaque_ap.get())->GetData(); 52 } 53 54 // If this stream is not redirected to a file, it will maintain a local 55 // cache for the stream output whose length can be accessed using this 56 // accessor. 57 size_t 58 SBStream::GetSize() 59 { 60 if (m_is_file || m_opaque_ap.get() == NULL) 61 return 0; 62 63 return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 64 } 65 66 void 67 SBStream::Printf (const char *format, ...) 68 { 69 if (!format) 70 return; 71 va_list args; 72 va_start (args, format); 73 ref().PrintfVarArg (format, args); 74 va_end (args); 75 } 76 77 void 78 SBStream::RedirectToFile (const char *path, bool append) 79 { 80 if (path == nullptr) 81 return; 82 83 std::string local_data; 84 if (m_opaque_ap.get()) 85 { 86 // See if we have any locally backed data. If so, copy it so we can then 87 // redirect it to the file so we don't lose the data 88 if (!m_is_file) 89 local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 90 } 91 StreamFile *stream_file = new StreamFile; 92 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 93 if (append) 94 open_options |= File::eOpenOptionAppend; 95 else 96 open_options |= File::eOpenOptionTruncate; 97 stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault); 98 99 m_opaque_ap.reset (stream_file); 100 101 if (m_opaque_ap.get()) 102 { 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 } 110 else 111 m_is_file = false; 112 } 113 114 void 115 SBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership) 116 { 117 if (fh == nullptr) 118 return; 119 120 std::string local_data; 121 if (m_opaque_ap.get()) 122 { 123 // See if we have any locally backed data. If so, copy it so we can then 124 // redirect it to the file so we don't lose the data 125 if (!m_is_file) 126 local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 127 } 128 m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership)); 129 130 if (m_opaque_ap.get()) 131 { 132 m_is_file = true; 133 134 // If we had any data locally in our StreamString, then pass that along to 135 // the to new file we are redirecting to. 136 if (!local_data.empty()) 137 m_opaque_ap->Write (&local_data[0], local_data.size()); 138 } 139 else 140 m_is_file = false; 141 } 142 143 void 144 SBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership) 145 { 146 std::string local_data; 147 if (m_opaque_ap.get()) 148 { 149 // See if we have any locally backed data. If so, copy it so we can then 150 // redirect it to the file so we don't lose the data 151 if (!m_is_file) 152 local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 153 } 154 155 m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership)); 156 if (m_opaque_ap.get()) 157 { 158 m_is_file = true; 159 160 // If we had any data locally in our StreamString, then pass that along to 161 // the to new file we are redirecting to. 162 if (!local_data.empty()) 163 m_opaque_ap->Write (&local_data[0], local_data.size()); 164 } 165 else 166 m_is_file = false; 167 168 } 169 170 lldb_private::Stream * 171 SBStream::operator->() 172 { 173 return m_opaque_ap.get(); 174 } 175 176 lldb_private::Stream * 177 SBStream::get() 178 { 179 return m_opaque_ap.get(); 180 } 181 182 lldb_private::Stream & 183 SBStream::ref() 184 { 185 if (m_opaque_ap.get() == NULL) 186 m_opaque_ap.reset (new StreamString()); 187 return *m_opaque_ap.get(); 188 } 189 190 void 191 SBStream::Clear () 192 { 193 if (m_opaque_ap.get()) 194 { 195 // See if we have any locally backed data. If so, copy it so we can then 196 // redirect it to the file so we don't lose the data 197 if (m_is_file) 198 m_opaque_ap.reset(); 199 else 200 static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear(); 201 } 202 } 203