filespecutils_carbon.cpp

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

CPP
1,621
字号

HX_RESULT CHXFileSpecUtils::RemoveDir(const CHXDirSpecifier& dirSpec)
{
	FSRef 	dirRef;
	OSErr	err;
	
	require_return(dirSpec.IsSet(), HXR_INVALID_PARAMETER);
	
	dirRef = (FSRef) dirSpec;
	
	err = FSDeleteObject(&dirRef);
	
	return err;

}

// ------------------------------------------------------------------------------------
//
// RemoveFile
//
// ------------------------------------------------------------------------------------

HX_RESULT CHXFileSpecUtils::RemoveFile(const CHXFileSpecifier& fileSpec)
{
	FSRef 	fileRef;
	OSErr	err;
	
	require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER);
	
	fileRef = (FSRef) fileSpec;
	
	err = FSDeleteObject(&fileRef);
	
	return err;
}

// ------------------------------------------------------------------------------------
//
// MakeFileReadOnly/MakeFileNotReadOnly
//
// ------------------------------------------------------------------------------------

HX_RESULT CHXFileSpecUtils::MakeFileReadOnly(const CHXFileSpecifier& fileSpec)
{
	FSSpec 	fileFSSpec;
	OSErr	err;
	
	require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER);
	
	fileFSSpec = (FSSpec) fileSpec;
	
	err = FSpSetFLock(&fileFSSpec); // is there an FSRef variant for this?
	
	if (err)
	{
		err = HXR_FAIL; // poor-man's OSErr-to-HX_RESULT conversion
	}
	
	return err;
}


HX_RESULT CHXFileSpecUtils::MakeFileNotReadOnly(const CHXFileSpecifier& fileSpec)
{
	FSSpec 	fileFSSpec;
	OSErr	err;
	
	require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER);
	
	fileFSSpec = (FSSpec) fileSpec;
	
	err = FSpRstFLock(&fileFSSpec); // is there an FSRef variant for this?
	
	if (err)
	{
		err = HXR_FAIL; // poor-man's OSErr-to-HX_RESULT conversion
	}
	
	return err;
}

// ------------------------------------------------------------------------------------
//
// RenameMoveFile
//
// ------------------------------------------------------------------------------------

HX_RESULT CHXFileSpecUtils::RenameMoveFile(CHXFileSpecifier& fileSpec, const char* pNewNameIfAny, 
	const CHXDirSpecifier* pNewDirectoryIfAny)
{
	HX_RESULT		res;
	CHXDirSpecifier		fileDir, destDir;
	CHXFileSpecifier	interimFileSpec;
	CHXString		strNewName;
	FSRef			fileRef, interimRef, targetRef;
	HFSUniStr255 		newUniName;
	BOOL			bRenaming, bMoving, bRenamed, bMoved;
	
	res = HXR_FAIL;
	bRenamed = bMoved = FALSE;
	
	require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER);
	
	fileDir = fileSpec.GetParentDirectory();
	
	if (pNewDirectoryIfAny)
	{
		destDir = *pNewDirectoryIfAny;
		bMoving = (destDir != fileDir) ? TRUE : FALSE;
	}
	else
	{
		destDir = fileDir;
		bMoving = FALSE;
	}
	
	if (pNewNameIfAny)
	{
		strNewName = pNewNameIfAny;
		bRenaming = (strNewName != fileSpec.GetName()) ? TRUE : FALSE;
	}
	else
	{
		strNewName = fileSpec.GetName();
		bRenaming = FALSE;
	}
	
	// ensure there's not already something there with this name
	CHXFileSpecifier specTestDest = destDir.SpecifyChildFile(strNewName);
	require( (!CHXFileSpecUtils::FileExists(specTestDest)), Bail);
	
	// try renaming, then move, then rename if we couldn't originally
	fileRef = (FSRef) fileSpec;
	
	// rename
	interimFileSpec = fileDir.SpecifyChildFile(strNewName); // new name in old directory
	if (bRenaming && interimFileSpec.IsSet() && !CHXFileSpecUtils::FileExists(interimFileSpec))
	{
		newUniName = interimFileSpec.GetNameHFSUniStr255();
		res = FSRenameUnicode(&fileRef, newUniName.length, newUniName.unicode, 
			kTextEncodingUnknown, &interimRef);
		if (res == noErr)
		{
			bRenamed = TRUE;
			fileRef = interimRef;
		}
	}
	
	// move
	if (bMoving)
	{
		targetRef = (FSRef) destDir;
		res = FSMoveObject(&fileRef, &targetRef, &interimRef);
		if (res == noErr)
		{
			bMoved = TRUE;
			fileRef = interimRef;
		}
	}
	
	// rename -- don't try to rename if we were supposed to move & didn't
	if (bRenaming && !bRenamed && (bMoved || !bMoving))
	{
		interimFileSpec = destDir.SpecifyChildFile(strNewName); // new name in new directory
		
		newUniName = interimFileSpec.GetNameHFSUniStr255();
		res = FSRenameUnicode(&fileRef, newUniName.length, newUniName.unicode, 
			kTextEncodingUnknown, &interimRef);
		if (res == noErr)
		{
			bRenamed = TRUE;
			fileRef = interimRef;
		}
	}
	
	if ((bRenamed || !bRenaming) && (bMoved || !bMoving))
	{
		fileSpec = fileRef;
		res = HXR_OK;
	}
	else
	{
		res = HXR_FAIL;
	}
