]>
git.saurik.com Git - wxWidgets.git/blob - src/common/stream.cpp
d5954d71d8c2340fd3383968df78354c960b6793
   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" 
  19 #include <wx/stream.h> 
  20 #include <wx/datstrm.h> 
  21 #include <wx/objstrm.h> 
  27 #define BUF_TEMP_SIZE 10000 
  29 // ---------------------------------------------------------------------------- 
  31 // ---------------------------------------------------------------------------- 
  33 #define CHECK_ERROR(err) \ 
  34    if (m_stream->m_lasterror == wxStream_NOERROR) \ 
  35      m_stream->m_lasterror = err 
  37 wxStreamBuffer::wxStreamBuffer(wxStreamBase
& stream
, BufMode mode
) 
  38   : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
), 
  39     m_buffer_size(0), m_wback(NULL
), m_wbacksize(0), m_wbackcur(0), 
  40     m_fixed(TRUE
), m_flushable(TRUE
), m_stream(&stream
), 
  41     m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(FALSE
) 
  45 wxStreamBuffer::wxStreamBuffer(BufMode mode
) 
  46   : m_buffer_start(NULL
), m_buffer_end(NULL
), m_buffer_pos(NULL
), 
  47     m_buffer_size(0), m_wback(NULL
), m_wbacksize(0), m_wbackcur(0), 
  48     m_fixed(TRUE
), m_flushable(FALSE
), m_stream(NULL
), 
  49     m_mode(mode
), m_destroybuf(FALSE
), m_destroystream(TRUE
) 
  51   m_stream 
= new wxStreamBase(); 
  54 wxStreamBuffer::wxStreamBuffer(const wxStreamBuffer
& buffer
) 
  56   m_buffer_start 
= buffer
.m_buffer_start
; 
  57   m_buffer_end 
= buffer
.m_buffer_end
; 
  58   m_buffer_pos 
= buffer
.m_buffer_pos
; 
  59   m_buffer_size 
= buffer
.m_buffer_size
; 
  60   m_fixed 
= buffer
.m_fixed
; 
  61   m_flushable 
= buffer
.m_flushable
; 
  62   m_stream 
= buffer
.m_stream
; 
  63   m_mode 
= buffer
.m_mode
; 
  65   m_destroystream 
= FALSE
; 
  71 wxStreamBuffer::~wxStreamBuffer() 
  76     wxDELETEA(m_buffer_start
); 
  81 size_t wxStreamBuffer::WriteBack(const char *buf
, size_t bufsize
) 
  88   ptrback 
= AllocSpaceWBack(bufsize
); 
  92   memcpy(ptrback
, buf
, bufsize
); 
  96 bool wxStreamBuffer::WriteBack(char c
) 
 100   ptrback 
= AllocSpaceWBack(1); 
 108 void wxStreamBuffer::SetBufferIO(char *buffer_start
, char *buffer_end
) 
 111     wxDELETEA(m_buffer_start
); 
 112   m_buffer_start 
= buffer_start
; 
 113   m_buffer_end   
= buffer_end
; 
 115   m_buffer_size 
= m_buffer_end
-m_buffer_start
; 
 116   m_destroybuf 
= FALSE
; 
 120 void wxStreamBuffer::SetBufferIO(size_t bufsize
) 
 125     wxDELETEA(m_buffer_start
); 
 128     m_buffer_start 
= NULL
; 
 135   b_start 
= new char[bufsize
]; 
 136   SetBufferIO(b_start
, b_start 
+ bufsize
); 
 140 void wxStreamBuffer::ResetBuffer() 
 142   m_stream
->m_lasterror 
= wxStream_NOERROR
; 
 143   m_stream
->m_lastcount 
= 0; 
 145     m_buffer_pos 
= m_buffer_end
; 
 147     m_buffer_pos 
= m_buffer_start
; 
 150 char *wxStreamBuffer::AllocSpaceWBack(size_t needed_size
) 
 154   m_wbacksize 
+= needed_size
; 
 157     temp_b 
= (char *)malloc(m_wbacksize
); 
 159     temp_b 
= (char *)realloc(m_wback
, m_wbacksize
); 
 165   return (char *)(m_wback
+(m_wbacksize
-needed_size
)); 
 168 size_t wxStreamBuffer::GetWBack(char *buf
, size_t bsize
) 
 170   size_t s_toget 
