Humble Framework for SkyOS


Main Page | Modules | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

HFile.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 **  $Header: /SkyOS.root/pig/Humble/HFile.h 5     2/04/05 10:45a Neusel $
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     VARIABLES
00030     ----------------------------------------------------------------------  */
00031 
00032 /*  ----------------------------------------------------------------------
00033     CTOR / DTOR
00034     ----------------------------------------------------------------------  */
00035 public:
00036     HFilename(StringPtr pstr = NULL) : HString(pstr)
00037         { cleanUp(); }
00038         
00039     virtual             
00040     ~HFilename(void)
00041         { /* EMPTY DTOR */ }
00042 /*  ----------------------------------------------------------------------
00043     METHODS
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         //  Start with the directory and strip off leading/trailing whitespace
00100         //
00101         if (STR_VALID(pstrDir))
00102             {
00103             m_str = pstrDir;
00104             cleanUp();
00105             nLen = m_str.length();
00106             }
00107         //
00108         //  Make sure there's a trailing '/' characters on the end
00109         //
00110         if (nLen > 0 && m_str[nLen - 1] != kDirSeparator)
00111             m_str += kDirSeparator;
00112         //
00113         //  Add in the filename
00114         //
00115         if (STR_VALID(pstrFile))
00116             {
00117             m_str += pstrFile;
00118             nLen = m_str.length();
00119             }
00120         //
00121         //  If there's an extension, make sure there's a leading '.'
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         //  Start stripping the components out in reverse order.  Find the
00158         //  extension first by looking for the dot.
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'; // replace the dot with a '\0' to shorten the string
00165             }
00166         //
00167         //  Now strip off the name by looking for the last slash
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         //  Whatever's left is the directory
00177         //
00178         if (GOOD_PTR(pstrDir))
00179             STR_NCPY(pstrDir, m_str.c_str(), m_str.length());
00180         }           
00181 /*  ----------------------------------------------------------------------
00182     GETTERS & SETTERS
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     INLINES
00330     ----------------------------------------------------------------------  */
00336     inline bool         IsValid(void) const
00337                             { return IsNotEmpty();  }
00338 /*  ----------------------------------------------------------------------
00339     OPERATORS
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     HFile class -- no implementation file
00356     ----------------------------------------------------------------------  */
00365 class HFile : public HObjNoCopy
00366     {
00367     typedef HObjNoCopy  base_class;
00368     static StringPtr    ClassName(void) { return "HFile"; }
00369 /*  ----------------------------------------------------------------------
00370     VARIABLES
00371     ----------------------------------------------------------------------  */
00372 protected:
00373     bool            m_bEOF;             
00374     FILE *          m_pFile;            
00375     uint32          m_uFlags;           
00376 /*  ----------------------------------------------------------------------
00377     CTOR / DTOR
00378     ----------------------------------------------------------------------  */
00379 public:
00380     HFile(void) : m_bEOF(false), m_pFile(NULL), m_uFlags(0)
00381         { /* STUB CTOR */ }
00382         
00383     virtual
00384     ~HFile(void)
00385         { Close(); }
00386 /*  ----------------------------------------------------------------------
00387     METHODS
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)  // write only
00486                 {
00487                 STR_CAT(szMode, ((uFlags & O_APPEND) ? "a" : "w"), kModeLen);
00488                 }
00489             else if (uFlags & O_RDWR)   // read/write
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    // read-only (O_RDONLY is zero, so we can't test against it)
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     GETTERS & SETTERS
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     INLINES
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 **  $History: HFile.h $
00779  * 
00780  * *****************  Version 5  *****************
00781  * User: Neusel       Date: 2/04/05    Time: 10:45a
00782  * Updated in $/SkyOS.root/pig/Humble
00783  * 
00784  * *****************  Version 4  *****************
00785  * User: Neusel       Date: 2/02/05    Time: 3:03p
00786  * Updated in $/SkyOS.root/pig/Humble
00787  * Incorporated HString / HStr name changes (Empty() => SetEmpty())
00788  * 
00789  * *****************  Version 3  *****************
00790  * User: Neusel       Date: 12/08/04   Time: 5:06p
00791  * Updated in $/SkyOS.root/pig/Humble
00792  * 20041208
00793  * 
00794  * *****************  Version 2  *****************
00795  * User: Neusel       Date: 11/30/04   Time: 1:01p
00796  * Updated in $/SkyOS.root/pig/Humble
00797  * Released as HUMBLE_VER 20041130.
00798  * 
00799  * *****************  Version 1  *****************
00800  * User: Neusel       Date: 11/23/04   Time: 8:24a
00801  * Created in $/SkyOS.root/pig/Humble
00802 **
00803 **  -------------------------------------------------------------------------
00804 **
00805 **  End of HFile.h
00806 **
00807 ****************************************************************************/