1ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton//===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
2ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton//
3ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton//                     The LLVM Compiler Infrastructure
4ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton//
5ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// This file is distributed under the University of Illinois Open Source
6ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// License. See LICENSE.TXT for details.
7ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton//
8ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton//===----------------------------------------------------------------------===//
9ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
10ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton#include "lldb/API/SBStream.h"
11ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
125892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton#include "lldb/Core/Error.h"
13ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton#include "lldb/Core/Stream.h"
14ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton#include "lldb/Core/StreamFile.h"
15ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton#include "lldb/Core/StreamString.h"
16ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
17ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonusing namespace lldb;
18ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonusing namespace lldb_private;
19ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
20ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::SBStream () :
21e5791dd89688683c9e1ec874b0be6906517e6827Johnny Chen    m_opaque_ap (new StreamString()),
22ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    m_is_file (false)
23ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
24ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
25ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
26ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::~SBStream ()
27ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
28ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
29ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
30ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonbool
31ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::IsValid() const
32ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
33ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    return (m_opaque_ap.get() != NULL);
34ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
35ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
36ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// If this stream is not redirected to a file, it will maintain a local
37ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// cache for the stream data which can be accessed using this accessor.
38ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonconst char *
39ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::GetData ()
40ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
41ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_is_file || m_opaque_ap.get() == NULL)
42ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        return NULL;
43ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
44ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
45ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
46ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
47ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// If this stream is not redirected to a file, it will maintain a local
48ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// cache for the stream output whose length can be accessed using this
49ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton// accessor.
50ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonsize_t
51ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::GetSize()
52ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
53ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_is_file || m_opaque_ap.get() == NULL)
54a9fe7e77bf7f1ec9793e685e2a01c7cc1b0c590cBill Wendling        return 0;
55ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
56ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
57ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
58ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
59ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonvoid
60ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::Printf (const char *format, ...)
61ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
624278bbed87590201f699769cdfbafcc5d6224c33Johnny Chen    if (!format)
634278bbed87590201f699769cdfbafcc5d6224c33Johnny Chen        return;
64ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    va_list args;
65ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    va_start (args, format);
66ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    ref().PrintfVarArg (format, args);
67ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    va_end (args);
68ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
69ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
70ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonvoid
71ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::RedirectToFile (const char *path, bool append)
72ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
73ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    std::string local_data;
74ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
75ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
76ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // See if we have any locally backed data. If so, copy it so we can then
77ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // redirect it to the file so we don't lose the data
78ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (!m_is_file)
79ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
80ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
815892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton    StreamFile *stream_file = new StreamFile;
825892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton    uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
835892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton    if (append)
845892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton        open_options |= File::eOpenOptionAppend;
855892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton    stream_file->GetFile().Open (path, open_options, File::ePermissionsDefault);
865892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton
875892856b0cd6591194c669afab5bf9ac19c5b3a0Greg Clayton    m_opaque_ap.reset (stream_file);
88ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
89ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
90ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
91ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_is_file = true;
92ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
93ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // If we had any data locally in our StreamString, then pass that along to
94ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // the to new file we are redirecting to.
95ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (!local_data.empty())
96ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            m_opaque_ap->Write (&local_data[0], local_data.size());
97ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
98ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    else
99ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_is_file = false;
100ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
101ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
102ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonvoid
103ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership)
104ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
105ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    std::string local_data;
106ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
107ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
108ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // See if we have any locally backed data. If so, copy it so we can then
109ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // redirect it to the file so we don't lose the data
110ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (!m_is_file)
111ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
112ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
113ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    m_opaque_ap.reset (new StreamFile (fh, transfer_fh_ownership));
114ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
115ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
116ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
117ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_is_file = true;
118ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
119ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // If we had any data locally in our StreamString, then pass that along to
120ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // the to new file we are redirecting to.
121ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (!local_data.empty())
122ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            m_opaque_ap->Write (&local_data[0], local_data.size());
123ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
124ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    else
125ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_is_file = false;
126ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
127ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
128ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonvoid
129ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::RedirectToFileDescriptor (int fd, bool transfer_fh_ownership)
130ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
131ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    std::string local_data;
132ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
133ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
134ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // See if we have any locally backed data. If so, copy it so we can then
135ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // redirect it to the file so we don't lose the data
136ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (!m_is_file)
137ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            local_data.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
138ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
139ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
140ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    m_opaque_ap.reset (new StreamFile (::fdopen (fd, "w"), transfer_fh_ownership));
141ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
142ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
143ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_is_file = true;
144ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
145ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // If we had any data locally in our StreamString, then pass that along to
146ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // the to new file we are redirecting to.
147ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (!local_data.empty())
148ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            m_opaque_ap->Write (&local_data[0], local_data.size());
149ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
150ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    else
151ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_is_file = false;
152ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
153ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
154ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
155ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonlldb_private::Stream *
156ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::operator->()
157ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
158ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    return m_opaque_ap.get();
159ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
160ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
161ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonlldb_private::Stream *
162ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::get()
163ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
164ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    return m_opaque_ap.get();
165ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
166ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
167ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonlldb_private::Stream &
168ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::ref()
169ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
170ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get() == NULL)
171ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        m_opaque_ap.reset (new StreamString());
172ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    return *m_opaque_ap.get();
173ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
174ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton
175ab7b39c679528fa2574430ec8035ee83d664acb8Greg Claytonvoid
176ab7b39c679528fa2574430ec8035ee83d664acb8Greg ClaytonSBStream::Clear ()
177ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton{
178ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    if (m_opaque_ap.get())
179ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    {
180ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // See if we have any locally backed data. If so, copy it so we can then
181ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        // redirect it to the file so we don't lose the data
182ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        if (m_is_file)
183ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            m_opaque_ap.reset();
184ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton        else
185ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton            static_cast<StreamString *>(m_opaque_ap.get())->GetString().clear();
186ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton    }
187ab7b39c679528fa2574430ec8035ee83d664acb8Greg Clayton}
188