filespecutils_carbon.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,621 行 · 第 1/3 页

CPP
1,621
字号
{
	HX_RESULT res;
	
	res = HXR_FAIL;
	
	if (dirSpec.IsSet())
	{
		FSRef	dirRef;
		OSErr	err;
		Boolean bIsFolder;
		Boolean bWasAliased;
		
		const Boolean kShouldResolveChains = true;
		
		dirRef = dirSpec;
		
		err = FSResolveAliasFileWithMountFlags(&dirRef, kShouldResolveChains,
			&bIsFolder, &bWasAliased, kResolveAliasFileNoUI);
		
		if ((err == noErr) && bIsFolder)
		{
			res = HXR_OK;
			
			if (bWasAliased)
			{
				dirSpec = dirRef;
			}
		}
		else
		{
			// error occurred
		}
	}
	
	return res;

}

// ------------------------------------------------------------------------------------
//
// MoveFileToTrash
// MoveFolderToTrash
// MoveFileToFolderWithRenaming
// MoveFolderToFolderWithRenaming
//
// ------------------------------------------------------------------------------------

static HX_RESULT MoveToFolderWithRenamingInternal(const FSRef* itemRef, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove, FSRef& outNewItemRef);

HX_RESULT CHXFileSpecUtils::MoveFileToTrash(const CHXFileSpecifier& fileSpec) 
{
	if (!CHXFileSpecUtils::FileExists(fileSpec)) return HXR_INVALID_PARAMETER;

	CHXDirSpecifier trashSpec;
	FSRef itemRef, newItemRef;
	
	const BOOL bDeleteIfCantMove = TRUE;

	itemRef = (FSRef) fileSpec;
	
	trashSpec = CHXFileSpecUtils::MacFindFolder(fileSpec.GetVRefNum(), kTrashFolderType);
	
	return MoveToFolderWithRenamingInternal(&itemRef, trashSpec, bDeleteIfCantMove, newItemRef);
}

HX_RESULT CHXFileSpecUtils::MoveFolderToTrash(const CHXDirSpecifier& dirSpec) 
{
	if (!CHXFileSpecUtils::DirectoryExists(dirSpec)) return HXR_INVALID_PARAMETER;

	CHXDirSpecifier trashSpec;
	FSRef itemRef, newItemRef;
	
	const BOOL bDeleteIfCantMove = TRUE;
	
	itemRef = (FSRef) dirSpec;
	
	trashSpec = CHXFileSpecUtils::MacFindFolder(dirSpec.GetVRefNum(), kTrashFolderType);
	
	return MoveToFolderWithRenamingInternal(&itemRef, trashSpec, bDeleteIfCantMove, newItemRef);
}

HX_RESULT CHXFileSpecUtils::MoveFileToCleanupAtStartup(const CHXFileSpecifier& fileSpec, BOOL bDeleteIfCantMove) 
{
	CHXFileSpecifier nonConstFileSpec(fileSpec);
	
	return MoveFileToCleanupAtStartup(nonConstFileSpec, bDeleteIfCantMove);
}

HX_RESULT CHXFileSpecUtils::MoveFileToCleanupAtStartup(CHXFileSpecifier& fileSpec, BOOL bDeleteIfCantMove) 
{
	if (!CHXFileSpecUtils::FileExists(fileSpec)) return HXR_INVALID_PARAMETER;

	CHXDirSpecifier cleanupSpec;
	FSRef itemRef, newItemRef;
	HX_RESULT res;
	
	itemRef = (FSRef) fileSpec;
	
	cleanupSpec = CHXFileSpecUtils::MacFindFolder(fileSpec.GetVRefNum(), kChewableItemsFolderType);
	
	res = MoveToFolderWithRenamingInternal(&itemRef, cleanupSpec, bDeleteIfCantMove, newItemRef);
	if (SUCCEEDED(res))
	{
		fileSpec = newItemRef;
	}
	
	return res;
}

