chxavfileutil.cpp

来自「著名的 helix realplayer 基于手机 symbian 系统的 播放」· C++ 代码 · 共 1,149 行 · 第 1/3 页

CPP
1,149
字号
    const TInt k_cchMinPath = 2; // must have at least 'a:'

    TInt cchPath = path.Length();
    if( cchPath >= k_cchMinPath )
    {
        TChar ch = path[0];
        bool bGood = ( ch.IsAlpha() && (path[1] == KDriveDelimiter) );
        if( bGood && (cchPath != k_cchMinPath) )
        {
            // a '\' is required unless the path is solely in the format 'a:'
            bGood = (path[2] == KPathDelimiter);
        }

        if( bGood )
        {
            ch.LowerCase();
            idx = ch - TChar('a');
        }
    }

    DPRINTF(SYMP_FILE, ("GetDriveIndex(): index is %d\n", idx));
    return idx;

}

////////////////////////////////////////////////////
//
CHXAvFile::DriveState TranslateDriveErrorCode(TInt err)
{
    CHXAvFile::DriveState driveState(dsUnknown);
    
    DPRINTF(SYMP_FILE, ("TranslateDriveErrorCode(): epoc code = %d\n", err));
    // translate error code
    switch (err)
    {
        case KErrNone:
            driveState = dsAccessible;
            break;
        case KErrLocked:
            driveState = dsLocked;
            break;
        case KErrCorrupt:
            driveState = dsCorrupted;
            break;
        default:
            driveState = dsUnknown;
            break;
    }

    DPRINTF(SYMP_FILE, ("TranslateDriveErrorCode(): code = %d\n", driveState));
    return driveState;
}

////////////////////////////////////////////////////
//
// lazy-mount drive (if necessary) and return true if locked
//
bool IsMountLocked(TInt idxDrive)
{
    DPRINTF(SYMP_FILE, ("IsMountLocked(): idxDrive = %d\n", idxDrive));
    RFs& fs = CCoeEnv::Static()->FsSession();

    TFullName fsName;
    TInt err = fs.FileSystemName(fsName, idxDrive);
    DPRINTF(SYMP_FILE, ("IsMountLocked(): err = %d; fs name = %s\n", err, dbg::CharPtr(fsName)()));
    if( (KErrNone == err) && (0 == fsName.Length()) )
    {
        DPRINTF(SYMP_FILE, ("IsMountLocked(): no name; mounting\n"));

        //
        // drive is present but not mounted; attempt to mount drive
        // now; mmc mount will succeed if password is cached
        //
        _LIT( KFat, "Fat" );
        err = fs.MountFileSystem(KFat, idxDrive);
    }
    
    return (err == KErrLocked);

}

////////////////////////////////////////////////////
// from experimentation on device:
//
// local fs:
//  FileSystemName returns 0; name = 'Lffs'
//  type = 6 (EMediaFlash); drive attr = 145; media_attr = 4(KMediaAttFormattable)
//
// unlocked mmc inserted:
//  FileSystemName returns 0; name = 'Fat'
//  type = 3 (EMediaHardDisk); drive attr = 33; media attr = 84(KMediaAttFormattable + 0x80)
//
// unlocked mmc, low mem:
//  type = 0 (EMediaNotPresent); attr = 33; media att = 112 (0x20 = KMediaAttLocked)
//
// locked mmc inserted:
//  FileSystemName returns 0; name = ''
//  MountFileSystem returns -22 (KErrLocked) 
//  Volume() fails, returns -18 (KErrNotReady) 
//
// mmc not inserted
//  FileSystemName returns 0; name = 'Fat'
//  Volume() fails, returns -18 (KErrNotReady)
//

