00001
00002
00003
00004
00005
00012 #ifndef HFILE_H
00013 # define HFILE_H
00014
00015 #include "HString.h"
00016 #include <fcntl.h>
00023 class HFilename : public HString
00024 {
00025 friend class HFile;
00026 typedef HString base_class;
00027 static StringPtr ClassName(void) { return "HFilename"; }
00028
00029
00030
00031
00032
00033
00034
00035 public:
00036 HFilename(StringPtr pstr = NULL) : HString(pstr)
00037 { cleanUp(); }
00038
00039 virtual
00040 ~HFilename(void)
00041 { }
00042
00043
00044
00045 public:
00057 bool
00058 Select(StringPtr pstrTitle, uint32 uFlags, sSelectFileTypes * pFileTypes = NULL)
00059 {
00060 bool bOK;
00061 int32 nRC;
00062 Text szDir[MAX_PATH+1] = { '\0' },
00063 szName[MAX_PATH+1] = { '\0' };
00064
00065 split(szDir, szName, NULL);
00066
00067 nRC = GI_FileSelect(NULL, uFlags, const_cast<TextPtr>(pstrTitle),
00068 TEXT(szDir), TEXT(szName),
00069 pFileTypes);
00070 if (nRC == ID_OK)
00071 {
00072 bOK = true;
00073 m_str = szName;
00074 DEBUG_LOG("HFilename::Select() => user chose \"%s\".\n", m_str.c_str());
00075 }
00076 else
00077 {
00078 DEBUG_LOG("HFilename::Select() => user canceled file selection.\n");
00079 bOK = false;
00080 }
00081
00082 return bOK;
00083 }
00084 protected:
00092 void
00093 build(StringPtr pstrDir, StringPtr pstrFile, StringPtr pstrExt)
00094 {
00095 int32 nLen = 0;
00096
00097 SetEmpty();
00098
00099
00100
00101 if (STR_VALID(pstrDir))
00102 {
00103 m_str = pstrDir;
00104 cleanUp();
00105 nLen = m_str.length();
00106 }
00107
00108
00109
00110 if (nLen > 0 && m_str[nLen - 1] != kDirSeparator)
00111 m_str += kDirSeparator;
00112
00113
00114
00115 if (STR_VALID(pstrFile))
00116 {
00117 m_str += pstrFile;
00118 nLen = m_str.length();
00119 }
00120
00121
00122
00123 if (STR_VALID(pstrExt))
00124 {
00125 if (pstrExt[0] != '.')
00126 m_str += '.';
00127 m_str += pstrExt;
00128 nLen = m_str.length();
00129 }
00130
00131 cleanUp();
00132 }
00139 void
00140 cleanUp(void)
00141 {
00142 Trim();
00143 Replace('\\', kDirSeparator);
00144 }
00152 void
00153 split(TextPtr pstrDir, TextPtr pstrName, TextPtr pstrExt)
00154 {
00155 std::string::size_type sPos;
00156
00157
00158
00159
00160 if ((sPos = m_str.rfind('.')) != std::string::npos)
00161 {
00162 if (GOOD_PTR(pstrExt))
00163 STR_NCPY(pstrExt, &m_str[sPos], m_str.length());
00164 m_str[sPos] = '\0';
00165 }
00166
00167
00168
00169 if ((sPos = m_str.rfind(kDirSeparator)) != std::string::npos)
00170 {
00171 if (GOOD_PTR(pstrName))
00172 STR_NCPY(pstrName, &m_str[sPos + 1], m_str.length());
00173 m_str[sPos] = '\0';
00174 }
00175
00176
00177
00178 if (GOOD_PTR(pstrDir))
00179 STR_NCPY(pstrDir, m_str.c_str(), m_str.length());
00180 }
00181
00182
00183
00184 public:
00198 ErrCode
00199 GetDir(HString & strDir, bool bWantSlash = false) const
00200 {
00201 ErrCode ec = HError::NoError();
00202 int32 nSlash = FindLast(kDirSeparator);
00203
00204 strDir.SetEmpty();
00205 if (nSlash > 0 || (nSlash == 0 && bWantSlash))
00206 {
00207 strDir = Left(bWantSlash ? nSlash + 1 : nSlash);
00208
00209 DEBUG_LOG( "HFilename::GetDir(%s) => \"%s\"\n",
00210 m_str.c_str(), StringPtr(strDir));
00211 }
00212 else
00213 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00214
00215 return ec;
00216 }
00223 ErrCode
00224 SetDir(StringPtr pstrDir)
00225 {
00226 ErrCode ec = HError::NoError();
00227 HString strName;
00228
00229 if ((ec = GetName(strName)) == NO_ERROR)
00230 {
00231 build(STR_SAFE(pstrDir), strName.GetString(), NULL);
00232
00233 DEBUG_LOG("HFilename::SetDir(%s) => \"%s\"\n", pstrDir, m_str.c_str());
00234 }
00235
00236 return ec;
00237 }
00248 ErrCode
00249 GetExt(HString & strExt, bool bWantDot = false) const
00250 {
00251 ErrCode ec = HError::NoError();
00252 std::string::size_type sPos = m_str.rfind('.');
00253
00254 strExt.SetEmpty();
00255 if (sPos != std::string::npos)
00256 {
00257 strExt = bWantDot ? m_str.substr(sPos) : m_str.substr(sPos + 1);
00258
00259 DEBUG_LOG( "HFilename::GetExt(%s) => \"%s\"\n",
00260 m_str.c_str(), StringPtr(strExt));
00261 }
00262 else
00263 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00264
00265 return ec;
00266 }
00273 ErrCode
00274 SetExt(StringPtr pstrExt)
00275 {
00276 ErrCode ec = HError::NoError();
00277 HString strExt(pstrExt);
00278 std::string::size_type sPos;
00279
00280 if (STR_VALID(pstrExt))
00281 {
00282 if ((sPos = m_str.rfind('.')) != std::string::npos)
00283 m_str = m_str.substr(0, sPos);
00284
00285 sPos = (pstrExt[0] == '.') ? 1 : 0;
00286 m_str = m_str + '.' + &pstrExt[sPos];
00287
00288 DEBUG_LOG( "HFilename::SetExt(%s) => \"%s\"\n",
00289 pstrExt, m_str.c_str());
00290 }
00291 else
00292 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00293 return ec;
00294 }
00305 ErrCode
00306 GetName(HString & strName) const
00307 {
00308 std::string::size_type sPos = m_str.rfind(kDirSeparator);
00309
00310 strName = (sPos == std::string::npos) ? m_str :
00311 m_str.substr(sPos + 1);
00312
00313 DEBUG_LOG("HFilename::GetName(%s) => \"%s\"\n",
00314 m_str.c_str(), StringPtr(strName));
00315 return HError::NoError();
00316 }
00325 StringPtr
00326 GetPath(void) const
00327 { return GetString(); }
00328
00329
00330
00336 inline bool IsValid(void) const
00337 { return IsNotEmpty(); }
00338
00339
00340
00341 HFilename & operator = (StringPtr pstr)
00342 {
00343 if (STR_VALID(pstr))
00344 {
00345 m_str = pstr;
00346 cleanUp();
00347 }
00348 else
00349 m_str.empty();
00350
00351 return *this;
00352 }
00353 };
00354
00355
00356
00365 class HFile : public HObjNoCopy
00366 {
00367 typedef HObjNoCopy base_class;
00368 static StringPtr ClassName(void) { return "HFile"; }
00369
00370
00371
00372 protected:
00373 bool m_bEOF;
00374 FILE * m_pFile;
00375 uint32 m_uFlags;
00376
00377
00378
00379 public:
00380 HFile(void) : m_bEOF(false), m_pFile(NULL), m_uFlags(0)
00381 { }
00382
00383 virtual
00384 ~HFile(void)
00385 { Close(); }
00386
00387
00388
00389 public:
00396 static ErrCode
00397 Delete(const HFilename & fs)
00398 {
00399 ErrCode ec = HError::NoError();
00400
00401 try
00402 {
00403 if (!fs.IsValid())
00404 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00405
00406 if (!Exists(fs))
00407 HError::Throw(ERR_NOT_FOUND, __FILE__, __LINE__);
00408
00409 if (unlink( fs.GetPath() ) != 0)
00410 HError::Throw(ERR_FILE_DELETE, __FILE__, __LINE__);
00411
00412 DEBUG_LOG("HFile::Delete(%s) => OK\n", fs.GetPath());
00413 }
00414 catch (const std::exception & e)
00415 {
00416 DEBUG_LOG("HFile::Delete(%s) => caught %s\n", fs.GetPath(), e.what());
00417
00418 ec = ErrCode( HError::GetLastError() );
00419 ASSERT( ec != NO_ERROR );
00420 }
00421
00422 return ec;
00423 }
00430 static bool
00431 Exists(const HFilename & fs)
00432 {
00433 bool bExists = false;
00434
00435 if (fs.IsValid())
00436 bExists = (access(fs.GetPath(), R_OK) >= 0);
00437 else
00438 (void) HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00439
00440 return bExists;
00441 }
00447 virtual ErrCode
00448 Close(void)
00449 {
00450 ErrCode ec = HError::NoError();
00451
00452 if (IsOpen())
00453 {
00454 if (fclose(m_pFile) == 0)
00455 {
00456 m_pFile = NULL;
00457 m_uFlags = 0;
00458 }
00459 else
00460 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00461 }
00462
00463 return ec;
00464 }
00472 virtual ErrCode
00473 Open(HFilename fs, uint32 uFlags = (O_BINARY|O_CREAT|O_RDWR))
00474 {
00475 ErrCode ec = HError::NoError();
00476
00477 if ((ec = Close()) != NO_ERROR)
00478 return ec;
00479
00480 if (fs.IsValid())
00481 {
00482 const int32 kModeLen = 15;
00483 Text szMode[kModeLen+1] = { '\0' };
00484
00485 if (uFlags & O_WRONLY)
00486 {
00487 STR_CAT(szMode, ((uFlags & O_APPEND) ? "a" : "w"), kModeLen);
00488 }
00489 else if (uFlags & O_RDWR)
00490 {
00491 if (uFlags & O_APPEND)
00492 STR_CAT(szMode, "a+", kModeLen);
00493 else if (uFlags & O_TRUNC)
00494 STR_CAT(szMode, "w+", kModeLen);
00495 else
00496 STR_CAT(szMode, "r+", kModeLen);
00497 }
00498 else
00499 {
00500 STR_CAT(szMode, "r", kModeLen);
00501 }
00502
00503 if (uFlags & O_BINARY)
00504 STR_CAT(szMode, "b", kModeLen);
00505
00506 DEBUG_LOG( "HFile::Open() => opening \"%s\" with mode \"%s\".\n",
00507 fs.GetPath(), szMode);
00508
00509 m_pFile = fopen(fs.GetPath(), szMode);
00510 if (IsOpen())
00511 {
00512 m_bEOF = false;
00513 m_uFlags = uFlags;
00514
00515 DEBUG_LOG( "HFile::Open() => ok\n");
00516 }
00517 else
00518 {
00519 DEBUG_LOG( "HFile::Open() => FAILED!\n");
00520 ec = HError::Set(ERR_FILE_OPEN, __FILE__, __LINE__);
00521 }
00522 }
00523 else
00524 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00525
00526 return ec;
00527 }
00534 virtual uint32
00535 Read(HMemory & buffer)
00536 { return Read(buffer.GetPtr(), buffer.GetSize()); }
00544 virtual uint32
00545 Read(void * pData, const uint32 uBytes)
00546 {
00547 ErrCode ec = HError::NoError();
00548 uint32 uActual = 0;
00549
00550 if (GOOD_PTR(pData) && uBytes > 0)
00551 {
00552 if (IsOpen() && !m_bEOF)
00553 {
00554 ASSERT( 1 == sizeof(uint8) );
00555 uActual = fread(pData, 1, uBytes, m_pFile);
00556 if (uActual < uBytes)
00557 {
00558 m_bEOF = true;
00559 DEBUG_LOG( "HFile::Read() => read only %lu of %lu bytes\n",
00560 uActual, uBytes);
00561 }
00562 }
00563 else
00564 ec = HError::Set(ERR_FILE_READ, __FILE__, __LINE__);
00565 }
00566 else
00567 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00568
00569 return uActual;
00570 }
00578 virtual int32
00579 ReadLine(TextPtr pszLine, const uint32 uMaxLen)
00580 {
00581 ErrCode ec = HError::NoError();
00582 int32 nLineLen = -1;
00583
00584 if (GOOD_PTR(pszLine) && uMaxLen > 0)
00585 {
00586 if (IsOpen() && !m_bEOF)
00587 {
00588 TextPtr psz;
00589
00590 for (psz = pszLine; psz < &pszLine[uMaxLen-1]; ++psz)
00591 {
00592 if (Read(psz, sizeof(Text)) != sizeof(Text))
00593 {
00594 m_bEOF = true;
00595 if ((nLineLen = int32(psz - pszLine)) == 0)
00596 nLineLen = -1;
00597
00598 break;
00599 }
00600
00601 if (*psz == '\n')
00602 {
00603 nLineLen = int32(psz - pszLine);
00604 break;
00605 }
00606 }
00607
00608 ASSERT( psz >= pszLine && psz < &pszLine[uMaxLen] );
00609 *psz = '\0';
00610 }
00611 else
00612 ec = HError::Set(ERR_FILE_READ, __FILE__, __LINE__);
00613 }
00614 else
00615 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00616
00617 return nLineLen;
00618 }
00626 int32
00627 Seek(int32 lOffset, const int nFrom) const
00628 {
00629 int32 lPos = ~0L;
00630
00631 ASSERT( nFrom == SEEK_CUR || nFrom == SEEK_END || nFrom == SEEK_SET );
00632
00633 if (IsOpen() && fseek(m_pFile, lOffset, nFrom) == 0)
00634 {
00635 lPos = ftell(m_pFile);
00636 DEBUG_LOG( "HFile::Seek() => moved %ld from %d to %ld.\n",
00637 lOffset, nFrom, lPos);
00638 }
00639
00640 return lPos;
00641 }
00649 virtual uint32
00650 Write(PtrConst pData, uint32 uBytes) const
00651 {
00652 ErrCode ec = HError::NoError();
00653 uint32 uActual = 0;
00654
00655 if (GOOD_PTR(pData) && uBytes > 0)
00656 {
00657 if (IsWritable())
00658 {
00659 uActual = fwrite(pData, 1, uBytes, m_pFile);
00660 }
00661 else
00662 ec = HError::Set(ERR_FILE_WRITE, __FILE__, __LINE__);
00663 }
00664 else
00665 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00666
00667 return uActual;
00668 }
00675 virtual uint32
00676 Write(HMemory const & buffer) const
00677 { return Write(static_cast<PtrConst>( buffer.GetPtr() ), buffer.GetSize()); }
00684 virtual uint32
00685 WriteLine(StringPtr pstr = NULL) const
00686 {
00687 ErrCode ec = HError::NoError();
00688 uint32 uBytes = 0;
00689
00690 if (IsWritable())
00691 {
00692 if (GOOD_PTR(pstr))
00693 {
00694 uint32 uLen = STR_LEN(pstr);
00695
00696 if (uLen > 0)
00697 uBytes += Write(reinterpret_cast<PtrConst>( pstr ), uLen);
00698 }
00699
00700 uBytes += Write(reinterpret_cast<PtrConst>( "\n" ), 1);
00701 }
00702 else
00703 ec = HError::Set(ERR_FILE_WRITE, __FILE__, __LINE__);
00704
00705 return uBytes;
00706 }
00707
00708
00709
00715 static ErrCode
00716 GetAppDirectory(HFilename & fsAppDir)
00717 {
00718 ErrCode ec = HError::NoError();
00719 Text szDir[MAX_PATH+1] = { '\0' };
00720
00721 if (GetApplicationDirectory(szDir) == S_OK)
00722 fsAppDir = szDir;
00723 else
00724 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00725
00726 return ec;
00727 }
00734 static ErrCode
00735 GetLength(const HFilename & fs, uint32 & uBytes)
00736 {
00737 ErrCode ec = HError::NoError();
00738
00739 uBytes = 0;
00740
00741 if (fs.IsValid())
00742 {
00743 struct stat statInfo;
00744
00745 if (stat(fs.GetPath(), &statInfo) == 0)
00746 uBytes = statInfo.st_size;
00747 else
00748 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00749 }
00750 else
00751 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00752
00753 return ec;
00754 }
00755
00756
00757
00760 inline bool IsAtEOF(void) const
00761 { return m_bEOF; }
00764 inline bool IsBinary(void) const
00765 { return (IsOpen() && (m_uFlags & O_BINARY)); }
00768 inline bool IsOpen(void) const
00769 { return GOOD_PTR(m_pFile); }
00772 inline bool IsWritable(void) const
00773 { return (IsOpen() && (m_uFlags & (O_RDWR|O_WRONLY))); }
00774 };
00775 #endif // HFILE_H
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807