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