= m_wbacksize
-m_wbackcur
; 
 175   memcpy(buf
, (m_wback
+m_wbackcur
), s_toget
); 
 177   m_wbackcur 
+= s_toget
; 
 178   if (m_wbackcur 
== m_wbacksize
) { 
 180     m_wback 
= (char *)NULL
; 
 188 bool wxStreamBuffer::FillBuffer() 
 192   count 
= m_stream
->OnSysRead(m_buffer_start
, m_buffer_size
); 
 193   m_buffer_end 
= m_buffer_start
+count
; 
 194   m_buffer_pos 
= m_buffer_start
; 
 201 bool wxStreamBuffer::FlushBuffer() 
 203   size_t count
, current
; 
 205   if (m_buffer_pos 
== m_buffer_start 
|| !m_flushable
) 
 208   current 
= m_buffer_pos
-m_buffer_start
; 
 209   count 
= m_stream
->OnSysWrite(m_buffer_start
, current
); 
 210   if (count 
!= current
) 
 212   m_buffer_pos 
= m_buffer_start
; 
 217 void wxStreamBuffer::GetFromBuffer(void *buffer
, size_t size
) 
 219   size_t s_toget 
= m_buffer_end
-m_buffer_pos
; 
 224   memcpy(buffer
, m_buffer_pos
, s_toget
); 
 225   m_buffer_pos 
+= s_toget
; 
 228 void wxStreamBuffer::PutToBuffer(const void *buffer
, size_t size
) 
 230   size_t s_toput 
= m_buffer_end
-m_buffer_pos
; 
 232   if (s_toput 
< size 
&& !m_fixed
) { 
 233     m_buffer_start 
= (char *)realloc(m_buffer_start
, m_buffer_size
+size
); 
 235     m_buffer_size 
+= size
; 
 236     m_buffer_end 
= m_buffer_start
+m_buffer_size
; 
 241   memcpy(m_buffer_pos
, buffer
, s_toput
); 
 242   m_buffer_pos 
+= s_toput
; 
 245 void wxStreamBuffer::PutChar(char c
) 
 247   wxASSERT(m_stream 
!= NULL
); 
 249   if (!m_buffer_size
) { 
 250     m_stream
->OnSysWrite(&c
, 1); 
 254   if (GetDataLeft() == 0 && !FlushBuffer()) { 
 255     CHECK_ERROR(wxStream_WRITE_ERR
); 
 260   m_stream
->m_lastcount 
= 1; 
 263 char wxStreamBuffer::GetChar() 
 267   wxASSERT(m_stream 
!= NULL
); 
 269   if (!m_buffer_size
) { 
 270     m_stream
->OnSysRead(&c
, 1); 
 274   if (!GetDataLeft()) { 
 275     CHECK_ERROR(wxStream_READ_ERR
); 
 279   GetFromBuffer(&c
, 1); 
 280   m_stream
->m_lastcount 
= 1; 
 284 size_t wxStreamBuffer::Read(void *buffer
, size_t size
) 
 286   wxASSERT(m_stream 
!= NULL
); 
 291   // ------------------ 
 292   // Buffering disabled 
 293   // ------------------ 
 295   m_stream
->m_lasterror 
= wxStream_NOERROR
; 
 296   m_stream
->m_lastcount 
= GetWBack((char *)buffer
, size
); 
 297   size 
-= m_stream
->m_lastcount
; 
 299     return m_stream
->m_lastcount
; 
 301   buffer 
= (void *)((char *)buffer
+m_stream
->m_lastcount
); 
 304     return (m_stream
->m_lastcount 
+= m_stream
->OnSysRead(buffer
, size
)); 
 309   size_t buf_left
, orig_size 
= size
; 
 312     buf_left 
= GetDataLeft();  
 314     // First case: the requested buffer is larger than the stream buffer, 
 316     if (size 
> buf_left
) { 
 317       GetFromBuffer(buffer
, buf_left
); 
 319       buffer 
= (char *)buffer 
+ buf_left
; // ANSI C++ violation. 
 322         CHECK_ERROR(wxStream_READ_ERR
); 
 323         return (m_stream
->m_lastcount 
= orig_size
-size
); 
 327       // Second case: we just copy from the stream buffer. 
 328       GetFromBuffer(buffer
, size
); 
 332   return (m_stream
->m_lastcount 
+= orig_size
); 
 335 size_t wxStreamBuffer::Read(wxStreamBuffer 
*s_buf
) 
 337   char buf
[BUF_TEMP_SIZE
]; 
 338   size_t s 
= 0, bytes_read 
= BUF_TEMP_SIZE
; 
 343   while (bytes_read 
!= 0) { 
 344     bytes_read 
= Read(buf
, bytes_read
); 
 345     bytes_read 
= s_buf
->Write(buf
, bytes_read
); 
 351 size_t wxStreamBuffer::Write(const void *buffer
, size_t size
) 
 353   wxASSERT(m_stream 
!= NULL
); 
 358   // ------------------ 
 359   // Buffering disabled 
 360   // ------------------ 
 362   m_stream
->m_lasterror 
= wxStream_NOERROR
; 
 364     return (m_stream
->m_lastcount 
= m_stream
->OnSysWrite(buffer
, size
)); 
 366   // ------------------ 
 368   // ------------------ 
 370   size_t buf_left
, orig_size 
= size
; 
 373     buf_left 
= m_buffer_end 
- m_buffer_pos
; 
 375     // First case: the buffer to write is larger than the stream buffer, 
 377     if (size 
> buf_left
) { 
 378       PutToBuffer(buffer
, buf_left
); 
 380       buffer 
= (char *)buffer 
+ buf_left
; // ANSI C++ violation. 
 382       if (!FlushBuffer()) { 
 383         CHECK_ERROR(wxStream_WRITE_ERR
); 
 384         return (m_stream
->m_lastcount 
= orig_size
-size
); 
 387       m_buffer_pos 
= m_buffer_start
; 
 391       // Second case: just copy it in the stream buffer. 
 392       PutToBuffer(buffer
, size
); 
 396   return (m_stream
->m_lastcount 
= orig_size
); 
 399 size_t wxStreamBuffer::Write(wxStreamBuffer 
*sbuf
) 
 401   char buf
[BUF_TEMP_SIZE
]; 
 402   size_t s 
= 0, bytes_count 
= BUF_TEMP_SIZE
, b_count2
; 
 407   while (bytes_count 
== BUF_TEMP_SIZE
) { 
 408     b_count2 
= sbuf
->Read(buf
, bytes_count
); 
 409     bytes_count 
= Write(buf
, b_count2
); 
 410     if (b_count2 
> bytes_count
) 
 411       sbuf
->WriteBack(buf
+bytes_count
, b_count2
-bytes_count
); 
 417 off_t 
wxStreamBuffer::Seek(off_t pos
, wxSeekMode mode
) 
 419   off_t ret_off
, diff
, last_access
; 
 421   last_access 
= GetLastAccess(); 
 424     diff 
= pos 
+ GetIntPosition(); 
 425     if (diff 
< 0 || diff 
> last_access
) 
 426       return wxInvalidOffset
; 
 427     SetIntPosition(diff
); 
 433     // We'll try to compute an internal position later ... 
 434     ret_off 
= m_stream
->OnSysSeek(pos
, wxFromStart
); 
 438   case wxFromCurrent
: { 
 439     diff 
= pos 
+ GetIntPosition(); 
 441     if ( (diff 
> last_access
) || (diff 
< 0) ) { 
 442       ret_off 
= m_stream
->OnSysSeek(pos
, wxFromCurrent
); 
 446       SetIntPosition(diff
); 
 451     // Hard to compute: always seek to the requested position. 
 452     ret_off 
= m_stream
->OnSysSeek(pos
, wxFromEnd
); 
 456   return wxInvalidOffset
; 
 459 off_t 
wxStreamBuffer::Tell() const 
 464     pos 
= m_stream
->OnSysTell(); 
 465     if (pos 
== wxInvalidOffset
) 
 466       return wxInvalidOffset
; 
 467     return pos 
- GetLastAccess() + GetIntPosition(); 
 469     return GetIntPosition(); 
 472 size_t wxStreamBuffer::GetDataLeft() 
 474   if (m_buffer_end 
== m_buffer_pos 
&& m_flushable
) 
 476   return m_buffer_end
-m_buffer_pos
; 
 479 // ---------------------------------------------------------------------------- 
 481 // ---------------------------------------------------------------------------- 
 483 wxStreamBase::wxStreamBase() 
 485   m_lasterror 
= wxStream_NOERROR
; 
 489 wxStreamBase::~wxStreamBase() 
 493 size_t wxStreamBase::OnSysRead(void *WXUNUSED(buffer
), size_t WXUNUSED(size
)) 
 498 size_t wxStreamBase::OnSysWrite(const void *WXUNUSED(buffer
), size_t WXUNUSED(bufsize
)) 
 503 off_t 
wxStreamBase::OnSysSeek(off_t 
WXUNUSED(seek
), wxSeekMode 
WXUNUSED(mode
)) 
 505   return wxInvalidOffset
; 
 508 off_t 
wxStreamBase::OnSysTell() const 
 510   return wxInvalidOffset
; 
 513 // ---------------------------------------------------------------------------- 
 515 // ---------------------------------------------------------------------------- 
 517 wxInputStream::wxInputStream() 
 520   m_i_destroybuf 
= TRUE
; 
 521   m_i_streambuf 
= new wxStreamBuffer(*this, wxStreamBuffer::read
); 
 524 wxInputStream::wxInputStream(wxStreamBuffer 
*buffer
) 
 527   m_i_destroybuf 
= FALSE
; 
 528   m_i_streambuf 
= buffer
; 
 531 wxInputStream::~wxInputStream() 
 534     delete m_i_streambuf
; 
 537 char wxInputStream::GetC() 
 540   m_i_streambuf
->Read(&c
, 1); 
 544 wxInputStream
& wxInputStream::Read(void *buffer
, size_t size
) 
 546   m_i_streambuf
->Read(buffer
, size
); 
 547   // wxStreamBuffer sets all variables for us 
 551 char wxInputStream::Peek() 
 553   m_i_streambuf
->GetDataLeft(); 
 555   return *(m_i_streambuf
->GetBufferPos()); 
 559 wxInputStream
& wxInputStream::Read(wxOutputStream
& stream_out
) 
 561   char buf
[BUF_TEMP_SIZE
];  
 562   size_t bytes_read 
= BUF_TEMP_SIZE
; 
 564   while (bytes_read 
== BUF_TEMP_SIZE
) { 
 565     bytes_read 
= Read(buf
, bytes_read
).LastRead(); 
 566     bytes_read 
= stream_out
.Write(buf
, bytes_read
).LastWrite(); 
 571 off_t 
wxInputStream::SeekI(off_t pos
, wxSeekMode mode
) 
 573   return m_i_streambuf
->Seek(pos
, mode
); 
 576 off_t 
wxInputStream::TellI() const 
 578   return m_i_streambuf
->Tell(); 
 581 // -------------------- 
 582 // Overloaded operators 
 583 // -------------------- 
 585 wxInputStream
& wxInputStream::operator>>(wxString
& line
) 
 587   wxDataInputStream 
s(*this); 
 593 wxInputStream
& wxInputStream::operator>>(char& c
) 
 599 wxInputStream
& wxInputStream::operator>>(short& i
) 
 608 wxInputStream
& wxInputStream::operator>>(int& i
) 
 617 wxInputStream
& wxInputStream::operator>>(long& i
) 
 619   /* I only implemented a simple integer parser */ 
 622   while (isspace( c 
= GetC() ) ) 
 626   if (! (c 
== '-' || isdigit(c
)) ) { 
 627     InputStreamBuffer()->WriteBack(c
); 
 647 wxInputStream
& wxInputStream::operator>>(double& f
) 
 649   /* I only implemented a simple float parser */ 
 652   while (isspace( c 
= GetC() ) ) 
 656   if (! (c 
== '-' || isdigit(c
)) ) { 
 657     InputStreamBuffer()->WriteBack(c
); 
 668     f 
= f
*10 + (c 
- '0'); 
 673     double f_multiplicator 
= (double) 0.1; 
 677       f 
+= (c
-'0')*f_multiplicator
; 
 678       f_multiplicator 
/= 10; 
 689 wxInputStream
& wxInputStream::operator>>(wxObject 
*& obj
) 
 691   wxObjectInputStream 
obj_s(*this); 
 692   obj 
= obj_s
.LoadObject(); 
 698 // ---------------------------------------------------------------------------- 
 700 // ---------------------------------------------------------------------------- 
 701 wxOutputStream::wxOutputStream() 
 704   m_o_destroybuf 
= TRUE
; 
 705   m_o_streambuf 
= new wxStreamBuffer(*this, wxStreamBuffer::write
); 
 708 wxOutputStream::wxOutputStream(wxStreamBuffer 
*buffer
) 
 711   m_o_destroybuf 
= FALSE
; 
 712   m_o_streambuf 
= buffer
; 
 715 wxOutputStream::~wxOutputStream() 
 718     delete m_o_streambuf
; 
 721 wxOutputStream
& wxOutputStream::Write(const void *buffer
, size_t size
) 
 723   m_o_streambuf
->Write(buffer
, size
); 
 727 wxOutputStream
& wxOutputStream::Write(wxInputStream
& stream_in
) 
 729   stream_in
.Read(*this); 
 733 off_t 
wxOutputStream::TellO() const 
 735   return m_o_streambuf
->Tell(); 
 738 off_t 
wxOutputStream::SeekO(off_t pos
, wxSeekMode mode
) 
 740   return m_o_streambuf
->Seek(pos
, mode
); 
 743 void wxOutputStream::Sync() 
 745   m_o_streambuf
->FlushBuffer(); 
 748 wxOutputStream
& wxOutputStream::operator<<(const char *string
) 
 750   return Write(string
, strlen(string
)); 
 753 wxOutputStream
& wxOutputStream::operator<<(wxString
& string
) 
 756   const wxWX2MBbuf buf 
= string
.mb_str(); 
 759   return Write(string
, string
.Len()); 
 763 wxOutputStream
& wxOutputStream::operator<<(char c
) 
 768 wxOutputStream
& wxOutputStream::operator<<(short i
) 
 772   strint
.Printf(_T("%i"), i
); 
 773   return *this << strint
; 
 776 wxOutputStream
& wxOutputStream::operator<<(int i
) 
 780   strint
.Printf(_T("%i"), i
); 
 781   return *this << strint
; 
 784 wxOutputStream
& wxOutputStream::operator<<(long i
) 
 788   strlong
.Printf(_T("%i"), i
); 
 789   return *this << strlong
; 
 792 wxOutputStream
& wxOutputStream::operator<<(double f
) 
 796   strfloat
.Printf(_T("%f"), f
); 
 797   return *this << strfloat
; 
 801 wxOutputStream
& wxOutputStream::operator<<(wxObject
& obj
) 
 803   wxObjectOutputStream 
obj_s(*this); 
 804   obj_s
.SaveObject(obj
); 
 809 // ---------------------------------------------------------------------------- 
 810 // wxFilterInputStream 
 811 // ---------------------------------------------------------------------------- 
 812 wxFilterInputStream::wxFilterInputStream() 
 813   : wxInputStream(NULL
) 
 815   // WARNING streambuf set to NULL ! 
 818 wxFilterInputStream::wxFilterInputStream(wxInputStream
& stream
) 
 819   : wxInputStream(stream
.InputStreamBuffer()) 
 821   m_parent_i_stream 
= &stream
; 
 824 wxFilterInputStream::~wxFilterInputStream() 
 828 // ---------------------------------------------------------------------------- 
 829 // wxFilterOutputStream 
 830 // ---------------------------------------------------------------------------- 
 831 wxFilterOutputStream::wxFilterOutputStream() 
 832   : wxOutputStream(NULL
) 
 836 wxFilterOutputStream::wxFilterOutputStream(wxOutputStream
& stream
) 
 837   : wxOutputStream(stream
.OutputStreamBuffer()) 
 839   m_parent_o_stream 
= &stream
; 
 842 wxFilterOutputStream::~wxFilterOutputStream() 
 846 // ---------------------------------------------------------------------------- 
 847 // Some IOManip function 
 848 // ---------------------------------------------------------------------------- 
 850 wxOutputStream
& wxEndL(wxOutputStream
& stream
) 
 853   return stream
.Write("\r\n", 2); 
 855   return stream
.Write("\n", 1);