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