Bail:
	return res;
}

// ------------------------------------------------------------------------------------
//
// read/write files
//
// ------------------------------------------------------------------------------------

static HX_RESULT WriteFileInternal(CHXFileSpecifier& fileSpec, const void *pBuff, UInt32 length, BOOL bReplaceExistingFile);
static HX_RESULT ReadFileInternal(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer);

HX_RESULT CHXFileSpecUtils::WriteBinaryFile(CHXFileSpecifier& fileSpec, IHXBuffer* inBuffer, BOOL bReplaceExistingFile)
{
	return WriteFileInternal(fileSpec, (void *) inBuffer->GetBuffer(), inBuffer->GetSize(), bReplaceExistingFile);
}

HX_RESULT CHXFileSpecUtils::WriteTextFile(CHXFileSpecifier& fileSpec, const CHXString& inStr, BOOL bReplaceExistingFile)
{
	return WriteFileInternal(fileSpec, (const char *) inStr, inStr.GetLength(), bReplaceExistingFile);
}

HX_RESULT WriteFileInternal(CHXFileSpecifier& fileSpec, const void *pBuff, UInt32 length, BOOL bReplaceExistingFile)
{
	check_nonnull(pBuff);
	
	require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER);
	
	long * kDontWantNodeID = NULL;
	FSCatalogInfo * kDontSetCatInfo = NULL;
	FSSpec * kDontWantFileFSSpec = NULL;
	
	CHXDirSpecifier parentDirSpec;
	
	Boolean targetIsDir;
	Boolean targetAlreadyExists;
	HFSUniStr255 uniName, dataForkName;
	FSRef fileFSRef;
	SInt16 forkRefNum;
	OSErr err;
	
	// if an item is there already, bail if we're in dont replace mode
	// or if the item is a directory
	fileFSRef = (FSRef) fileSpec;
	
	targetAlreadyExists = (FSGetNodeID(&fileFSRef, kDontWantNodeID, &targetIsDir) == noErr);
	
	// before we delete an old file, save the parent and filename info so we can create the new one
	// (since the FSRef for the file in the old file spec becomes invalid once we delete the file)
	parentDirSpec = fileSpec.GetParentDirectory();
	uniName = fileSpec.GetNameHFSUniStr255();


	if (targetAlreadyExists)
	{
		if (targetIsDir) return HXR_INVALID_PATH;
		
		if (!bReplaceExistingFile) return HXR_FILE_EXISTS;
		
		if (bReplaceExistingFile) 
		{
			err = FSDeleteObject(&fileFSRef);
		}
	} 

	// create, open, write into the file, and close it
	err = FSCreateFileUnicode((FSRef *) parentDirSpec, uniName.length, uniName.unicode,
		kFSCatInfoNone, kDontSetCatInfo, &fileFSRef, kDontWantFileFSSpec);
	if (err == noErr)
	{
		dataForkName.length = 0;
		err = FSGetDataForkName(&dataForkName);
		check_noerr(err);
		
		err = FSOpenFork(&fileFSRef, dataForkName.length, dataForkName.unicode,
			fsWrPerm, &forkRefNum);
		if (err == noErr)
		{
			long ioBytes = length;
			
			err = FSWrite(forkRefNum, &ioBytes, pBuff);
			check_noerr(err);
			
			FSCloseFork(forkRefNum);
		}
		
		if (err == noErr)
		{
			// update the file spec to point to the new file
			fileSpec = fileFSRef;
		}
		else
		{
			// we failed to write it; delete it
			(void) FSDeleteObject(&fileFSRef);
		}
	}
	
	return (err == noErr ? HXR_OK : HXR_FAIL);
}


