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