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