LLDB  mainline
SBStream.cpp
Go to the documentation of this file.
1 //===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/API/SBStream.h"
10 
11 #include "SBReproducerPrivate.h"
12 #include "lldb/Core/StreamFile.h"
13 #include "lldb/Host/FileSystem.h"
14 #include "lldb/Utility/Status.h"
15 #include "lldb/Utility/Stream.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 SBStream::SBStream() : m_opaque_up(new StreamString()), m_is_file(false) {
23 }
24 
26  : m_opaque_up(std::move(rhs.m_opaque_up)), m_is_file(rhs.m_is_file) {}
27 
29 
30 bool SBStream::IsValid() const {
32  return this->operator bool();
33 }
34 SBStream::operator bool() const {
35  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStream, operator bool);
36 
37  return (m_opaque_up != NULL);
38 }
39 
40 // If this stream is not redirected to a file, it will maintain a local cache
41 // for the stream data which can be accessed using this accessor.
42 const char *SBStream::GetData() {
44 
45  if (m_is_file || m_opaque_up == NULL)
46  return NULL;
47 
48  return static_cast<StreamString *>(m_opaque_up.get())->GetData();
49 }
50 
51 // If this stream is not redirected to a file, it will maintain a local cache
52 // for the stream output whose length can be accessed using this accessor.
55 
56  if (m_is_file || m_opaque_up == NULL)
57  return 0;
58 
59  return static_cast<StreamString *>(m_opaque_up.get())->GetSize();
60 }
61 
62 void SBStream::Printf(const char *format, ...) {
63  if (!format)
64  return;
65  va_list args;
66  va_start(args, format);
67  ref().PrintfVarArg(format, args);
68  va_end(args);
69 }
70 
71 void SBStream::RedirectToFile(const char *path, bool append) {
72  LLDB_RECORD_METHOD(void, SBStream, RedirectToFile, (const char *, bool), path,
73  append);
74 
75  if (path == nullptr)
76  return;
77 
78  std::string local_data;
79  if (m_opaque_up) {
80  // See if we have any locally backed data. If so, copy it so we can then
81  // redirect it to the file so we don't lose the data
82  if (!m_is_file)
83  local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
84  }
85  StreamFile *stream_file = new StreamFile;
86  uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
87  if (append)
88  open_options |= File::eOpenOptionAppend;
89  else
90  open_options |= File::eOpenOptionTruncate;
91 
92  FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path),
93  open_options);
94  m_opaque_up.reset(stream_file);
95 
96  if (m_opaque_up) {
97  m_is_file = true;
98 
99  // If we had any data locally in our StreamString, then pass that along to
100  // the to new file we are redirecting to.
101  if (!local_data.empty())
102  m_opaque_up->Write(&local_data[0], local_data.size());
103  } else
104  m_is_file = false;
105 }
106 
107 void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
108  LLDB_RECORD_METHOD(void, SBStream, RedirectToFileHandle, (FILE *, bool), fh,
109  transfer_fh_ownership);
110 
111  if (fh == nullptr)
112  return;
113 
114  std::string local_data;
115  if (m_opaque_up) {
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 = static_cast<StreamString *>(m_opaque_up.get())->GetString();
120  }
121  m_opaque_up.reset(new StreamFile(fh, transfer_fh_ownership));
122 
123  if (m_opaque_up) {
124  m_is_file = true;
125 
126  // If we had any data locally in our StreamString, then pass that along to
127  // the to new file we are redirecting to.
128  if (!local_data.empty())
129  m_opaque_up->Write(&local_data[0], local_data.size());
130  } else
131  m_is_file = false;
132 }
133 
134 void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
135  LLDB_RECORD_METHOD(void, SBStream, RedirectToFileDescriptor, (int, bool), fd,
136  transfer_fh_ownership);
137 
138  std::string local_data;
139  if (m_opaque_up) {
140  // See if we have any locally backed data. If so, copy it so we can then
141  // redirect it to the file so we don't lose the data
142  if (!m_is_file)
143  local_data = static_cast<StreamString *>(m_opaque_up.get())->GetString();
144  }
145 
146  m_opaque_up.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
147  if (m_opaque_up) {
148  m_is_file = true;
149 
150  // If we had any data locally in our StreamString, then pass that along to
151  // the to new file we are redirecting to.
152  if (!local_data.empty())
153  m_opaque_up->Write(&local_data[0], local_data.size());
154  } else
155  m_is_file = false;
156 }
157 
158 lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); }
159 
160 lldb_private::Stream *SBStream::get() { return m_opaque_up.get(); }
161 
163  if (m_opaque_up == NULL)
164  m_opaque_up.reset(new StreamString());
165  return *m_opaque_up;
166 }
167 
170 
171  if (m_opaque_up) {
172  // See if we have any locally backed data. If so, copy it so we can then
173  // redirect it to the file so we don't lose the data
174  if (m_is_file)
175  m_opaque_up.reset();
176  else
177  static_cast<StreamString *>(m_opaque_up.get())->Clear();
178  }
179 }
180 
181 namespace lldb_private {
182 namespace repro {
183 
184 template <>
188  LLDB_REGISTER_METHOD_CONST(bool, SBStream, operator bool, ());
189  LLDB_REGISTER_METHOD(const char *, SBStream, GetData, ());
190  LLDB_REGISTER_METHOD(size_t, SBStream, GetSize, ());
191  LLDB_REGISTER_METHOD(void, SBStream, RedirectToFile, (const char *, bool));
192  LLDB_REGISTER_METHOD(void, SBStream, RedirectToFileHandle, (FILE *, bool));
194  LLDB_REGISTER_METHOD(void, SBStream, Clear, ());
195 }
196 
197 }
198 }
bool IsValid() const
Definition: SBStream.cpp:30
The registry contains a unique mapping between functions and their ID.
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
#define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class)
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
A file utility class.
Definition: FileSpec.h:55
void RegisterMethods< SBStream >(Registry &R)
Definition: SBStream.cpp:185
size_t size_t PrintfVarArg(const char *format, va_list args)
Definition: Stream.cpp:115
const char * GetData()
Definition: SBStream.cpp:42
#define LLDB_REGISTER_CONSTRUCTOR(Class, Signature)
#define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method)
void void RedirectToFile(const char *path, bool append)
Definition: SBStream.cpp:71
void Printf(const char *format,...) __attribute__((format(printf
Definition: SBStream.cpp:62
#define LLDB_RECORD_METHOD(Result, Class, Method, Signature,...)
size_t GetSize()
Definition: SBStream.cpp:53
lldb_private::Stream & ref()
Definition: SBStream.cpp:162
lldb_private::Stream * operator->()
Definition: SBStream.cpp:158
Definition: SBAddress.h:15
lldb_private::Stream * get()
Definition: SBStream.cpp:160
void RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership)
Definition: SBStream.cpp:107
#define LLDB_REGISTER_METHOD(Result, Class, Method, Signature)
#define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method)
void RedirectToFileDescriptor(int fd, bool transfer_fh_ownership)
Definition: SBStream.cpp:134
#define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature)