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