• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Stream.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <spl/types.h>
00018 
00019 #ifdef _WINDOWS
00020 #include <spl/configwin32.h>
00021 #include <stdio.h>
00022 #else
00023 #include <spl/autoconf/config.h>
00024 #endif
00025 
00026 #include <spl/io/BlockingStream.h>
00027 #include <spl/io/DualChannelStream.h>
00028 #include <spl/Int64.h>
00029 #include <spl/io/NullStream.h>
00030 #include <spl/text/StringBuffer.h>
00031 #include <spl/io/Stream.h>
00032 #include <spl/io/StreamBuffer.h>
00033 #include <spl/io/StreamDelegateDispatch.h>
00034 #include <spl/io/TextStream.h>
00035 #include <spl/io/ThreadSafeStream.h>
00036 #include <stdarg.h>
00037 #ifdef HAVE_ERRNO_H
00038 #include <errno.h>
00039 #endif
00040 
00041 extern char *int32toa( int32 i, char *buf, const int buflen );
00042 
00043 using namespace spl;
00044 
00045 StreamDelegateDispatch::~StreamDelegateDispatch()
00046 {
00047 }
00048 
00049 void StreamDelegateDispatch::Add(IStreamReadListener *l)
00050 {
00051         m_onClose += Delegate<IStreamReadListener>::Create(l, &IStreamReadListener::IStreamRead_OnClose);
00052         m_onError += DelegateOneParameter<IStreamReadListener, const String&>::Create(l, &IStreamReadListener::IStreamRead_OnError);
00053         m_onRead += DelegateTwoParameter<IStreamReadListener, const Array<byte>&, int>::Create(l, &IStreamReadListener::IStreamRead_OnRead);
00054 }
00055 
00056 #ifdef DEBUG
00057 void StreamDelegateDispatch::ValidateMem() const
00058 {
00059         m_onClose.ValidateMem();
00060         m_onError.ValidateMem();
00061         m_onRead.ValidateMem();
00062 }
00063 
00064 void StreamDelegateDispatch::CheckMem() const
00065 {
00066         m_onClose.CheckMem();
00067         m_onError.CheckMem();
00068         m_onRead.CheckMem();
00069 }
00070 #endif
00071 
00072 IStreamReadListener::~IStreamReadListener()
00073 {
00074 }
00075 
00076 IStream::IStream()
00077 {
00078 }
00079 
00080 IStream::~IStream()
00081 {
00082 }
00083 
00084 IStreamState::IStreamState( IStream* parent, IStreamState **parentStateVar )
00085 : m_parent(parent), m_holder(parentStateVar)
00086 {
00087 }
00088 
00089 IStreamState::~IStreamState()
00090 {
00091 }
00092 
00093 void IStreamState::ChangeState(IStreamState *newState)
00094 {
00095         this->OnLeave( newState );
00096         newState->OnEnter( this );
00097         *m_holder = newState;
00098         delete this;
00099 }
00100 
00101 NullStream::NullStream()
00102 {
00103 }
00104 
00105 NullStream::~NullStream()
00106 {
00107 }
00108 
00109 void NullStream::Close()
00110 {
00111 }
00112 
00113 void NullStream::Flush()
00114 {
00115 }
00116 
00117 int NullStream::Read(Array<byte>& buffer, const int offset, int count)
00118 {
00119         buffer[offset] = 0;
00120         return 0;
00121 }
00122 
00123 int NullStream::ReadByte()
00124 {
00125         return 0;
00126 }
00127 
00128 long NullStream::Seek(const long offset, const SeekOrigin origin)
00129 {
00130         return 0;
00131 }
00132 
00133 void NullStream::Write(const Array<byte>& buffer, const int offset, const int count)
00134 {
00135 }
00136 
00137 void NullStream::WriteByte(byte value)
00138 {
00139 }
00140 
00141 bool NullStream::CanRead() const
00142 {
00143         return true;
00144 }
00145 
00146 bool NullStream::CanSeek() const
00147 {
00148         return true;
00149 }
00150 
00151 bool NullStream::CanWrite() const
00152 {
00153         return true;
00154 }
00155 
00156 long NullStream::Length() const
00157 {
00158         return 0;
00159 }
00160 
00161 long NullStream::Position() const
00162 {
00163         return 0;
00164 }
00165 
00166 #ifdef DEBUG
00167 void NullStream::ValidateMem() const
00168 {
00169 }
00170 
00171 void NullStream::CheckMem() const
00172 {
00173 }
00174 #endif
00175 
00176 DualChannelStream::DualChannelStream(IStreamPtr input, IStreamPtr output, bool canClose)
00177 : m_in(input), m_out(output)
00178 {
00179 }
00180 
00181 DualChannelStream::~DualChannelStream()
00182 {
00183 }
00184 
00185 void DualChannelStream::Close()
00186 {
00187         m_in->Close();
00188         m_out->Close();
00189 }
00190 
00191 void DualChannelStream::Flush()
00192 {
00193         m_in->Flush();
00194         m_out->Flush();
00195 }
00196 
00197 int DualChannelStream::Read(Array<byte>& buffer, const int offset, int count)
00198 {
00199         return m_in->Read(buffer, offset, count);
00200 }
00201 
00202 int DualChannelStream::ReadByte()
00203 {
00204         return m_in->ReadByte();
00205 }
00206 
00207 long DualChannelStream::Seek(const long offset, const SeekOrigin origin)
00208 {
00209         return m_out->Seek(offset, origin);
00210 }
00211 
00212 void DualChannelStream::Write(const Array<byte>& buffer, const int offset, const int count)
00213 {
00214         m_out->Write(buffer, offset, count);
00215 }
00216 
00217 void DualChannelStream::WriteByte(byte value)
00218 {
00219         m_out->WriteByte(value);
00220 }
00221 
00222 bool DualChannelStream::CanRead() const
00223 {
00224         return m_in->CanRead();
00225 }
00226 
00227 bool DualChannelStream::CanSeek() const
00228 {
00229         return m_out->CanSeek();
00230 }
00231 
00232 bool DualChannelStream::CanWrite() const
00233 {
00234         return m_out->CanWrite();
00235 }
00236 
00237 long DualChannelStream::Length() const
00238 {
00239         return m_in->Length();
00240 }
00241 
00242 long DualChannelStream::Position() const
00243 {
00244         return m_out->Position();
00245 }
00246 
00247 #ifdef DEBUG
00248 void DualChannelStream::ValidateMem() const
00249 {
00250         m_in.ValidateMem();
00251         m_out.ValidateMem();
00252 }
00253 
00254 void DualChannelStream::CheckMem() const
00255 {
00256         m_in.CheckMem();
00257         m_out.CheckMem();
00258 }
00259 #endif
00260 
00261 BlockingStream::BlockingStream(IStreamPtr strm)
00262 : m_strm(strm), m_dataready(), m_datalock()
00263 {
00264         ASSERT(m_strm->CanRead());
00265 }
00266 
00267 BlockingStream::~BlockingStream()
00268 {
00269         m_strm->Close();
00270 }
00271 
00272 int BlockingStream::Read(Array<byte>& buffer, const int offset, int count)
00273 {
00274         int readbytes = 0;
00275 
00276         while ( 0 == readbytes )
00277         {
00278                 m_datalock.Lock();
00279                 int pending = m_strm->Length();
00280                 m_datalock.Unlock();
00281                 if ( 0 == pending )
00282                 {
00283                         m_dataready.Wait();
00284                 }
00285                 m_datalock.Lock();
00286                 readbytes = m_strm->Read(buffer, offset, count);
00287                 m_datalock.Unlock();
00288         }
00289         return readbytes;
00290 }
00291 
00292 int BlockingStream::ReadByte()
00293 {
00294         Array<byte> buf(1);
00295         int count = Read(buf, 0, 1);
00296         if ( 0 >= count )
00297         {
00298                 return -1;
00299         }
00300         return (int)buf[0];
00301 }
00302 
00303 void BlockingStream::Write(const Array<byte>& buffer, const int offset, const int count)
00304 {
00305         m_datalock.Lock();
00306         m_strm->Write(buffer, offset, count);
00307         m_datalock.Unlock();
00308         m_dataready.Notify();
00309 }
00310 
00311 void BlockingStream::WriteByte(byte value)
00312 {
00313         Array<byte> buf(1);
00314         buf[0] = value;
00315         Write(buf, 0, 1);
00316 }
00317 
00318 void BlockingStream::Close()
00319 {
00320         m_strm->Close();
00321 }
00322 
00323 void BlockingStream::Flush()
00324 {
00325         m_strm->Flush();
00326 }
00327 
00328 long BlockingStream::Seek(const long offset, const SeekOrigin origin)
00329 {
00330         return m_strm->Seek(offset, origin);
00331 }
00332 
00333 bool BlockingStream::CanRead() const
00334 {
00335         return m_strm->CanRead();
00336 }
00337 
00338 bool BlockingStream::CanSeek() const
00339 {
00340         return m_strm->CanSeek();
00341 }
00342 
00343 bool BlockingStream::CanWrite() const
00344 {
00345         return m_strm->CanWrite();
00346 }
00347 
00348 long BlockingStream::Length() const
00349 {
00350         return m_strm->Length();
00351 }
00352 
00353 long BlockingStream::Position() const
00354 {
00355         return m_strm->Position();
00356 }
00357 
00358 #ifdef DEBUG
00359 void BlockingStream::ValidateMem() const
00360 {
00361         m_strm->ValidateMem();
00362 }
00363 
00364 void BlockingStream::CheckMem() const
00365 {
00366         m_strm.CheckMem();
00367 }
00368 #endif
00369 
00370 TextWriter::TextWriter(IStreamPtr strm)
00371 : m_strm(strm)
00372 {
00373         if ( ! m_strm->CanWrite() )
00374         {
00375                 throw new InvalidArgumentException("Stream is not writable.");
00376         }
00377 }
00378 
00379 TextWriter::~TextWriter()
00380 {
00381 }
00382 
00383 void TextWriter::Close()
00384 {
00385         m_strm->Close();
00386 }
00387 
00388 void TextWriter::Flush()
00389 {
00390         m_strm->Flush();
00391 }
00392 
00393 void TextWriter::Write(const String& buf)
00394 {
00395         ASSERT ( sizeof(char) == sizeof(byte) );
00396 
00397         m_strm->Write( buf.ToByteArray() );
00398 }
00399 
00400 void TextWriter::Write(byte b)
00401 {
00402         Write((unsigned int)b);
00403 }
00404 
00405 void TextWriter::Write(int8 i)
00406 {
00407         char buf[128];
00408         int32toa(i, buf, 128);
00409         Write(buf);
00410 }
00411 
00412 void TextWriter::Write(int16 i)
00413 {
00414         char buf[128];
00415         int32toa(i, buf, 128);
00416         Write(buf);
00417 }
00418 
00419 void TextWriter::Write(int32 i)
00420 {
00421         char buf[128];
00422         int32toa(i, buf, 128);
00423         Write(buf);
00424 }
00425 
00426 void TextWriter::Write(int64 i)
00427 {
00428         Write(*Int64::ToString(i));
00429 }
00430 
00431 void TextWriter::Write(uint16 i)
00432 {
00433         char buf[128];
00434         int32toa(i, buf, 128);
00435         Write(buf);
00436 }
00437 
00438 void TextWriter::Write(uint32 i)
00439 {
00440         char buf[128];
00441         int32toa(i, buf, 128);
00442         Write(buf);
00443 }
00444 
00445 void TextWriter::Write(float32 f)
00446 {
00447         char buf[128];
00448         sprintf(buf, "%f", f);
00449         Write(buf);
00450 }
00451 
00452 void TextWriter::Write(float64 f)
00453 {
00454         char buf[128];
00455         sprintf(buf, "%lf", f);
00456         Write(buf);
00457 }
00458 
00459 void TextWriter::WriteLine(const String& str)
00460 {
00461         Write(str);
00462 #ifdef _WINDOWS
00463         Write("\r\n");
00464 #elif _MACOSX
00465         Write("\r");
00466 #else
00467         Write("\n");
00468 #endif
00469 }
00470 
00471 // FYI, va args doesn't work with reference.
00472 void TextWriter::WriteFormat(const String fmt, ...)
00473 {
00474         va_list marker;
00475         va_start(marker, fmt);
00476 
00477         StringPtr str = String::FormatVA(fmt, marker);
00478 
00479         Write(str->GetChars());
00480 }
00481 
00482 #ifdef DEBUG
00483 void TextWriter::ValidateMem() const
00484 {
00485         m_strm.ValidateMem();
00486 }
00487 
00488 void TextWriter::CheckMem() const
00489 {
00490         m_strm.CheckMem();
00491 }
00492 #endif
00493 
00494 TextReader::TextReader(IStreamPtr strm)
00495 : m_strm(strm), m_peekch(-1)
00496 {
00497 }
00498 
00499 TextReader::~TextReader()
00500 {
00501 }
00502 
00503 void TextReader::Close()
00504 {
00505         m_strm->Close();
00506 }
00507 
00508 int TextReader::Peek()
00509 {
00510         if ( m_peekch > -1 )
00511         {
00512                 return m_peekch;
00513         }
00514         m_peekch = Read();
00515         return m_peekch;
00516 }
00517 
00518 int TextReader::Read()
00519 {
00520         return _Read();
00521 }
00522 
00523 int TextReader::ReadBlock(Array<byte>& buf, int offset, int count)
00524 {
00525         ASSERT( count > 0 && offset >= 0 );
00526         if ( m_peekch > -1 )
00527         {
00528                 buf[offset++] = (char)m_peekch;
00529                 count--;
00530         }
00531 
00532         ASSERT ( sizeof(char) == sizeof(byte) );
00533         return m_strm->Read(buf, offset, count);
00534 }
00535 
00536 bool TextReader::ReadLine(StringBuffer& sb)
00537 {
00538         int ch;
00539 
00540         while ( '\n' != (ch = _Read()) )
00541         {
00542                 if ( -1 == ch )
00543                 {
00544                         if ( sb.Length() == 0 )
00545                         {
00546                                 return false;
00547                         }
00548                         return true;
00549                 }
00550                 if ( '\r' != ch )
00551                 {
00552                         sb.Append( (char)ch );
00553                 }
00554         }
00555         return true;
00556 }
00557 
00558 StringPtr TextReader::ReadLine()
00559 {
00560         StringBuffer buf;
00561         if ( ReadLine(buf) )
00562         {
00563                 return buf.ToString();
00564         }
00565         return StringPtr();
00566 }
00567 
00568 bool TextReader::ReadLine(Array<byte>& buf, int& lineLen)
00569 {
00570         int buflen = buf.Length();
00571         lineLen = 0;
00572 
00573         ASSERT( buflen > 0 );
00574         int ch = _Read();
00575 
00576         if ( -1 == ch )
00577         {
00578                 return false;
00579         }
00580 
00581         while ( lineLen < (buflen-1) && ch != '\n' && ch != -1 )
00582         {
00583                 if ( '\r' != ch )
00584                 {
00585                         buf[lineLen++] = ch;
00586                 }
00587                 ch = _Read();
00588         }
00589         buf[lineLen++] = '\0';
00590 
00591         return true;
00592 }
00593 
00594 StringPtr TextReader::ReadToEnd()
00595 {
00596         StringBuffer buf;
00597         int ch;
00598 
00599         while ( (ch = _Read()) > -1 )
00600         {
00601                 m_strm->ValidateMem();
00602                 buf.Append( (char)ch );
00603         }
00604         return buf.ToString();
00605 }
00606 
00607 #ifdef DEBUG
00608 void TextReader::ValidateMem() const
00609 {
00610         m_strm.ValidateMem();
00611 }
00612 
00613 void TextReader::CheckMem() const
00614 {
00615         m_strm.CheckMem();
00616 }
00617 #endif
00618 
00619 ThreadSafeStream::ThreadSafeStream( IStreamPtr strm )
00620 : m_strm(strm), m_lock()
00621 {
00622 }
00623 
00624 ThreadSafeStream::~ThreadSafeStream()
00625 {
00626         m_strm->Close();
00627 }
00628 
00629 void ThreadSafeStream::Close()
00630 {
00631         m_strm->Close();
00632 }
00633 
00634 void ThreadSafeStream::Flush()
00635 {
00636         m_lock.Lock();
00637         m_strm->Flush();
00638         m_lock.Unlock();
00639 }
00640 
00641 int ThreadSafeStream::Read(Array<byte>& buffer, const int offset, int count)
00642 {
00643         m_lock.Lock();
00644         int ret = m_strm->Read(buffer, offset, count);
00645         m_lock.Unlock();
00646         return ret;
00647 }
00648 
00649 int ThreadSafeStream::ReadByte()
00650 {
00651         m_lock.Lock();
00652         int ch = m_strm->ReadByte();
00653         m_lock.Unlock();
00654         return ch;
00655 }
00656 
00657 long ThreadSafeStream::Seek(const long offset, const SeekOrigin origin)
00658 {
00659         m_lock.Lock();
00660         long ret = m_strm->Seek(offset, origin);
00661         m_lock.Unlock();
00662         return ret;
00663 }
00664 
00665 void ThreadSafeStream::Write(const Array<byte>& buffer, const int offset, const int count)
00666 {
00667         m_lock.Lock();
00668         m_strm->Write(buffer, offset, count);
00669         m_lock.Unlock();
00670 }
00671 
00672 void ThreadSafeStream::WriteByte(byte value)
00673 {
00674         m_lock.Lock();
00675         m_strm->WriteByte(value);
00676         m_lock.Unlock();
00677 }
00678 
00679 bool ThreadSafeStream::CanRead() const
00680 {
00681         return m_strm->CanRead();
00682 }
00683 
00684 bool ThreadSafeStream::CanSeek() const
00685 {
00686         return m_strm->CanSeek();
00687 }
00688 
00689 bool ThreadSafeStream::CanWrite() const
00690 {
00691         return m_strm->CanWrite();
00692 }
00693 
00694 long ThreadSafeStream::Length() const
00695 {
00696         long len = m_strm->Length();
00697         return len;
00698 }
00699 
00700 long ThreadSafeStream::Position() const
00701 {
00702         long ret = m_strm->Position();
00703         return ret;
00704 }
00705 
00706 #ifdef DEBUG
00707 void ThreadSafeStream::ValidateMem() const
00708 {
00709         m_strm.ValidateMem();
00710 }
00711 
00712 void ThreadSafeStream::CheckMem() const
00713 {
00714         m_strm.CheckMem();
00715 }
00716 #endif
00717 
00718 StreamBuffer::StreamBuffer( IStreamPtr strm, const int buflen )
00719 :       m_strm(strm), 
00720         m_bufpos(0), 
00721         m_buflen(buflen), 
00722         m_buf(buflen)
00723 {
00724 }
00725 
00726 StreamBuffer::~StreamBuffer()
00727 {
00728         Flush();
00729         m_strm->Close();
00730 }
00731 
00732 void StreamBuffer::Close()
00733 {
00734         Flush();
00735         m_strm->Close();
00736 }
00737 
00738 void StreamBuffer::Flush()
00739 {
00740         if ( m_bufpos > 0 && m_strm->CanWrite() )
00741         {
00742                 m_strm->Write(m_buf, 0, m_bufpos);
00743         }
00744         m_bufpos = 0;
00745 }
00746 
00747 int StreamBuffer::Read(Array<byte>& buffer, const int offset, int count)
00748 {
00749         if ( m_bufpos == 0 )
00750         {
00751                 // load the buffer
00752                 m_bufpos = m_strm->Read(m_buf, 0, m_buflen);
00753                 if ( m_bufpos < 0 )
00754                 {
00755                         m_bufpos = 0;
00756                         return -1;
00757                 }
00758         }
00759         if ( count > m_bufpos )
00760         {
00761                 count = m_bufpos;
00762         }
00763         ASSERT( m_bufpos >= count );
00764         memcpy(&buffer[offset], m_buf, count);
00765         memcpy(m_buf, &m_buf[count], m_bufpos - count);
00766         m_bufpos -= count;
00767         return count;
00768 }
00769 
00770 int StreamBuffer::ReadByte()
00771 {
00772         Array<byte> buf(1);
00773         if ( 0 >= StreamBuffer::Read(buf, 0, 1) )
00774         {
00775                 return -1;
00776         }
00777         return (int)buf[0];
00778 }
00779 
00780 long StreamBuffer::Seek(const long offset, const SeekOrigin origin)
00781 {
00782         Flush();
00783         return m_strm->Seek(offset, origin);
00784 }
00785 
00786 void StreamBuffer::Write(const Array<byte>& buffer, const int offset, const int count)
00787 {
00788         if ( m_bufpos + count >= m_buflen )
00789         {
00790                 Flush();
00791         }
00792         if ( count >= m_buflen )
00793         {
00794                 m_strm->Write(buffer, offset, count);
00795         }
00796         else
00797         {
00798                 memcpy(&m_buf[m_bufpos], &buffer[offset], count);
00799                 m_bufpos += count;
00800         }
00801         ASSERT( m_bufpos < m_buflen );
00802 }
00803 
00804 void StreamBuffer::WriteByte(byte value)
00805 {
00806         if ( m_bufpos + 1 >= m_buflen )
00807         {
00808                 Flush();
00809         }
00810         m_buf[m_bufpos++] = value;
00811 }
00812 
00813 bool StreamBuffer::CanRead() const
00814 {
00815         return m_strm->CanRead();
00816 }
00817 
00818 bool StreamBuffer::CanSeek() const
00819 {
00820         return m_strm->CanSeek();
00821 }
00822 
00823 bool StreamBuffer::CanWrite() const
00824 {
00825         return m_strm->CanWrite();
00826 }
00827 
00828 long StreamBuffer::Length() const
00829 {
00830         return m_strm->Length();
00831 }
00832 
00833 long StreamBuffer::Position() const
00834 {
00835         if ( 0 != m_bufpos )
00836         {
00837                 throw new IOException("StreamBuffer: Flush before calling Position");
00838         }
00839         return m_strm->Position();
00840 }
00841 
00842 #ifdef DEBUG
00843 void StreamBuffer::ValidateMem() const
00844 {
00845         m_buf.ValidateMem();
00846         m_strm.ValidateMem();
00847 }
00848 
00849 void StreamBuffer::CheckMem() const
00850 {
00851         m_buf.CheckMem();
00852         m_strm.CheckMem();
00853 }
00854 #endif