HX_RESULT CHXFileSpecUtils::MoveFolderToCleanupAtStartup(const CHXDirSpecifier& dirSpec, BOOL bDeleteIfCantMove) 
{
	CHXDirSpecifier nonConstDirSpec(dirSpec);
	
	return MoveFolderToCleanupAtStartup(nonConstDirSpec, bDeleteIfCantMove);
}

HX_RESULT CHXFileSpecUtils::MoveFolderToCleanupAtStartup(CHXDirSpecifier& dirSpec, BOOL bDeleteIfCantMove) 
{
	if (!CHXFileSpecUtils::DirectoryExists(dirSpec)) return HXR_INVALID_PARAMETER;

	CHXDirSpecifier cleanupSpec;
	FSRef itemRef, newItemRef;
	HX_RESULT res;
	
	itemRef = (FSRef) dirSpec;
	
	cleanupSpec = CHXFileSpecUtils::MacFindFolder(dirSpec.GetVRefNum(), kChewableItemsFolderType);
	
	res = MoveToFolderWithRenamingInternal(&itemRef, cleanupSpec, bDeleteIfCantMove, newItemRef);
	
	if (SUCCEEDED(res))
	{
		dirSpec = newItemRef;
	}
	return res;
}


HX_RESULT CHXFileSpecUtils::MoveFileToFolderWithRenaming(CHXFileSpecifier& fileSpec, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove) 
{
	if (!CHXFileSpecUtils::FileExists(fileSpec)) return HXR_INVALID_PARAMETER;
	if (!CHXFileSpecUtils::DirectoryExists(targetSpec)) return HXR_INVALID_PARAMETER;

	FSRef itemRef, newItemRef;
	HX_RESULT res;
	
	itemRef = (FSRef) fileSpec;
	
	res = MoveToFolderWithRenamingInternal(&itemRef, targetSpec, bDeleteIfCantMove, newItemRef);

	if (SUCCEEDED(res))
	{
		fileSpec = newItemRef;
	}
	return res;
}

HX_RESULT CHXFileSpecUtils::MoveFolderToFolderWithRenaming(CHXDirSpecifier& dirSpec, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove) 
{
	if (!CHXFileSpecUtils::DirectoryExists(dirSpec)) return HXR_INVALID_PARAMETER;
	if (!CHXFileSpecUtils::DirectoryExists(targetSpec)) return HXR_INVALID_PARAMETER;

	FSRef itemRef, newItemRef;
	HX_RESULT res;
	
	itemRef = (FSRef) dirSpec;
	
	res = MoveToFolderWithRenamingInternal(&itemRef, targetSpec, bDeleteIfCantMove, newItemRef);
	if (SUCCEEDED(res))
	{
		dirSpec = newItemRef;
	}
	return res;
}

