]>
git.saurik.com Git - wxWidgets.git/blob - src/common/stream.cpp
c755d78c9d1549b439c0ad267f5bb9519cdb98c6
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxStream base classes 
   4 // Author:      Guilhem Lavaux 
   8 // Copyright:   (c) Guilhem Lavaux 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "stream.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  30 #include <wx/stream.h> 
  31 #include <wx/datstrm.h> 
  32 #include <wx/objstrm.h> 
  34 #define BUF_TEMP_SIZE 10000 
  36 // ---------------------------------------------------------------------------- 
  38 // ---------------------------------------------------------------------------- 
  40 #define CHECK_ERROR(err) \ 
  41    if (m_stream->m_lasterror == wxStream_NOERROR) \ 
  42      m_stream->m_lasterror = err 
  44 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
) 
  45   : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
), 
  46     m_buffer_size(0), m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
), 
  47     m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
) 
  51 wxStreamBuffer::wxStreamBuffer(BufMode mode
) 
  52   : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
), 
  53     m_buffer_size(0), m_fixed(TRUE
), m_flushable(FALSE
), m_stream(NULL
), 
  54     m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
) 
  56   m_stream 
= new wxStreamBase(); 
  59 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
) 
  61   m_buffer_start 
= buffer
.m_buffer_start
; 
  62   m_buffer_end 
= buffer
.m_buffer_end
; 
  63   m_buffer_pos 
= buffer
.m_buffer_pos
; 
  64   m_buffer_size 
= buffer
.m_buffer_size
; 
  65   m_fixed 
= buffer
.m_fixed
; 
  66   m_flushable 
= buffer
.m_flushable
; 
  67   m_stream 
= buffer
.m_stream
; 
  68   m_mode 
= buffer
.m_mode
; 
  70   m_destroystream 
= FALSE
; 
  73 wxStreamBuffer::~wxStreamBuffer() 
  76     wxDELETEA(m_buffer_start
); 
  81 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
) 
  84     wxDELETEA(m_buffer_start
); 
  85   m_buffer_start 
= buffer_start
; 
  86   m_buffer_end   
= buffer_end
; 
  88   m_buffer_size 
= m_buffer_end
-m_buffer_start
; 
  93 void wxStreamBuffer::SetBufferIO(size_t bufsize
) 
  98     wxDELETEA(m_buffer_start
); 
 101     m_buffer_start 
= NULL
; 
 108   b_start 
= new char[bufsize
]; 
 109   SetBufferIO(b_start
, b_start 
+ bufsize
); 
 113 void wxStreamBuffer::ResetBuffer() 
 115   m_stream
->m_lasterror 
= wxStream_NOERROR
; 
 116   m_stream
->m_lastcount 
= 0; 
 118     m_buffer_pos 
= m_buffer_end
; 
 120     m_buffer_pos 
= m_buffer_start
; 
 123 bool wxStreamBuffer::FillBuffer() 
 127   count 
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
); 
 128   m_buffer_end 
= m_buffer_start
+count
; 
 129   m_buffer_pos 
= m_buffer_start
; 
 136 bool wxStreamBuffer::FlushBuffer() 
 138   size_t count
, current
; 
 140   if (m_buffer_pos 
== m_buffer_start 
|| !m_flushable
) 
 143   current 
= m_buffer_pos
-m_buffer_start
; 
 144   count 
= m_stream
->OnSysWrite(m_buffer_start
, current
); 
 145   if (count 
!= current
) 
 147   m_buffer_pos 
= m_buffer_start
; 
 152 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
) 
 154   size_t s_toget 
= m_buffer_end
-m_buffer_pos
; 
 159   memcpy(buffer
, m_buffer_pos
, s_toget
); 
 160   m_buffer_pos 
+= s_toget
; 
 163 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
) 
 165   size_t s_toput 
= m_buffer_end
-m_buffer_pos
; 
 167   if (s_toput 
< size 
&& !m_fixed
) { 
 168     m_buffer_start 
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
); 
 170     m_buffer_size 
+= size
; 
 171     m_buffer_end 
= m_buffer_start
+m_buffer_size
; 
 176   memcpy(m_buffer_pos
, buffer
, s_toput
); 
 177   m_buffer_pos 
