We now have SBStream that mirrors the generic stream classes we 
use inside lldb (lldb_private::StreamFile, and lldb_private::StreamString).



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@114188 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp
new file mode 100644
index 0000000..55714fd
--- /dev/null
+++ b/source/API/SBStream.cpp
@@ -0,0 +1,178 @@
+//===-- 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/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBStream::SBStream () :
+    m_opaque_ap (),
+    m_is_file (false)
+{
+}
+
+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 NULL;
+    
+    return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
+}
+
+void
+SBStream::Printf (const char *format, ...)
+{
+    va_list args;
+    va_start (args, format);
+    ref().PrintfVarArg (format, args);
+    va_end (args);
+}
+
+void
+SBStream::RedirectToFile (const char *path, bool append)
+{
+    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.swap(static_cast<StreamString *>(m_opaque_ap.get())->GetString());
+    }
+    m_opaque_ap.reset (new StreamFile (path, append ? "a" : "w"));
+
+    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)
+{
+    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.swap(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.swap(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())->GetString().clear();
+    }
+}