static HX_RESULT MoveToFolderWithRenamingInternal(const FSRef* itemRef, const CHXDirSpecifier& targetSpec, BOOL bDeleteIfCantMove, FSRef& outNewItemRef) 
{	
	check_nonnull(itemRef);
	
	HX_RESULT	pnres;

	OSErr err;
	
	pnres = HXR_FAILED;
	
	ZeroInit(&outNewItemRef);
	
	if (!targetSpec.IsSet())
	{
		// targetSpec wasn't set, nowhere to move to
		
		if (bDeleteIfCantMove)
		{
			err = FSDeleteObject(itemRef);
			if (err == noErr)
			{
				pnres = HXR_OK;
			}
		}
	}
	else
	{
		// targetSpec is set
		//
		// try to move the file to the target
		FSRef newItemRef, targetRef, newNameRef;
		
		targetRef = (FSRef) targetSpec;
		
		err = FSMoveObject(itemRef, &targetRef, &newItemRef);
		if (err == noErr)
		{
			outNewItemRef = newItemRef;
			
			pnres = HXR_OK;
		}
		else if (err != dupFNErr)
		{
			// catmove failed for some unknown reason, not a name conflict
			if (bDeleteIfCantMove)
			{
				err = FSDeleteObject(itemRef);
				if (err == noErr)
				{
					pnres = HXR_OK;
				}
			}
		}
		else
		{
			// there's a name conflict; find a unique name for the file we're moving in the
			// target folder, rename it, and then move it again
			
			CHXString strName, strTemplate;
			CHXFileSpecifier specNewNamedFile;
			HFSUniStr255 uniName, newUniName;
			INT32 periodOffset;
			const char* const kWildcard = "%-%-%";
			
			err = FSGetFileDirName(itemRef, &uniName);
			
			strName.SetFromHFSUniStr255(uniName, CFStringGetSystemEncoding()); // make a template like "filename_%-%-%"
			
			periodOffset = strName.ReverseFind('.');
			if (periodOffset != -1)
			{
				// put the _2 or whatever just before the extension
				strTemplate = strName.Left(periodOffset);
				strTemplate += "_";
				strTemplate += kWildcard;
				strTemplate += strName.Mid(periodOffset);
			}
			else
			{
				// put the _2 or whatever after the filename
				strTemplate = strName + "_";
				strTemplate += kWildcard;
			}
			
			specNewNamedFile = CHXFileSpecUtils::GetUniqueFileSpec(targetSpec, strName, strTemplate, kWildcard);
			
			newUniName = specNewNamedFile.GetNameHFSUniStr255();
			
			err = FSRenameUnicode(itemRef, newUniName.length, newUniName.unicode, kTextEncodingUnknown, &newNameRef);
			if (err == noErr)
			{
				err = FSMoveObject(&newNameRef, &targetRef, &newItemRef);
				
				if (err == noErr)
				{
					outNewItemRef = newItemRef;
					
					pnres = HXR_OK;
				}
				else if (err != noErr && bDeleteIfCantMove)
				{
					// couldn't move it; delete the renamed file
					err = FSDeleteObject(&newNameRef);
					if (err == noErr)
					{
						pnres = HXR_OK;
					}
				}
				else
				{
					// couldn't move it; change the name back
					
					err = FSRenameUnicode(&newNameRef, uniName.length, uniName.unicode, 
						kTextEncodingUnknown, &newNameRef);
				}
			}
			else
			{
				// rename failed for some reason
				if (bDeleteIfCantMove)
				{
					// couldn't move it; delete the renamed file
					err = FSDeleteObject(itemRef);
					if (err == noErr)
					{
						pnres = HXR_OK;
					}
				}
			}			
		} 
	}

	return pnres;
}

// ------------------------------------------------------------------------------------
//
// GetSystemTempDirectory
//
// ------------------------------------------------------------------------------------

CHXDirSpecifier CHXFileSpecUtils::GetSystemTempDirectory()
{
	return CHXFileSpecUtils::MacFindFolder(kOnAppropriateDisk, kChewableItemsFolderType);
}

// ------------------------------------------------------------------------------------
//
// GetUniqueFileSpec
// GetUniqueTempFileSpec
//
// ------------------------------------------------------------------------------------

static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, 
									const char *pszNameFirst, const char *pszTemplate, 
									const char *pszWildcard, UINT32 nStartNum);
									
const UINT32 kNumWrapValue = 9999+1;	// limit insertions to 4-digit numbers
	
CHXFileSpecifier CHXFileSpecUtils::GetUniqueFileSpec(const CHXDirSpecifier& locationSpec, 
									const char *pszNameFirst, const char *pszTemplate, 
									const char *pszWildcard)
{
	return GetUniqueFileSpecInternal(locationSpec, pszNameFirst, pszTemplate, pszWildcard, 0);
}

CHXFileSpecifier CHXFileSpecUtils::GetUniqueTempFileSpec(const CHXDirSpecifier& locationSpec, 
									const char *pszTemplate, const char *pszWildcard)
{
	CMultiplePrimeRandom 	rand(HX_GET_TICKCOUNT());
	
	UINT32 num;
	
	num = rand.GetRandomNumber();
	
	num %= kNumWrapValue;
	
	// skip 0, which means "don't substitute for the wildcard", and 1
	if (num == 0 || num == 1) num = 2;

	return GetUniqueFileSpecInternal(locationSpec, NULL, pszTemplate, pszWildcard, num);
}


