1254721Semaste//===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/API/SBStream.h"
11254721Semaste
12254721Semaste#include "lldb/Core/Error.h"
13254721Semaste#include "lldb/Core/Stream.h"
14254721Semaste#include "lldb/Core/StreamFile.h"
15254721Semaste#include "lldb/Core/StreamString.h"
16254721Semaste
17254721Semasteusing namespace lldb;
18254721Semasteusing namespace lldb_private;
19254721Semaste
20254721SemasteSBStream::SBStream () :
21254721Semaste    m_opaque_ap (new StreamString()),
22254721Semaste    m_is_file (false)
23254721Semaste{
24254721Semaste}
25254721Semaste
26254721SemasteSBStream::~SBStream ()
27254721Semaste{
28254721Semaste}
29254721Semaste
30254721Semastebool
31254721SemasteSBStream::IsValid() const
32254721Semaste{
33254721Semaste    return (m_opaque_ap.get() != NULL);
34254721Semaste}
35254721Semaste
36254721Semaste// If this stream is not redirected to a file, it will maintain a local
37254721Semaste// cache for the stream data which can be accessed using this accessor.
38254721Semasteconst char *
39254721SemasteSBStream::GetData ()
40254721Semaste{
41254721Semaste    if (m_is_file || m_opaque_ap.get() == NULL)
42254721Semaste        return NULL;
43254721Semaste
44254721Semaste    return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
45254721Semaste}
46254721Semaste
47254721Semaste// If this stream is not redirected to a file, it will maintain a local
48254721Semaste// cache for the stream output whose length can be accessed using this
49254721Semaste// accessor.
50254721Semastesize_t
51254721SemasteSBStream::GetSize()
52254721Semaste{
53254721Semaste    if (m_is_file || m_opaque_ap.get() == NULL)
54254721Semaste        return 0;
55254721Semaste
56254721Semaste    return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
57254721Semaste}
58254721Semaste
59254721Semastevoid
60254721SemasteSBStream::Printf (const char *format, ...)
61254721Semaste{
62254721Semaste    if (!format)
63254721Semaste        return;
64254721Semaste    va_list args;
65254721Semaste    va_start (args, format);
66254721Semaste    ref().PrintfVarArg (format, args);
67254721Semaste    va_end (args);
68254721Semaste}
69254721Semaste
70254721Semastevoid
71254721SemasteSBStream::RedirectToFile (const char *path, bool append)
72254721Semaste{
73254721Semaste    std::string local_data;
74254721Semaste    if (m_opaque_ap.get())
75254721Semaste    {
76254721Semaste        // See if we have any locally backed data. If so, copy it so we can then
77254721Semaste        // redirect it to the file so we don't lose the data
78254721Semaste        if (!m_is_file)
79254721Semaste            local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
80254721Semaste    }
81254721Semaste    StreamFile *stream_file = new StreamFile;
82254721Semaste    uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
83254721Semaste    if (append)
84254721Semaste        open_options |= File::eOpenOptionAppend;
85263367Semaste    stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault);
86254721Semaste
87254721Semaste    m_opaque_ap.reset (stream_file);
88254721Semaste
89254721Semaste    if (m_opaque_ap.get())
90254721Semaste    {
91254721Semaste        m_is_file = true;
92254721Semaste
93254721Semaste        // If we had any data locally in our StreamString, then pass that along to
94254721Semaste        // the to new file we are redirecting to.
95254721Semaste        if (!local_data.empty())
96254721Semaste            m_opaque_ap->Write (&local_data[0], local_data.size());
97254721Semaste    }
98254721Semaste    else
99254721Semaste        m_is_file = false;
100254721Semaste}
101254721Semaste
102254721Semastevoid
103254721SemasteSBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership)
104254721Semaste{
105254721Semaste    std::string local_data;
106254721Semaste    if (m_opaque_ap.get())
107254721Semaste    {
108254721Semaste        // See if we have any locally backed data. If so, copy it so we can then
109254721Semaste        // redirect it to the file so we don't lose the data
110254721Semaste        if (!m_is_file)
111254721Semaste            local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
112254721Semaste    }
113254721Semaste    m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership));
114254721Semaste
115254721Semaste    if (m_opaque_ap.get())
116254721Semaste    {
117254721Semaste        m_is_file = true;
118254721Semaste
119254721Semaste        // If we had any data locally in our StreamString, then pass that along to
120254721Semaste        // the to new file we are redirecting to.
121254721Semaste        if (!local_data.empty())
122254721Semaste            m_opaque_ap->Write (&local_data[0], local_data.size());
123254721Semaste    }
124254721Semaste    else
125254721Semaste        m_is_file = false;
126254721Semaste}
127254721Semaste
128254721Semastevoid
129254721SemasteSBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership)
130254721Semaste{
131254721Semaste    std::string local_data;
132254721Semaste    if (m_opaque_ap.get())
133254721Semaste    {
134254721Semaste        // See if we have any locally backed data. If so, copy it so we can then
135254721Semaste        // redirect it to the file so we don't lose the data
136254721Semaste        if (!m_is_file)
137254721Semaste            local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
138254721Semaste    }
139254721Semaste
140254721Semaste    m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership));
141254721Semaste    if (m_opaque_ap.get())
142254721Semaste    {
143254721Semaste        m_is_file = true;
144254721Semaste
145254721Semaste        // If we had any data locally in our StreamString, then pass that along to
146254721Semaste        // the to new file we are redirecting to.
147254721Semaste        if (!local_data.empty())
148254721Semaste            m_opaque_ap->Write (&local_data[0], local_data.size());
149254721Semaste    }
150254721Semaste    else
151254721Semaste        m_is_file = false;
152254721Semaste
153254721Semaste}
154254721Semaste
155254721Semastelldb_private::Stream *
156254721SemasteSBStream::operator->()
157254721Semaste{
158254721Semaste    return m_opaque_ap.get();
159254721Semaste}
160254721Semaste
161254721Semastelldb_private::Stream *
162254721SemasteSBStream::get()
163254721Semaste{
164254721Semaste    return m_opaque_ap.get();
165254721Semaste}
166254721Semaste
167254721Semastelldb_private::Stream &
168254721SemasteSBStream::ref()
169254721Semaste{
170254721Semaste    if (m_opaque_ap.get() == NULL)
171254721Semaste        m_opaque_ap.reset (new StreamString());
172254721Semaste    return *m_opaque_ap.get();
173254721Semaste}
174254721Semaste
175254721Semastevoid
176254721SemasteSBStream::Clear ()
177254721Semaste{
178254721Semaste    if (m_opaque_ap.get())
179254721Semaste    {
180254721Semaste        // See if we have any locally backed data. If so, copy it so we can then
181254721Semaste        // redirect it to the file so we don't lose the data
182254721Semaste        if (m_is_file)
183254721Semaste            m_opaque_ap.reset();
184254721Semaste        else
185254721Semaste            static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear();
186254721Semaste    }
187254721Semaste}
188