HX_RESULT CHXFileSpecUtils::ReadBinaryFile(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer)
{
	return ReadFileInternal(fileSpec, pOutBuffer);
}

HX_RESULT CHXFileSpecUtils::ReadTextFile(const CHXFileSpecifier& fileSpec, CHXString& outStr)
{
	HX_RESULT res;
	IHXBuffer *pBuff = NULL;
	
	res = ReadFileInternal(fileSpec, pBuff);
	
	if (SUCCEEDED(res))
	{
		outStr = CHXString((const char *) pBuff->GetBuffer(), (int) pBuff->GetSize());
		
		HX_RELEASE(pBuff);
	}
	
	return res;
}

HX_RESULT ReadFileInternal(const CHXFileSpecifier& fileSpec, IHXBuffer*& pOutBuffer)
{
	require_return(fileSpec.IsSet(), HXR_INVALID_PARAMETER);

	HFSUniStr255 dataForkName;
	FSRef fileFSRef;
	SInt16 forkRefNum = -1;
	SInt64 forkSize;
	OSStatus err;
	
	pOutBuffer = new CHXBuffer();
	require_nonnull_action(pOutBuffer, Bail, err = HXR_OUTOFMEMORY);
	pOutBuffer->AddRef();
	
	dataForkName.length = 0;
	err = FSGetDataForkName(&dataForkName);
	require_noerr(err, Bail);
	
	fileFSRef = (FSRef) fileSpec;
	
	err = FSOpenFork(&fileFSRef, dataForkName.length, dataForkName.unicode,
		fsRdPerm, &forkRefNum);
	require_noerr_quiet(err, Bail);
		
	err = FSGetForkSize(forkRefNum, &forkSize);
	require_noerr(err, Bail);
	
	require_action(forkSize <= 0x07FFFFFFF, Bail, err = HXR_INVALID_PATH); // file is too big for a 32-bit signed length
	
	err = pOutBuffer->SetSize((UInt32) forkSize);
	require_noerr(err, Bail);
	
	{
            long ioBytes = forkSize;
            
            err = FSRead(forkRefNum, &ioBytes, pOutBuffer->GetBuffer());
            require_noerr(err, Bail);
                    
            (void) FSCloseFork(forkRefNum);
            
            return HXR_OK;
        }
	
Bail:
	HX_RELEASE(pOutBuffer);
	if (forkRefNum != -1) (void) FSCloseFork(forkRefNum);
	
	return HXR_FAIL;
}

// ------------------------------------------------------------------------------------
//
// GetFileType
//
// ------------------------------------------------------------------------------------

FOURCC CHXFileSpecUtils::GetFileType(const CHXFileSpecifier& fileSpec)
{
	FOURCC fileType;
	OSErr err;
	
	require_return(fileSpec.IsSet(), 0);
	
	fileType = 0;
	
	FSRef		fileRef;
	FinderInfo	fndrInfo;
	Boolean		isDir;
	
	ExtendedFinderInfo * kDontWantExtendedInfo = NULL;
	
	fileRef = (FSRef) fileSpec;
	
	err = FSGetFinderInfo(&fileRef, &fndrInfo, kDontWantExtendedInfo, &isDir);
	
	if ((err == noErr) && !isDir)
	{
		fileType = fndrInfo.file.fileType;
	}
	
	return fileType;
}