static CHXFileSpecifier GetUniqueFileSpecInternal(const CHXDirSpecifier& locationSpec, 
									const char *pszNameFirst, const char *pszTemplate, 
									const char *pszWildcard, UINT32 nStartNum)
{
	CHXFileSpecifier 		resultFileSpec;
	
	require_return(locationSpec.IsSet(), resultFileSpec);
	require_return(pszTemplate != NULL && pszWildcard != NULL, resultFileSpec);
	require_return(pszNameFirst != NULL || nStartNum != 0, resultFileSpec);
	
	CHXFileSpecifier 	testFileSpec;
	CHXDirSpecifier 	testDirSpec;
	CHXString			strNumber;
	CHXString			strName;
	UINT32				nCurrentNum;
	
	nCurrentNum = nStartNum;

	while (1) 
	{
		// if the number is non-zero, make a string from the template;
		// if the number is zero, user the initial name string
		if (nCurrentNum == 0)
		{
			// replace the wildcard in the template with the number string
			strName = pszNameFirst;
		}
		else
		{
			// replace the wildcard in the template with the number string
			strNumber.Empty();
			strNumber.AppendULONG(nCurrentNum);

			strName = pszTemplate;
			strName.FindAndReplace(pszWildcard, strNumber);	// replace first wildcard with number string
		}
		
		
		// test if a file or directory exists with that name
		testFileSpec = locationSpec.SpecifyChildFile(strName);
		testDirSpec = locationSpec.SpecifyChildDirectory(strName);
		if (CHXFileSpecUtils::FileExists(testFileSpec)
			|| CHXFileSpecUtils::DirectoryExists(testDirSpec))
		{
			// an item already has that name, so increment & wrap the number
			nCurrentNum++;
			nCurrentNum %= kNumWrapValue;
			
			// don't use 0 again, and skip 1 since "MyFile2.txt" logically follows "MyFile.txt"
			if (nCurrentNum == 0 || nCurrentNum == 1) 
			{
				nCurrentNum = 2; 
			}
			
			// a quick sanity check
			if (nCurrentNum == nStartNum)
			{
				check(!"GetUniqueFileSpecInternal number wrapped");
				break;
			}
		}
		else
		{
			// the name is unique
			resultFileSpec = testFileSpec;
			break;
		}
		
	} // while

	return resultFileSpec;
}

CHXDirSpecifier 
CHXFileSpecUtils::GetAppDataDir(const char* szAppName)
{	
	// we'll use a com.RealNetworks.data folder in user's prefs
	CHXDirSpecifier targetDir;
	CHXDirSpecifier prefsDir = CHXFileSpecUtils::MacFindFolder(kUserDomain, kPreferencesFolderType);
	CHXDirSpecifier dataDir = prefsDir.SpecifyChildDirectory( "com.RealNetworks.data" );
	if (!CHXFileSpecUtils::DirectoryExists(dataDir))
	{
	    CHXFileSpecUtils::CreateDir(dataDir);
	}

	if (szAppName == NULL || *szAppName == 0)
	{
	    targetDir = dataDir;
	}
	else
	{
	    targetDir = dataDir.SpecifyChildDirectory(szAppName);

	    if (!CHXFileSpecUtils::DirectoryExists(targetDir))
	    {
		CHXFileSpecUtils::CreateDir(targetDir);
	    }
	}
	HX_ASSERT(CHXFileSpecUtils::DirectoryExists(targetDir));
	
	return targetDir;
}

