155 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- SBStream.cpp ----------------------------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "lldb/API/SBStream.h"
 | |
| 
 | |
| #include "lldb/Core/StreamFile.h"
 | |
| #include "lldb/Utility/Status.h"
 | |
| #include "lldb/Utility/Stream.h"
 | |
| #include "lldb/Utility/StreamString.h"
 | |
| 
 | |
| using namespace lldb;
 | |
| using namespace lldb_private;
 | |
| 
 | |
| SBStream::SBStream() : m_opaque_ap(new StreamString()), m_is_file(false) {}
 | |
| 
 | |
| SBStream::SBStream(SBStream &&rhs)
 | |
|     : m_opaque_ap(std::move(rhs.m_opaque_ap)), m_is_file(rhs.m_is_file) {}
 | |
| 
 | |
| SBStream::~SBStream() {}
 | |
| 
 | |
| bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); }
 | |
| 
 | |
| // If this stream is not redirected to a file, it will maintain a local
 | |
| // cache for the stream data which can be accessed using this accessor.
 | |
| const char *SBStream::GetData() {
 | |
|   if (m_is_file || m_opaque_ap.get() == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
 | |
| }
 | |
| 
 | |
| // If this stream is not redirected to a file, it will maintain a local
 | |
| // cache for the stream output whose length can be accessed using this
 | |
| // accessor.
 | |
| size_t SBStream::GetSize() {
 | |
|   if (m_is_file || m_opaque_ap.get() == NULL)
 | |
|     return 0;
 | |
| 
 | |
|   return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
 | |
| }
 | |
| 
 | |
| void SBStream::Printf(const char *format, ...) {
 | |
|   if (!format)
 | |
|     return;
 | |
|   va_list args;
 | |
|   va_start(args, format);
 | |
|   ref().PrintfVarArg(format, args);
 | |
|   va_end(args);
 | |
| }
 | |
| 
 | |
| void SBStream::RedirectToFile(const char *path, bool append) {
 | |
|   if (path == nullptr)
 | |
|     return;
 | |
| 
 | |
|   std::string local_data;
 | |
|   if (m_opaque_ap.get()) {
 | |
|     // See if we have any locally backed data. If so, copy it so we can then
 | |
|     // redirect it to the file so we don't lose the data
 | |
|     if (!m_is_file)
 | |
|       local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString();
 | |
|   }
 | |
|   StreamFile *stream_file = new StreamFile;
 | |
|   uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
 | |
|   if (append)
 | |
|     open_options |= File::eOpenOptionAppend;
 | |
|   else
 | |
|     open_options |= File::eOpenOptionTruncate;
 | |
|   stream_file->GetFile().Open(path, open_options,
 | |
|                               lldb::eFilePermissionsFileDefault);
 | |
| 
 | |
|   m_opaque_ap.reset(stream_file);
 | |
| 
 | |
|   if (m_opaque_ap.get()) {
 | |
|     m_is_file = true;
 | |
| 
 | |
|     // If we had any data locally in our StreamString, then pass that along to
 | |
|     // the to new file we are redirecting to.
 | |
|     if (!local_data.empty())
 | |
|       m_opaque_ap->Write(&local_data[0], local_data.size());
 | |
|   } else
 | |
|     m_is_file = false;
 | |
| }
 | |
| 
 | |
| void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
 | |
|   if (fh == nullptr)
 | |
|     return;
 | |
| 
 | |
|   std::string local_data;
 | |
|   if (m_opaque_ap.get()) {
 | |
|     // See if we have any locally backed data. If so, copy it so we can then
 | |
|     // redirect it to the file so we don't lose the data
 | |
|     if (!m_is_file)
 | |
|       local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString();
 | |
|   }
 | |
|   m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership));
 | |
| 
 | |
|   if (m_opaque_ap.get()) {
 | |
|     m_is_file = true;
 | |
| 
 | |
|     // If we had any data locally in our StreamString, then pass that along to
 | |
|     // the to new file we are redirecting to.
 | |
|     if (!local_data.empty())
 | |
|       m_opaque_ap->Write(&local_data[0], local_data.size());
 | |
|   } else
 | |
|     m_is_file = false;
 | |
| }
 | |
| 
 | |
| void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
 | |
|   std::string local_data;
 | |
|   if (m_opaque_ap.get()) {
 | |
|     // See if we have any locally backed data. If so, copy it so we can then
 | |
|     // redirect it to the file so we don't lose the data
 | |
|     if (!m_is_file)
 | |
|       local_data = static_cast<StreamString *>(m_opaque_ap.get())->GetString();
 | |
|   }
 | |
| 
 | |
|   m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
 | |
|   if (m_opaque_ap.get()) {
 | |
|     m_is_file = true;
 | |
| 
 | |
|     // If we had any data locally in our StreamString, then pass that along to
 | |
|     // the to new file we are redirecting to.
 | |
|     if (!local_data.empty())
 | |
|       m_opaque_ap->Write(&local_data[0], local_data.size());
 | |
|   } else
 | |
|     m_is_file = false;
 | |
| }
 | |
| 
 | |
| lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); }
 | |
| 
 | |
| lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); }
 | |
| 
 | |
| lldb_private::Stream &SBStream::ref() {
 | |
|   if (m_opaque_ap.get() == NULL)
 | |
|     m_opaque_ap.reset(new StreamString());
 | |
|   return *m_opaque_ap.get();
 | |
| }
 | |
| 
 | |
| void SBStream::Clear() {
 | |
|   if (m_opaque_ap.get()) {
 | |
|     // See if we have any locally backed data. If so, copy it so we can then
 | |
|     // redirect it to the file so we don't lose the data
 | |
|     if (m_is_file)
 | |
|       m_opaque_ap.reset();
 | |
|     else
 | |
|       static_cast<StreamString *>(m_opaque_ap.get())->Clear();
 | |
|   }
 | |
| }
 |