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