+= s_toput
; 
 180 void wxStreamBuffer::PutChar(char c
) 
 182   wxASSERT(m_stream 
!= NULL
); 
 184   if (!m_buffer_size
) { 
 185     m_stream
->OnSysWrite(&c
, 1); 
 189   if (GetDataLeft() == 0 && !FlushBuffer()) { 
 190     CHECK_ERROR(wxStream_WRITE_ERR
); 
 195   m_stream
->m_lastcount 
= 1; 
 198 char wxStreamBuffer::GetChar() 
 202   wxASSERT(m_stream 
!= NULL
); 
 204   if (!m_buffer_size
) { 
 205     m_stream
->OnSysRead(&c
, 1); 
 209   if (!GetDataLeft()) { 
 210     CHECK_ERROR(wxStream_READ_ERR
); 
 214   GetFromBuffer(&c
, 1); 
 216   m_stream
->m_lastcount 
= 1; 
 220 size_t wxStreamBuffer::Read(void *buffer
, size_t size
) 
 222   wxASSERT(m_stream 
!= NULL
); 
 227   // ------------------ 
 228   // Buffering disabled 
 229   // ------------------ 
 231   m_stream
->m_lasterror 
= wxStream_NOERROR
; 
 233     return (m_stream
->m_lastcount 
+= m_stream
->OnSysRead(buffer
, size
)); 
 238   size_t buf_left
, orig_size 
= size
; 
 241     buf_left 
= GetDataLeft();  
 243     // First case: the requested buffer is larger than the stream buffer, 
 245     if (size 
> buf_left
) { 
 246       GetFromBuffer(buffer
, buf_left
); 
 248       buffer 
= (char *)buffer 
+ buf_left
; // ANSI C++ violation. 
 251         CHECK_ERROR(wxStream_READ_ERR
); 
 252         return (m_stream
->m_lastcount 
= orig_size
-size
); 
 256       // Second case: we just copy from the stream buffer. 
 257       GetFromBuffer(buffer
, size
); 
 261   return (m_stream
->m_lastcount 
+= orig_size
); 
 264 size_t wxStreamBuffer::Read(wxStreamBuffer 
*s_buf
) 
 266   char buf
[BUF_TEMP_SIZE
]; 
 267   size_t s 
= 0, bytes_read 
= BUF_TEMP_SIZE
; 
 272   while (bytes_read 
!= 0) { 
 273     bytes_read 
= Read(buf
, bytes_read
); 
 274     bytes_read 
= s_buf
->Write(buf
, bytes_read
); 
 280 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
) 
 282   wxASSERT(m_stream 
!= NULL
); 
 287   // ------------------ 
 288   // Buffering disabled 
 289   // ------------------ 
 291   m_stream
->m_lasterror 
= wxStream_NOERROR
; 
 293     return (m_stream
->m_lastcount 
= m_stream
->OnSysWrite(buffer
, size
)); 
 295   // ------------------ 
 297   // ------------------ 
 299   size_t buf_left
, orig_size 
= size
; 
 302     buf_left 
= m_buffer_end 
- m_buffer_pos
; 
 304     // First case: the buffer to write is larger than the stream buffer, 
 306     if (size 
> buf_left
) { 
 307       PutToBuffer(buffer
, buf_left
); 
 309       buffer 
= (char *)buffer 
+ buf_left
; // ANSI C++ violation. 
 311       if (!FlushBuffer()) { 
 312         CHECK_ERROR(wxStream_WRITE_ERR
); 
 313         return (m_stream
->m_lastcount 
= orig_size
-size
); 
 316       m_buffer_pos 
= m_buffer_start
; 
 320       // Second case: just copy it in the stream buffer. 
 321       PutToBuffer(buffer
, size
); 
 325   return (m_stream
->m_lastcount 
= orig_size
); 
 328 size_t wxStreamBuffer::Write(wxStreamBuffer 
*sbuf
) 
 330   char buf
[BUF_TEMP_SIZE
]; 
 331   size_t s 
= 0, bytes_count 
= BUF_TEMP_SIZE
, b_count2
; 
 332   wxInputStream 
*in_stream
; 
 337   in_stream 
= (wxInputStream 
*)sbuf
->Stream(); 
 339   while (bytes_count 
== BUF_TEMP_SIZE
) { 
 340     b_count2 
= sbuf
->Read(buf
, bytes_count
); 
 341     bytes_count 
= Write(buf
, b_count2
); 
 342     if (b_count2 
> bytes_count
) 
 343       in_stream
->Ungetch(buf
+bytes_count
, b_count2
-bytes_count
); 
 349 off_t 
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
) 
 351   off_t ret_off
, diff
, last_access
; 
 353   last_access 
= GetLastAccess(); 
 356     diff 
= pos 
+ GetIntPosition(); 
 357     if (diff 
< 0 || diff 
> last_access
) 
 358       return wxInvalidOffset
; 
 359     SetIntPosition(diff
); 
 365     // We'll try to compute an internal position later ... 
 366     ret_off 
= m_stream
->OnSysSeek(pos
, wxFromStart
); 
 370   case wxFromCurrent
: { 
 371     diff 
= pos 
+ GetIntPosition(); 
 373     if ( (diff 
> last_access
) || (diff 
< 0) ) { 
 374       ret_off 
= m_stream
->OnSysSeek(pos
, wxFromCurrent
); 
 378       SetIntPosition(diff
); 
 383     // Hard to compute: always seek to the requested position. 
 384     ret_off 
= m_stream
->OnSysSeek(pos
, wxFromEnd
); 
 388   return wxInvalidOffset
; 
 391 off_t 
wxStreamBuffer::Tell() const 
 396     pos 
= m_stream
->OnSysTell(); 
 397     if (pos 
== wxInvalidOffset
) 
 398       return wxInvalidOffset
; 
 399     return pos 
- GetLastAccess() + GetIntPosition(); 
 401     return GetIntPosition(); 
 404 size_t wxStreamBuffer::GetDataLeft() 
 406   if (m_buffer_end 
== m_buffer_pos 
&& m_flushable
) 
 408   return m_buffer_end
-m_buffer_pos
; 
 411 // ---------------------------------------------------------------------------- 
 413 // ---------------------------------------------------------------------------- 
 415 wxStreamBase::wxStreamBase() 
 417   m_lasterror 
= wxStream_NOERROR
; 
 421 wxStreamBase::~wxStreamBase() 
 425 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
)) 
 430 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
)) 
 435 off_t 
wxStreamBase::OnSysSeek(off_t 
WXUNUSED(seek
), wxSeekMode 
WXUNUSED(mode
)) 
 437   return wxInvalidOffset
; 
 440 off_t 
wxStreamBase::OnSysTell() const 
 442   return wxInvalidOffset
; 
 445 // ---------------------------------------------------------------------------- 
 447 // ---------------------------------------------------------------------------- 
 449 wxInputStream::wxInputStream() 
 451     m_wback(NULL
), m_wbacksize(0), m_wbackcur(0) 
 455 wxInputStream::~wxInputStream() 
 461 char *wxInputStream::AllocSpaceWBack(size_t needed_size
) 
 465   m_wbacksize 
+= needed_size
; 
 468     temp_b 
= (char *)malloc(m_wbacksize
); 
 470     temp_b 
= (char *)realloc(m_wback
, m_wbacksize
); 
 476   return (char *)(m_wback
+(m_wbacksize
-needed_size
)); 
 479 size_t wxInputStream::GetWBack(char *buf
, size_t bsize
) 
 481   size_t s_toget 
= m_wbacksize
-m_wbackcur
; 
 489   memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
); 
 491   m_wbackcur 
+= s_toget
; 
 492   if (m_wbackcur 
== m_wbacksize
) { 
 494     m_wback 
= (char *)NULL
; 
 502 size_t wxInputStream::Ungetch(const void *buf
, size_t bufsize
) 
 506   ptrback 
= AllocSpaceWBack(bufsize
); 
 510   memcpy(ptrback
, buf
, bufsize
); 
 514 bool wxInputStream::Ungetch(char c
) 
 518   ptrback 
= AllocSpaceWBack(1); 
 526 char wxInputStream::GetC() 
 533 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
) 
 536   char *buf 
= (char *)buffer
; 
 538   retsize 
= GetWBack(buf
, size
); 
 539   if (retsize 
== size
) { 
 541     m_lasterror 
= wxStream_NOERROR
; 
 547   m_lastcount 
= OnSysRead(buf
, size
); 
 551 char wxInputStream::Peek() 
 556   if (m_lasterror 
== wxStream_NOERROR
) { 
 563 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
) 
 565   char buf
[BUF_TEMP_SIZE
];  
 566   size_t bytes_read 
= BUF_TEMP_SIZE
; 
 568   while (bytes_read 
== BUF_TEMP_SIZE
) { 
 569     bytes_read 
= Read(buf
, bytes_read
).LastRead(); 
 570     bytes_read 
= stream_out
.Write(buf
, bytes_read
).LastWrite(); 
 575 off_t 
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
) 
 577   return OnSysSeek(pos
, mode
); 
 580 off_t 
wxInputStream::TellI() const 
 585 // -------------------- 
 586 // Overloaded operators 
 587 // -------------------- 
 590 wxInputStream
& wxInputStream::operator>>(wxObject 
*& obj
) 
 592   wxObjectInputStream 
obj_s(*this); 
 593   obj 
= obj_s
.LoadObject(); 
 599 // ---------------------------------------------------------------------------- 
 601 // ---------------------------------------------------------------------------- 
 602 wxOutputStream::wxOutputStream() 
 607 wxOutputStream::~wxOutputStream() 
 611 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
) 
 613   m_lastcount 
= OnSysWrite(buffer
, size
); 
 617 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
) 
 619   stream_in
.Read(*this); 
 623 off_t 
wxOutputStream::TellO() const 
 628 off_t 
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
) 
 630   return OnSysSeek(pos
, mode
); 
 633 void wxOutputStream::Sync() 
 638 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
) 
 640   wxObjectOutputStream 
obj_s(*this); 
 641   obj_s
.SaveObject(obj
); 
 646 // ---------------------------------------------------------------------------- 
 647 // wxFilterInputStream 
 648 // ---------------------------------------------------------------------------- 
 649 wxFilterInputStream::wxFilterInputStream() 
 654 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
) 
 657   m_parent_i_stream 
