+// ----------------------------------------------------------------------------
+// wxStreamBuffer
+// ----------------------------------------------------------------------------
+
+wxStreamBuffer::wxStreamBuffer(wxInputStream& i_stream)
+ : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
+ m_buffer_size(0), m_istream(&i_stream), m_ostream(NULL)
+{
+}
+
+wxStreamBuffer::wxStreamBuffer(wxOutputStream& o_stream)
+ : m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
+ m_buffer_size(0), m_istream(NULL), m_ostream(&o_stream)
+{
+}
+
+wxStreamBuffer::~wxStreamBuffer()
+{
+}
+
+void wxStreamBuffer::WriteBack(char c)
+{
+ if (m_ostream)
+ return;
+
+ // Assume that if we write "back" we have read a few bytes: so we have some
+ // space.
+
+ m_buffer_pos--;
+ *m_buffer_pos = c;
+}
+
+void wxStreamBuffer::SetBufferIO(char *buffer_start, char *buffer_end)
+{
+ m_buffer_pos = m_buffer_start = buffer_start;
+ m_buffer_end = buffer_end;
+
+ m_buffer_size = m_buffer_end-m_buffer_start;
+}
+
+void wxStreamBuffer::SetBufferIO(size_t bufsize)
+{
+ if (m_buffer_start)
+ delete[] m_buffer_start;
+
+ if (!bufsize) {
+ m_buffer_start = NULL;
+ m_buffer_end = NULL;
+ m_buffer_pos = NULL;
+ m_buffer_size = 0;
+ }
+
+ m_buffer_start = new char[bufsize];
+ m_buffer_end = m_buffer_start + bufsize;
+ if (m_istream)
+ m_buffer_pos = m_buffer_end;
+ else
+ m_buffer_pos = m_buffer_start;
+ m_buffer_size = bufsize;
+}
+
+void wxStreamBuffer::ResetBuffer()
+{
+ if (m_istream)
+ m_buffer_pos = m_buffer_end;
+ else
+ m_buffer_pos = m_buffer_start;
+}
+
+void wxStreamBuffer::Read(void *buffer, size_t size)
+{
+ wxASSERT(m_istream != NULL);
+
+ // ------------------
+ // Buffering disabled
+ // ------------------
+
+ if (!m_buffer_size) {
+ m_istream->m_lastread = m_istream->DoRead(buffer, size);
+ return;
+ }
+
+ // -----------------
+ // Buffering enabled
+ // -----------------
+ size_t buf_left, orig_size = size;
+ size_t read_ret;
+
+ while (size > 0) {
+ buf_left = m_buffer_end - m_buffer_pos;
+
+ // First case: the requested buffer is larger than the stream buffer,
+ // we split
+ if (size > buf_left) {
+ memcpy(buffer, m_buffer_pos, buf_left);
+ size -= buf_left;
+ buffer = (char *)buffer + buf_left; // ANSI C++ violation.
+
+ read_ret = m_istream->DoRead(m_buffer_start, m_buffer_size);
+
+ // Read failed
+ if (read_ret == 0) {
+ m_istream->m_lastread = orig_size-size;
+ m_buffer_pos = m_buffer_end = m_buffer_start;
+ return;
+ } else {
+ m_buffer_end = m_buffer_start+read_ret;
+ m_buffer_pos = m_buffer_start;
+ }
+ } else {
+
+ // Second case: we just copy from the stream buffer.
+ memcpy(buffer, m_buffer_pos, size);
+ m_buffer_pos += size;
+ break;
+ }
+ }
+ m_istream->m_lastread = orig_size;
+}
+
+void wxStreamBuffer::Write(const void *buffer, size_t size)
+{
+ wxASSERT(m_ostream != NULL);
+
+ // ------------------
+ // Buffering disabled
+ // ------------------
+
+ if (!m_buffer_size) {
+ m_ostream->m_lastwrite = m_ostream->DoWrite(buffer, size);
+ return;
+ }
+
+ // ------------------
+ // Buffering enabled
+ // ------------------
+
+ size_t buf_left, orig_size = size;
+ size_t write_ret;
+
+ while (size > 0) {
+ buf_left = m_buffer_end - m_buffer_pos;
+
+ // First case: the buffer to write is larger than the stream buffer,
+ // we split it
+ if (size > buf_left) {
+ memcpy(m_buffer_pos, buffer, buf_left);
+ size -= buf_left;
+ buffer = (char *)buffer + buf_left; // ANSI C++ violation.
+
+ write_ret = m_ostream->DoWrite(m_buffer_start, m_buffer_size);
+ if (write_ret != m_buffer_size) {
+ m_ostream->m_bad = TRUE;
+ m_ostream->m_lastwrite = orig_size-size;
+ m_buffer_pos = m_buffer_end = m_buffer_start;
+ return;
+ }
+ m_buffer_pos = m_buffer_start;
+
+ } else {
+
+ // Second case: just copy it in the stream buffer.
+
+ memcpy(m_buffer_pos, buffer, size);
+ m_buffer_pos += size;
+ break;
+ }
+ }
+ m_ostream->m_lastwrite = orig_size;
+}
+