////////////////////////////////////////////////////
// get drive information from drive index
//
DriveInfo GetDriveInfo(TInt idxDrive)
{
    DPRINTF(SYMP_FILE, ("GetDriveInfo(): looking at drive '%c:'\n", idxDrive + 'a'));

    DriveInfo info;
   
    if(idxDrive != -1)
    {
        info.idxDrive = idxDrive;
        
        //
        // This will fail if drive is locked or not inserted
        //
        RFs& fs = CCoeEnv::Static()->FsSession();
        TInt err = fs.Volume(info.volInfo, idxDrive);
        if( KErrNone == err )
        {
            info.bVolInfoValid = true;
        
            TDriveInfo& drive = info.volInfo.iDrive;
            DPRINTF(SYMP_FILE, ("GetDriveInfo(): type = %d; drive_attr = %d; media_attr = %d\n",
                                drive.iType, drive.iDriveAtt, drive.iMediaAtt));
            info.type = drive.iType;
            if(drive.iDriveAtt != EMediaNotPresent)
            {
                // only in this case can we access...
                info.state = dsAccessible;
            }
            else
            {
                // this case (not normal) appears to occur when memory is low!
                DPRINTF(SYMP_FILE, ("GetDriveInfo(): drive absent\n"));
                info.state = dsUnknown;
                info.type = EMediaNotPresent; // just for sanity
            }

            if( drive.iMediaAtt & KMediaAttLocked)
            {
                // drive is reported locked when it is not when memory is low; we won't argue
                info.state = dsLocked;
            }
        }
        else
        {
            DPRINTF(SYMP_FILE, ("GetDriveInfo(): Volume() failed\n"));

            //
            // Volume() doesn't fail with KErrLocked as you might expect (when drive is in fact locked)! Do explicit check.
            //
            if( IsMountLocked(idxDrive) )
            {
                info.state = dsLocked;
            }
            else
            {
                
                info.state = TranslateDriveErrorCode(err);
            }
        }
    }

    return info;
}



////////////////////////////////////////////////////////////
// allocate a TFileName with assembled folder and name:
//
//  first        - folder suffix '/' is optional; KNullDesC is OK
//  second       - folder prefix '/' is optional; KNullDesC is OK
//  type         - if ntFolder, ensure trailing folder suffix '/'
//               - if ntFile, ensure no trailing folder suffix
//               - if ntUnspecified, append second as is
//
// examples (before possibly adding or removing trailing folder suffix based on type):          
//
// "path"   + "\file"   -> "path\file"
// "\path"  + "file'    -> "\path\file"
// ""       + "file"    -> "\file"
// "c:\path"   + ""     -> "c:\path"
// "path"   + "\file\"  -> "path\file\"
//
//
TFileName* AllocFileNameL(const TDesC& first, const TDesC& second, NameType type)
{
    TFileName* pName = new (ELeave) TFileName;
    AUTO_PUSH_POP(pName);
    pName->Copy(first);
    AppendPath(*pName, second, type);
    return pName;
}

TFileName* AllocFileNameL(const TDesC& path, NameType type )
{
    return AllocFileNameL(path, KNullDesC, type);
}


HBufC* AllocFileUrlL(const TDesC& path)
{
    // get path with backslashes converted to forward slashes
    HBufC* pbuff = CHXAvStringUtils::AllocTextL(path);
    AUTO_PUSH_POP_DEL(pbuff);

    TPtr ptr = pbuff->Des();
    BackToForwardSlash(ptr);

    // in case path has special characters that need to be escaped (e.g., '#' or '%')
    CHXAvEscapedString escPath;
    escPath.EscapePathStr(CHXAvStringUtils::DescToString(*pbuff));
    CHXString strEscaped = escPath.GetEscapedStr();
    HBufC* pEscaped = CHXAvStringUtils::StringToHBuf(strEscaped);
    AUTO_PUSH_POP_DEL(pEscaped);

    // concatenate file:// prefix
    HBufC* pURL = CHXAvStringUtils::AllocTextL(KFileProtocolPrefix, *pEscaped);
    
    return pURL;
}

