chxavfileutil.cpp

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

CPP
1,149
字号
/*****************************************************************************
 * chxavfileutil.h
 * ---------------
 *
 * Synopsis:
 * File utility namespace.  Misc stuff for helping to work with filenames and
 * paths.
 *
 * Target:
 * Symbian OS
 *
 *
 * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
 *
 *****************************************************************************/

// Symbian includes...
#include <eikfutil.h>
#include <f32file.h>
#include <apgcli.h>
#include <apmrec.h>
#include <sysutil.h>
#include <eikappui.h>
#include <eikapp.h>

// Helix includes...
#include "hxtypes.h"
#include "hxassert.h"
#include "hxcom.h"
#include "hxprefs.h" //IHXPreferences


// Include from this project...
#include "chxavutil.h"
#include "chxavfileutil.h"
#include "chxavcleanstring.h"
#include "chxavutil.h"
#include "chxavescapedstring.h"
#include "chxavdirectoryreader.h"
#include "chxavcleanupstack.h"
#include "hxsym_debug.h"
#include "hxapihelp.h"
#include "hxsym_leaveutil.h"
#include "hxsym_filetype.h"
#include "hxsym_mimetypes.h"


namespace CHXAvFile
{


// explictly instanciate GetFolderChildCount template here
template
TInt GetFolderChildCount(const TDesC& folderPath, 
				 TInt& countOut, bool bWantFolders,
                                 PFNNanoPlayerFilterType isWantedFile);


////////////////////////////////////////////////////
// get number of folders and files immediately within the
// given directory (not recursive)
//
template <typename FileFilter>
TInt GetFolderChildCount(const TDesC& folderPath, 
				 TInt& countOut, bool bWantFolders,
                                 FileFilter isWantedFile)
{
    RFs& fs = CCoeEnv::Static()->FsSession();
    CHXAvDirectoryReader reader(fs);

    TInt error = KErrNone;
    countOut = -1;

    reader.SetSortFlags(ESortNone); // be as fast as possible; don't need sorting here
    if( reader.SetToPath(folderPath) )
    {
	countOut = 0;
	const CDir* pFiles = reader.GetFiles();
	if(pFiles)
	{
            // only count files that are of interest and not hidden
            TInt count = pFiles->Count();
            for(TInt idx = 0; idx < count; ++idx)
            {
                TEntry entry = (*pFiles)[idx];
                if( !CHXAvUtil::ShouldHideFromUser(entry) && isWantedFile(folderPath, entry.iName) )
                {
                    ++countOut;
                }
            }
            pFiles = 0;
	}
	if( bWantFolders )
	{
	    const CDir* pFolders = reader.GetDirs();
	    if(pFolders)
	    {
                // add non-hidden directories to total
                TInt count = pFolders->Count();
                for(TInt idx = 0; idx < count; ++idx)
                {
                    TEntry entry = (*pFolders)[idx];
                    if( !CHXAvUtil::ShouldHideFromUser(entry) )
                    {
                        countOut += 1;
                    }
                }
	
	    }
	}
    }
    else
    {
	error = reader.GetLastError();
    }
    return error;

}

bool IsNanoPlayerFileType(const TDesC& fullPath)
{
    FileType fileType = GetFileType(fullPath);
    return IsNanoPlayerFileType(fileType);
}

bool IsNanoPlayerFileType(const TDesC& folderPath, const TDesC& itemName)
{
    TFileName* fullPath = AllocFileNameL(folderPath, itemName);
    AUTO_PUSH_POP_DEL(fullPath);
    FileType fileType = GetFileType(*fullPath);
    return IsNanoPlayerFileType(fileType);
}



////////////////////////////////
// get fully qualified absolute path (with drive letter prefix), ensuring that it
// exists
//
// searches all available drives: first session drive (normally 'c:\'), then y to a, then z
//
// if a drive letter is supplied, only that drive will be searched; other
// drives are not searched
//
// Parameters:
//
// path     - absolute (with drive) or relative (to unspecified drive) path;
//            must have folder suffix if a folder is wanted
// fullPath - fully qualified absolute and verified path (with drive letter prefix) 
//            if return is KErrNone
//
// bAllowWildCard - returns first match if true (even if multiple matches!)
//
TInt GetFullPath(RFs& fs, const TDesC& path, TDes& fullPath, bool bAllowWildCard)
{
    DPRINTF(SYMP_FILE, ("CHXAvFile::GetFullPath(): looking for '%s'\n", dbg::CharPtr(path)()));

    TInt err = KErrNotFound;
    fullPath = KNullDesC;
    
    TInt idxDrive = GetDriveIndex(path);
    if( (-1 != idxDrive) && path.Length() <= 3 )
    {
        //
        // special case: confirming that drive root path (e.g. 'e:\') exists
        // 
        // TFileFind fails if we specify root path 
        //
        if(PathExists(path))
        {
            fullPath = path;
            err = KErrNone;
        }
    }
    else
    {
        TFindFile find(fs);
    
        CDir* pDir = 0;
        if(bAllowWildCard)
        {
            // search for first match
            err = find. FindWildByDir(path, KNullDesC, pDir);
        }
        else
        {
            err = find.FindByDir(path, KNullDesC);
        }

        if (err == KErrNone)
        {
            if(pDir)
            {
                fullPath = GetFolderPath(find.File());
                if( pDir->Count() > 0 )
                {
                    // File() returns drive and path in this case; set returned path to first entry found
                    fullPath.Append( (*pDir)[0].iName );
                }
                HX_DELETE(pDir);
            }
            else
            {
                fullPath = find.File();
            }

            // if drive was specified for sought-after path, ensure found path matches
        
            if( idxDrive != -1 )
            {
                //
                // TFindFile will search for path on an alternate drive
                // if it fails to find a path on a specified drive; it treats drive letter
                // as meaning 'preferred' as opposed to 'required' (as we do)
                //

                TInt idxDriveFound = GetDriveIndex(fullPath);

                if(idxDriveFound != idxDrive)
                {
                    // path doesn't exist on drive we wanted; refuse path on alternate drive
                    fullPath = KNullDesC;
                    err = KErrNotFound;
                }
            }
        }
    }
    
    DPRINTF(SYMP_FILE, ("GetFullPath(): found '%s'\n", dbg::CharPtr(fullPath)()));

    return err;
}


////////////////////////////////////////////////////////
// alloc default name; append (N) to name until name is unique
// within the path 
//
// defaultName      - name of file or folder to begin with ('name' or 'name/')
// basePath         - full base path
//
// e.g., New Folder, New Folder(01), New Folder(02)
//
// returns 0 if: 
//    a) no unique name could be found (bad base path or roque tester); 
//    b) not enough space to fit suggested name plus prefix (base path + default name near max TFileName)
//
// XXXLCM consider using CApaApplication::GenerateFileName
//
TFileName* AllocUniqueDefaultNameL(const TDesC& basePath, 
                               const TDesC& defaultName, 
                               bool bWantFolder, 
                               const CHXAvNameDisplayTrait& nameTrait)
{
    _LIT(KDuplicateNameFormat, "%S(%02d)");
    const TUint k_cchSuffix = 4; //"(NN)"
    const TUint k_maxTries = 100;

    TFileName* pPathOut = 0;
    
    // make sure we have a qualified name (indicating folder or file)
    TFileName* pFullDefaultName = AllocFileNameL(defaultName, (bWantFolder ? CHXAvFile::ntFolder : CHXAvFile::ntFile));
    AUTO_PUSH_POP_DEL(pFullDefaultName);

    // break up qualified name for display and formatting
    NameExt nameInfo = nameTrait.GetDisplayText(*pFullDefaultName, bWantFolder);

    // max chars for 'name' in 'name.xx'
    TInt cchMaxNamePart = KMaxFileName - basePath.Length() - nameInfo.second.Length();
    if( !HasFolderSuffix(basePath) )
    {
        cchMaxNamePart -= 1; // for path sep that would be added to form full path
    }

    if ( cchMaxNamePart > 0 )
    {
        // possibly crop 'name' in 'name.xx' 
        if( nameInfo.first.Length() > cchMaxNamePart )
        {
            nameInfo.first.Set(nameInfo.first.Ptr(), cchMaxNamePart);
        }

        // working display name buffer
        HBufC* pDisplayName = HBufC::NewMaxL(nameInfo.first.Length() + k_cchSuffix);
        AUTO_PUSH_POP_DEL(pDisplayName);
        TPtr ptrDisplayName = pDisplayName->Des();
    
        // potential name to be displayed to user
        ptrDisplayName.Copy(nameInfo.first);

        // full path to go out
        pPathOut = new (ELeave) TFileName;
        AUTO_PUSH_POP(pPathOut);

        bool bFound = false;
        for(TInt idx = 0; idx < k_maxTries; ++idx)
        {
            // re-form path and see if it is unique
            pPathOut->Copy(basePath);
            AppendPath(*pPathOut, ptrDisplayName, CHXAvFile::ntUnspecified);
            pPathOut->Append(nameInfo.second);
        
            DPRINTF(SYMP_FILE, ("AllocUniqueDefaultFilenameL(): testing '%s'\n", dbg::CharPtr(*pPathOut)()));

            if(!PathExists(*pPathOut))
            {
                // found a unique name
                bFound = true;
                break;
            }

            // from now on we'll be adding suffix...

            // max chars for 'name' in 'name(NN).xx'
            TInt cchMaxNamePartMinusSuffix = cchMaxNamePart - k_cchSuffix;
            if(cchMaxNamePartMinusSuffix <= 0 )
            {
                // give up...
                break;
            }

            // possibly crop 'name' in 'name(NN)' 
            if( nameInfo.first.Length() > cchMaxNamePartMinusSuffix )
            {
                nameInfo.first.Set(nameInfo.first.Ptr(), cchMaxNamePartMinusSuffix);
            }

            // name was not unique; try next (start with 01)
            ptrDisplayName.Format(KDuplicateNameFormat, &nameInfo.first, idx + 1);
        }

        if( !bFound )
        { 
            HX_DELETE(pPathOut);
        }
    }

    return pPathOut;
}



////////////////////////////////////////////////////////////
//
// fullPath     - full path to file or folder; folders must have folder suffix
//
bool PathExists(const TDesC& fullPath)
{
    DPRINTF(SYMP_FILE, ("PathExists(): checking path '%s'\n", dbg::CharPtr(fullPath)()));

    RFs& fs = CCoeEnv::Static()->FsSession();
    
    //
    // note: BaflUtils::PathExists() is only api that appears to correctly 
    // validate a root folder, e.g., 'c:\')
    //

    if(HasFolderSuffix(fullPath))
    {
        return BaflUtils::PathExists(fs, fullPath);
    }

    return BaflUtils::FileExists(fs, fullPath);
    
}

////////////////////////////////
//
// return 0-based index of drive relative to 'a'; -1 if no drive specified
//
// (note: a valid index maps to TDriveNumer)
//
// 'c:'             -> 2
// 'a:\'            -> 0
// 'e:\foo\bar\     -> 4
// '\foo\bar'       -> -1
// 'c:hello'        -> -1
//
TInt GetDriveIndex(const TDesC& path)
{
    DPRINTF(SYMP_FILE, ("GetDriveIndex(): checking '%s'\n", dbg::CharPtr(path)()));
    TInt idx = -1;

⌨️ 快捷键说明

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