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 NULL; 55 56 return static_cast<StreamString *>(m_opaque_ap.get())->GetSize(); 57 } 58 59 void 60 SBStream::Printf (const char *format, ...) 61 { 62 va_list args; 63 va_start (args, format); 64 ref().PrintfVarArg (format, args); 65 va_end (args); 66 } 67 68 void 69 SBStream::RedirectToFile (const char *path, bool append) 70 { 71 std::string local_data; 72 if (m_opaque_ap.get()) 73 { 74 // See if we have any locally backed data. If so, copy it so we can then 75 // redirect it to the file so we don't lose the data 76 if (!m_is_file) 77 local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 78 } 79 StreamFile *stream_file = new StreamFile; 80 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; 81 if (append) 82 open_options |= File::eOpenOptionAppend; 83 stream_file->GetFile().Open (path, open_options, File::ePermissionsDefault); 84 85 m_opaque_ap.reset (stream_file); 86 87 if (m_opaque_ap.get()) 88 { 89 m_is_file = true; 90 91 // If we had any data locally in our StreamString, then pass that along to 92 // the to new file we are redirecting to. 93 if (!local_data.empty()) 94 m_opaque_ap->Write (&local_data[0], local_data.size()); 95 } 96 else 97 m_is_file = false; 98 } 99 100 void 101 SBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership) 102 { 103 std::string local_data; 104 if (m_opaque_ap.get()) 105 { 106 // See if we have any locally backed data. If so, copy it so we can then 107 // redirect it to the file so we don't lose the data 108 if (!m_is_file) 109 local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 110 } 111 m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership)); 112 113 if (m_opaque_ap.get()) 114 { 115 m_is_file = true; 116 117 // If we had any data locally in our StreamString, then pass that along to 118 // the to new file we are redirecting to. 119 if (!local_data.empty()) 120 m_opaque_ap->Write (&local_data[0], local_data.size()); 121 } 122 else 123 m_is_file = false; 124 } 125 126 void 127 SBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership) 128 { 129 std::string local_data; 130 if (m_opaque_ap.get()) 131 { 132 // See if we have any locally backed data. If so, copy it so we can then 133 // redirect it to the file so we don't lose the data 134 if (!m_is_file) 135 local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString()); 136 } 137 138 m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership)); 139 if (m_opaque_ap.get()) 140 { 141 m_is_file = true; 142 143 // If we had any data locally in our StreamString, then pass that along to 144 // the to new file we are redirecting to. 145 if (!local_data.empty()) 146 m_opaque_ap->Write (&local_data[0], local_data.size()); 147 } 148 else 149 m_is_file = false; 150 151 } 152 153 lldb_private::Stream * 154 SBStream::operator->() 155 { 156 return m_opaque_ap.get(); 157 } 158 159 lldb_private::Stream * 160 SBStream::get() 161 { 162 return m_opaque_ap.get(); 163 } 164 165 lldb_private::Stream & 166 SBStream::ref() 167 { 168 if (m_opaque_ap.get() == NULL) 169 m_opaque_ap.reset (new StreamString()); 170 return *m_opaque_ap.get(); 171 } 172 173 void 174 SBStream::Clear () 175 { 176 if (m_opaque_ap.get()) 177 { 178 // See if we have any locally backed data. If so, copy it so we can then 179 // redirect it to the file so we don't lose the data 180 if (m_is_file) 181 m_opaque_ap.reset(); 182 else 183 static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear(); 184 } 185 } 186