// ------------------------------------------------------------------------------------
//
// MakeNameLegal
//
// returns TRUE if the name was changed
//
// ------------------------------------------------------------------------------------

BOOL CHXFileSpecUtils::MakeNameLegal(char *pszName)
{
	const char *badChars = ":";
	const char replacementChar = '-';
	const long maxNameLength = 255;

	long len, idx;
	BOOL bChanged;
	
	require_nonnull_return(pszName, FALSE);
	
	bChanged = FALSE;
	
	len = strlen(pszName);
	
	// replace any illegal characters
	for (idx = 0; idx < len; idx++)
	{
		if (strchr(badChars, pszName[idx]))
		{
			pszName[idx] = replacementChar;
			bChanged = TRUE;
		}
	}
	
	// be sure the name isn't too long
	if (len > maxNameLength)
	{
		pszName[maxNameLength] = 0;
		bChanged = TRUE;
	}
	
	return bChanged;
}


// ------------------------------------------------------------------------------------
//
// FindFolder
//
// ------------------------------------------------------------------------------------

CHXDirSpecifier CHXFileSpecUtils::MacFindFolder(short vRefNum, FolderType foldType)
{
	CHXDirSpecifier			foundDirSpec;
	OSErr				err;
	FSRef				folderRef;
	
	err = ::FSFindFolder(vRefNum, foldType, kCreateFolder, &folderRef);
	if (err == noErr)
	{
		foundDirSpec = folderRef;
	}
	
	return foundDirSpec;
}

CHXFileSpecifier CHXFileSpecUtils::SpecifyFileWithMacFindFolder(short vRefNum, FolderType foldType, const char *pszChildFile)
{
	CHXDirSpecifier parentDir;
	CHXFileSpecifier targetFile;
	
	parentDir = CHXFileSpecUtils::MacFindFolder(vRefNum, foldType);
	check(parentDir.IsSet());
	
	if (CHXFileSpecUtils::DirectoryExists(parentDir))
	{
		targetFile = parentDir.SpecifyChildFile(pszChildFile);
	}
	
	return targetFile;
}

CHXDirSpecifier CHXFileSpecUtils::SpecifyFolderWithMacFindFolder(short vRefNum, FolderType foldType, const char *pszChildFolder)
{
	CHXDirSpecifier parentDir;
	CHXDirSpecifier targetDir;
	
	parentDir = CHXFileSpecUtils::MacFindFolder(vRefNum, foldType);
	check(parentDir.IsSet());
	
	if (CHXFileSpecUtils::DirectoryExists(parentDir))
	{
		targetDir = parentDir.SpecifyChildDirectory(pszChildFolder);
	}
	
	return targetDir;
}

// ------------------------------------------------------------------------------------
//
// ResolveFileSpecifierAlias
// ResolveDirSpecifierAlias
//
// These resolve a file spec to an alias file in place
//
// ------------------------------------------------------------------------------------

HX_RESULT CHXFileSpecUtils::ResolveFileSpecifierAlias(CHXFileSpecifier& fileSpec)
{
	HX_RESULT res;
	
	res = HXR_FAIL;
	
	// GR 7/8/02
	// check that the file exists before resolving it in hopes of avoiding
	// a mysterious crash on 10.1.5
	if (CHXFileSpecUtils::FileExists(fileSpec))
	{
		FSRef	fileRef;
		OSErr	err;
		Boolean bIsFolder;
		Boolean bWasAliased;
		
		const Boolean kShouldResolveChains = true;
		
		fileRef = (FSRef) fileSpec;
		
		err = FSResolveAliasFileWithMountFlags(&fileRef, kShouldResolveChains,
			&bIsFolder, &bWasAliased, kResolveAliasFileNoUI);
		
		if ((err == noErr) && !bIsFolder)
		{
			res = HXR_OK;
			
			if (bWasAliased)
			{
				fileSpec = fileRef;
			}
		}
		else
		{
			// error occurred
		}
	}
	
	return res;

}

HX_RESULT CHXFileSpecUtils::ResolveDirSpecifierAlias(CHXDirSpecifier& dirSpec)

⌨️ 快捷键说明

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