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

src/StreamFd.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 #ifdef _WIN32
00018 #include <spl/configwin32.h>
00019 #else
00020 #include <spl/autoconf/config.h>
00021 #endif
00022 
00023 #include <spl/io/FileStream.h>
00024 
00025 #ifdef HAVE_IO_H
00026 #include <io.h>
00027 #endif
00028 #ifdef HAVE_FCNTL_H
00029 #include <fcntl.h>
00030 #endif
00031 #ifdef HAVE_SYS_FCNTL_H
00032 #include <sys/fcntl.h>
00033 #endif
00034 
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038 #ifdef HAVE_ERRNO_H
00039 #include <errno.h>
00040 #endif
00041 
00042 using namespace spl;
00043 
00044 class FdStreamState_Closed : public IStreamState
00045 {
00046 public:
00047         FdStreamState_Closed(spl::IStream *parent, IStreamState **parentStateVar);
00048         virtual ~FdStreamState_Closed();
00049 
00050         virtual void OnLeave(IStreamState *newState);
00051         virtual void OnEnter(IStreamState *oldState);
00052 
00053         virtual void Close();
00054         virtual void Flush();
00055         virtual int Read(Array<byte>& buffer, const int offset, int count);
00056         virtual int ReadByte();
00057         virtual long Seek(const long offset, const SeekOrigin origin);
00058         virtual void Write(const Array<byte>& buffer, const int offset, const int count);
00059         virtual void WriteByte(byte value);
00060 
00061         virtual bool CanRead() const;
00062         virtual bool CanSeek() const;
00063         virtual bool CanWrite() const;
00064 
00065         virtual long Length() const;
00066         virtual long Position() const;
00067 #ifdef DEBUG
00068         virtual void ValidateMem() const;
00069         virtual void CheckMem() const;
00070 #endif
00071 };
00072 
00073 FdStreamState_Closed::FdStreamState_Closed
00074 (
00075         spl::IStream *parent, 
00076         IStreamState **parentStateVar
00077 )
00078 : IStreamState(parent, parentStateVar)
00079 {
00080 }
00081 
00082 FdStreamState_Closed::~FdStreamState_Closed()
00083 {
00084 }
00085 
00086 void FdStreamState_Closed::OnLeave(IStreamState *newState)
00087 {
00088 }
00089 
00090 void FdStreamState_Closed::OnEnter(IStreamState *oldState)
00091 {
00092 }
00093 
00094 void FdStreamState_Closed::Close()
00095 {
00096         throw new IOException("File is closed, so it can't be closed again.");
00097 }
00098 
00099 void FdStreamState_Closed::Flush()
00100 {
00101         throw new IOException("File is closed, so it can't be flushed");
00102 }
00103 
00104 int FdStreamState_Closed::Read(Array<byte>& buffer, const int offset, int count)
00105 {
00106         throw new IOException("File is closed, so it can't be read");
00107 }
00108 
00109 int FdStreamState_Closed::ReadByte()
00110 {
00111         throw new IOException("File is closed, so it can't be read");
00112 }
00113 
00114 long FdStreamState_Closed::Seek(const long offset, const SeekOrigin origin)
00115 {
00116         throw new IOException("File is closed, so it can't be seeked");
00117 }
00118 
00119 void FdStreamState_Closed::Write(const Array<byte>& buffer, const int offset, const int count)
00120 {
00121         throw new IOException("File is closed, so it can't be written");
00122 }
00123 
00124 void FdStreamState_Closed::WriteByte(byte value)
00125 {
00126         throw new IOException("File is closed, so it can't be written");
00127 }
00128 
00129 bool FdStreamState_Closed::CanRead() const
00130 {
00131         throw new NotImplementedException();
00132 }
00133 
00134 bool FdStreamState_Closed::CanSeek() const
00135 {
00136         throw new NotImplementedException();
00137 }
00138 
00139 bool FdStreamState_Closed::CanWrite() const
00140 {
00141         throw new NotImplementedException();
00142 }
00143 
00144 long FdStreamState_Closed::Length() const
00145 {
00146         throw new IOException("File is closed");
00147 }
00148 
00149 long FdStreamState_Closed::Position() const
00150 {
00151         throw new IOException("File is closed");
00152 }
00153 
00154 #ifdef DEBUG
00155 void FdStreamState_Closed::ValidateMem() const
00156 {
00157 }
00158 
00159 void FdStreamState_Closed::CheckMem() const
00160 {
00161 }
00162 #endif
00163 
00164 class FdStreamState_Open : public IStreamState
00165 {
00166 public:
00167         FdStreamState_Open(IStream *parent, IStreamState **parentStateVar);
00168         virtual ~FdStreamState_Open();
00169 
00170         virtual void OnLeave(IStreamState *newState);
00171         virtual void OnEnter(IStreamState *oldState);
00172 
00173         virtual void Close();
00174         virtual void Flush();
00175         virtual int Read(Array<byte>& buffer, const int offset, int count);
00176         virtual int ReadByte();
00177         virtual long Seek(const long offset, const SeekOrigin origin);
00178         virtual void Write(const Array<byte>& buffer, const int offset, const int count);
00179         virtual void WriteByte(byte value);
00180 
00181         virtual bool CanRead() const;
00182         virtual bool CanSeek() const;
00183         virtual bool CanWrite() const;
00184 
00185         virtual long Length() const;
00186         virtual long Position() const;
00187 #ifdef DEBUG
00188         virtual void ValidateMem() const;
00189         virtual void CheckMem() const;
00190 #endif
00191 };
00192 
00193 FdStreamState_Open::FdStreamState_Open
00194 (
00195         IStream* parent, 
00196         IStreamState **parentStateVar
00197 )
00198 : IStreamState(parent, parentStateVar)
00199 {
00200 }
00201 
00202 FdStreamState_Open::~FdStreamState_Open()
00203 {
00204 }
00205 
00206 void FdStreamState_Open::OnLeave(IStreamState *newState)
00207 {
00208         if ( ((FdStream *)m_parent)->m_canClose )
00209         {
00210                 close( ((FdStream *)m_parent)->m_fd );
00211         }
00212 }
00213 
00214 void FdStreamState_Open::OnEnter(IStreamState *oldState)
00215 {
00216 }
00217 
00218 void FdStreamState_Open::Close()
00219 {
00220         IStreamState *newstate = new FdStreamState_Closed(m_parent, m_holder);
00221         ChangeState(newstate);
00222 }
00223 
00224 void FdStreamState_Open::Flush()
00225 {
00226         //flush( ((FdStream *)m_parent)->m_fd);
00227 }
00228 
00229 int FdStreamState_Open::Read(Array<byte>& buffer, const int offset, int count)
00230 {
00231         ASSERT(offset + count <= buffer.Length());
00232 
00233         int ret = (int)read(((FdStream *)m_parent)->m_fd, &(buffer.Data()[offset]), count);
00234         ((FdStream *)m_parent)->m_lasterr = errno;
00235         return ret;
00236 }
00237 
00238 int FdStreamState_Open::ReadByte()
00239 {
00240         byte b;
00241         read(((FdStream *)m_parent)->m_fd, &b, 1);
00242         return b;
00243 }
00244 
00245 long FdStreamState_Open::Seek(const long offset, const SeekOrigin origin)
00246 {
00247         throw new NotImplementedException();
00248 }
00249 
00250 void FdStreamState_Open::Write(const Array<byte>& buffer, const int offset, const int count)
00251 {
00252         ASSERT(offset + count <= buffer.Length());
00253 
00254         write(((FdStream *)m_parent)->m_fd, &(buffer.Data()[offset]), count);
00255         ((FdStream *)m_parent)->m_lasterr = errno;
00256 }
00257 
00258 void FdStreamState_Open::WriteByte(byte value)
00259 {
00260         write(((FdStream *)m_parent)->m_fd, &value, 1);
00261         ((FdStream *)m_parent)->m_lasterr = errno;
00262 }
00263 
00264 bool FdStreamState_Open::CanRead() const
00265 {
00266         throw new NotImplementedException();
00267 }
00268 
00269 bool FdStreamState_Open::CanSeek() const
00270 {
00271         throw new NotImplementedException();
00272 }
00273 
00274 bool FdStreamState_Open::CanWrite() const
00275 {
00276         throw new NotImplementedException();
00277 }
00278 
00279 long FdStreamState_Open::Length() const
00280 {
00281         throw new NotImplementedException();
00282 }
00283 
00284 long FdStreamState_Open::Position() const
00285 {
00286         throw new NotImplementedException();
00287         //return tell(((FdStream *)m_parent)->m_fd);
00288 }
00289 
00290 #ifdef DEBUG
00291 void FdStreamState_Open::ValidateMem() const
00292 {
00293 }
00294 
00295 void FdStreamState_Open::CheckMem() const
00296 {
00297 }
00298 #endif
00299 
00300 FdStream::FdStream(int fp, File::FileAccess access, bool canClose)
00301 : m_filepathname(""), m_mode(File::FILEMODE_Open), m_access(access), m_canClose(canClose), m_lasterr(0), m_state(NULL)
00302 {
00303         m_fd = fp;
00304         m_state = new FdStreamState_Open(this, &m_state);
00305 }
00306 
00307 FdStream::FdStream(const String& path, File::FileMode mode, File::FileAccess access)
00308 : m_filepathname(path), m_mode(mode), m_access(access), 
00309 m_canClose(true), m_lasterr(0), m_state(NULL)
00310 {
00311         if ( File::Exists(path) )
00312         {
00313                 if ( File::FILEMODE_CreateNew == mode )
00314                 {
00315                         throw new IOException("File exists");
00316                 }
00317                 if ( File::FILEMODE_Truncate == mode )
00318                 {
00319                         if ( 0 > (m_fd = open(path.GetChars(), O_WRONLY)) )
00320                         {
00321                                 close(m_fd);
00322                         }
00323                 }
00324         }
00325         else if ( File::FILEMODE_Open == mode )
00326         {
00327                 throw new IOException("File not found");
00328         }
00329         else
00330         {
00331                 // create the file
00332                 if ( 0 > (m_fd = open(path.GetChars(), O_APPEND)) )
00333                 {
00334                         close(m_fd);
00335                 }
00336         }
00337         if ( File::FILEMODE_Append == mode )
00338         {
00339                 if ( File::FILEACC_Read == access )
00340                 {
00341                         m_fd = open(path.GetChars(), O_APPEND);
00342                 }
00343                 else
00344                 {
00345                         m_fd = open(path.GetChars(), O_APPEND);
00346                 }
00347         }
00348         else
00349         {
00350                 if ( File::FILEACC_Read == access )
00351                 {
00352                         m_fd = open(path.GetChars(), O_RDONLY);
00353                 }
00354                 else if ( File::FILEACC_Write == access )
00355                 {
00356                         m_fd = open(path.GetChars(), O_RDONLY);
00357                 }
00358                 else
00359                 {
00360                         m_fd = open(path.GetChars(), O_RDONLY);
00361                 }
00362         }
00363         if ( 0 > m_fd )
00364         {
00365                 throw new IOException("Can't open file");
00366         }
00367         else
00368         {
00369                 m_state = new FdStreamState_Open(this, &m_state);
00370         }
00371 }
00372 
00373 FdStream::~FdStream()
00374 {
00375         Close();
00376         delete m_state;
00377 }
00378 
00379 void FdStream::Close()
00380 {
00381         m_state->Close();
00382 }
00383 
00384 void FdStream::Flush()
00385 {
00386         m_state->Flush();
00387 }
00388 
00389 int FdStream::Read(Array<byte>& buffer, const int offset, int count)
00390 {
00391         return m_state->Read(buffer, offset, count);
00392 }
00393 
00394 int FdStream::ReadByte()
00395 {
00396         return m_state->ReadByte();
00397 }
00398 
00399 long FdStream::Seek(const long offset, const SeekOrigin origin)
00400 {
00401         return m_state->Seek(offset, origin);
00402 }
00403 
00404 void FdStream::Write(const Array<byte>& buffer, const int offset, const int count)
00405 {
00406         m_state->Write(buffer, offset, count);
00407 }
00408 
00409 void FdStream::WriteByte(byte value)
00410 {
00411         m_state->WriteByte(value);
00412 }
00413 
00414 bool FdStream::CanRead() const
00415 {
00416         return m_access != File::FILEACC_Write;
00417 }
00418 
00419 bool FdStream::CanSeek() const
00420 {
00421         return true;
00422 }
00423 
00424 bool FdStream::CanWrite() const
00425 {
00426         return m_access != File::FILEACC_Read;
00427 }
00428 
00429 long FdStream::Length() const
00430 {
00431         return m_state->Length();
00432 }
00433 
00434 long FdStream::Position() const
00435 {
00436         return m_state->Position();
00437 }
00438 
00439 #ifdef DEBUG
00440 void FdStream::ValidateMem() const
00441 {
00442         m_filepathname.ValidateMem();
00443         ASSERT_PTR( m_state );
00444         m_state->ValidateMem();
00445 }
00446 
00447 void FdStream::CheckMem() const
00448 {
00449         m_filepathname.CheckMem();
00450         DEBUG_NOTE_MEM( m_state );
00451         m_state->CheckMem();
00452 }
00453 #endif