#ifdef _DEBUG
void CHXFileSpecUtils::TestMacFileSpecUtils()
{
	CHXString drive1Name = "Tenspot:";
	CHXString drive2Name = "Sandy:";
	CHXString driveEjectableLockedName = "Dev.CD Feb 01 TC Disk 1:";
	CHXString driveServerName = "grobbins:";
	
	CHXDirSpecifier dirServerSpec = drive2Name;

	dirServerSpec = "Dev.CD Feb 01 TC Disk 1:Tool Chest:fake";
	dirServerSpec = "Sandy:fake:";
	//dirServerSpec = "grobbins:Sites:";
	//dirServerSpec = "grobbins:Sites:fake";
	CHXDirSpecifier dirServer2Spec = driveServerName;


	CHXFileSpecifier file1Spec = "Tenspot:123456789a123456789b123456789c123456789d.png";
	CHXFileSpecifier file2Spec = "Tenspot:123456789a123456789b123456789c123456789d:LVd";
	CHXFileSpecifier fileFake1Spec = "Tenspot:123456789a123456789b123456789c123456789d:BOO";
	CHXDirSpecifier dirFake1Spec = "Tenspot:123456789a123456789b123456789c123456789d:BOO Folder";

	CHXFileSpecifier fromNameSpec = "RealPlayer.xSYM";
	CHXFileSpecifier fromPartialPath = ":RealPlayer.xSYM";
	CHXFileSpecifier fromBadName = "BOO";
	
	HX_RESULT res;
	INT64 spaceFree, spaceTotal, fileSize;
	BOOL bFlag;
	
	res = CHXFileSpecUtils::GetFreeSpaceOnDisk(drive1Name, spaceFree);
	res = CHXFileSpecUtils::GetTotalSpaceOnDisk(drive1Name, spaceTotal);
	check(spaceTotal > spaceFree);

	bFlag = CHXFileSpecUtils::IsDiskEjectable(drive1Name);
	check(!bFlag);
	bFlag = CHXFileSpecUtils::IsDiskEjectable(driveEjectableLockedName);
	check(bFlag);
	
	bFlag = CHXFileSpecUtils::IsDiskWritable(drive1Name);
	check(bFlag);
	bFlag = CHXFileSpecUtils::IsDiskWritable(driveEjectableLockedName);
	check(!bFlag);
	
	bFlag = CHXFileSpecUtils::IsDiskLocal(drive1Name);
	check(bFlag);
	//bFlag = CHXFileSpecUtils::IsDiskLocal(driveServerName);  this fails because HFS<-->FSRef fails on mounted vols
	//check(!bFlag);
	
	res = CHXFileSpecUtils::GetFileSize(file1Spec, fileSize);
	res = CHXFileSpecUtils::GetFileSize(file2Spec, fileSize);
	res = CHXFileSpecUtils::GetFileSize(fileFake1Spec, fileSize);
	
	res = CHXFileSpecUtils::FileExists(file1Spec);
	res = CHXFileSpecUtils::FileExists(file2Spec);
	res = CHXFileSpecUtils::FileExists(fileFake1Spec);
	
	bFlag = CHXFileSpecUtils::DirectoryExists(dirFake1Spec);
	check(!bFlag);
	res = CHXFileSpecUtils::CreateDir(dirFake1Spec);
	bFlag = CHXFileSpecUtils::DirectoryExists(dirFake1Spec);
	check(bFlag);
	res = CHXFileSpecUtils::RemoveDir(dirFake1Spec);
	bFlag = CHXFileSpecUtils::DirectoryExists(dirFake1Spec);
	check(!bFlag);
	
	CHXDirSpecifier ffDir = CHXFileSpecUtils::SpecifyFolderWithMacFindFolder(file1Spec.GetVRefNum(), kPreferencesFolderType, "Real Folder");
	res = CHXFileSpecUtils::CreateDir(ffDir);
	bFlag = CHXFileSpecUtils::DirectoryExists(ffDir);
	check(bFlag);
	res = CHXFileSpecUtils::MoveFolderToCleanupAtStartup(ffDir);
	bFlag = CHXFileSpecUtils::DirectoryExists(ffDir);
	check(!bFlag);
	
}
#endif

⌨️ 快捷键说明

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