////////////////////////////////////////////////////////////
//
// append path element to path, ensuring that optional path 
// separators make sense
//
//    path              - folder suffix ('/') at end  is optional
//    tail              - path prefix ('/') at beggining is optional; will be added if missing
//
//    type              - if 'folder' ensures trailing '/' exists on end of path
//                      - if 'file' ensures trailing '/' does not exist on end of path
//                      - if 'unspecified', just appends tail as is
void AppendPath(TDes& path, const TDesC& name, NameType type)
{
    // XXXLCM check total size doesn't overflow KMaxFileName (AppendPathL, or copy to max)

    if( name.Length() > 0 )
    {
        // make sure existing path has trailing folder suffix
        EnsureFolderSuffix(path);

        TPtrC ptrName;

        TInt idxBegin = 0;
        TInt idxEnd = name.Length();

        if( (ntFile == type) && HasFolderSuffix(name) )
        {
            // don't include trailing slash - we are forming a filename
            idxEnd--;
        }

        if(HasFolderPrefix(name))
        {
            // don't append the first path sep
            idxBegin++;
        }
            
        ptrName.Set(name.Mid(idxBegin, idxEnd - idxBegin));

        path.Append(ptrName);
    }

    if( ntFolder == type )
    {
        EnsureFolderSuffix(path);
    }
}




////////////////////////////////////////////////////////////
//
// return path with filename part lopped off
//
// "\foo\bar"  -> \foo\          <-- bar is interpreted as file
// "\foo\bar\" -> \foo\bar\
// "\foo\"     -> \foo\
// "\file.rm"  -> \
// "foo"       -> KNullDesc
// ""          -> KNullDesc
//
TPtrC GetFolderPath(const TDesC& path)
{
    TInt idx = path.Length();
    if( idx > 0 )
    {
	// find current folder root
	idx = path.LocateReverse(KPathDelimiter);
	if( KErrNotFound != idx )
	{
	    // include trailing '\'
	    return path.Left(idx + 1);
	}
    }
    return TPtrC(KNullDesC);
}

////////////////////////////////////////////////////////////
//
// return path to folder that is parent of current
// folder
//
// "\foo\bar"  -> \foo\       <-- bar is interpreted as file
// "\foo\bar\" -> \foo\
// "\foo\"     -> \
// "\"         -> KNullDesc
// "foo"       -> KNullDesc
// ""          -> KNullDesc
//
TPtrC GetParentFolder(const TDesC& path)
{
    TPtrC parent(KNullDesC);

    // find current folder root
    TInt idx = path.LocateReverse(KPathDelimiter);
    if( idx > 0 )
    {
        if( HasFolderSuffix(path) )
        {
            // path name is a folder; skip the folder suffix and get parent folder
	    TPtrC current = path.Left(idx);
	    idx = current.LocateReverse(KPathDelimiter);
        }

        if( idx > 0 )
        {
            parent.Set(path.Left(idx + 1));
        }
    }
    
    return parent;	
}

////////////////////////////////////
// return true if 'childPath' specifies a path that
// is under the parentPath
//
// c:\myfolder\music\      c:\myfolder\music\rock\      true
// c:\myfolder\music\      c:\myfolder\music\styx.rm    true
// \myfolder\music\        \myfolder\music\classical    true
// c:\myfolder\music\      \myfolder\music\rock\        false (ambiguous)
// c:\myfolder\music\      c:\myfolder\music\           false (same path)
// {empty path}            {whatever}                   false (an invalid path can't have children)
//
bool IsSubPath(const TDesC& parentPath, const TDesC& childPath)
{
    bool bIsSubPath = false;
    TInt parentLength = parentPath.Length();

    // empty parent path means no path (can't have child)
    if( parentLength > 0 )
    {
        // a child path must be longer than the parent path
        if(childPath.Length() > parentPath.Length())
        {
	    // get possible matching base path from the parent
	    TPtrC childBasePath = childPath.Left(parentLength);

	    bIsSubPath = (0 == childBasePath.CompareF(parentPath));
        }
    }
    return bIsSubPath;
}

////////////////////////////////////
//
// get name-only part of most-significant part of path
//
// "\foo\bar\file.rm" -> "file.rm"
// "\foo\bar\"        -> "bar"
// "\foo\bar"         -> "bar"
// "\foo\bar\ "       -> " "
// "bar\"             -> "bar"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?