= &stream
; 
 660 wxFilterInputStream::~wxFilterInputStream() 
 664 // ---------------------------------------------------------------------------- 
 665 // wxFilterOutputStream 
 666 // ---------------------------------------------------------------------------- 
 667 wxFilterOutputStream::wxFilterOutputStream() 
 672 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
) 
 675   m_parent_o_stream 
= &stream
; 
 678 wxFilterOutputStream::~wxFilterOutputStream() 
 682 // ---------------------------------------------------------------------------- 
 683 // wxBufferedInputStream 
 684 // ---------------------------------------------------------------------------- 
 685 wxBufferedInputStream::wxBufferedInputStream(wxInputStream
& s
) 
 686   : wxFilterInputStream(s
) 
 688   m_i_streambuf 
= new wxStreamBuffer(*this, wxStreamBuffer::read
); 
 689   m_i_streambuf
->SetBufferIO(1024); 
 692 wxBufferedInputStream::~wxBufferedInputStream() 
 694   delete m_i_streambuf
; 
 697 wxInputStream
& wxBufferedInputStream::Read(void *buffer
, size_t size
) 
 700   char *buf 
= (char *)buffer
; 
 702   retsize 
= GetWBack(buf
, size
); 
 703   m_lastcount 
= retsize
; 
 704   if (retsize 
== size
) { 
 705     m_lasterror 
= wxStream_NOERROR
; 
 711   m_i_streambuf
->Read(buf
, size
); 
 716 off_t 
wxBufferedInputStream::SeekI(off_t pos
, wxSeekMode mode
) 
 718   return m_i_streambuf
->Seek(pos
, mode
); 
 721 off_t 
wxBufferedInputStream::TellI() const 
 723   return m_i_streambuf
->Tell(); 
 726 size_t wxBufferedInputStream::OnSysRead(void *buffer
, size_t bufsize
) 
 728   return m_parent_i_stream
->Read(buffer
, bufsize
).LastRead(); 
 731 off_t 
wxBufferedInputStream::OnSysSeek(off_t seek
, wxSeekMode mode
) 
 733   return m_parent_i_stream
->SeekI(seek
, mode
); 
 736 off_t 
wxBufferedInputStream::OnSysTell() const 
 738   return m_parent_i_stream
->TellI(); 
 741 // ---------------------------------------------------------------------------- 
 742 // wxBufferedOutputStream 
 743 // ---------------------------------------------------------------------------- 
 745 wxBufferedOutputStream::wxBufferedOutputStream(wxOutputStream
& s
) 
 746   : wxFilterOutputStream(s
) 
 748   m_o_streambuf 
= new wxStreamBuffer(*this, wxStreamBuffer::write
); 
 749   m_o_streambuf
->SetBufferIO(1024); 
 752 wxBufferedOutputStream::~wxBufferedOutputStream() 
 754   delete m_o_streambuf
; 
 757 wxOutputStream
& wxBufferedOutputStream::Write(const void *buffer
, size_t size
) 
 760   m_o_streambuf
->Write(buffer
, size
); 
 764 off_t 
wxBufferedOutputStream::SeekO(off_t pos
, wxSeekMode mode
) 
 766   return m_o_streambuf
->Seek(pos
, mode
); 
 769 off_t 
wxBufferedOutputStream::TellO() const 
 771   return m_o_streambuf
->Tell(); 
 774 void wxBufferedOutputStream::Sync() 
 776   m_o_streambuf
->FlushBuffer(); 
 777   m_parent_o_stream
->Sync(); 
 780 size_t wxBufferedOutputStream::OnSysWrite(const void *buffer
, size_t bufsize
) 
 782   return m_parent_o_stream
->Write(buffer
, bufsize
).LastWrite(); 
 785 off_t 
wxBufferedOutputStream::OnSysSeek(off_t seek
, wxSeekMode mode
) 
 787   return m_parent_o_stream
->SeekO(seek
, mode
); 
 790 off_t 
wxBufferedOutputStream::OnSysTell() const 
 792   return m_parent_o_stream
->TellO(); 
 795 // ---------------------------------------------------------------------------- 
 796 // Some IOManip function 
 797 // ---------------------------------------------------------------------------- 
 799 wxOutputStream
& wxEndL(wxOutputStream
& stream
) 
 802   return stream
.Write("\r\n", 2); 
 805   return stream
.Write("\r", 1); 
 807   return stream
.Write("\n", 1);