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 + -
显示快捷键?