Created
January 6, 2013 03:05
-
-
Save shanewfx/4464961 to your computer and use it in GitHub Desktop.
[C++] FileReader.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "FileReader.h" | |
#ifdef _MAC_ | |
#include <CoreServices/CoreServices.h> | |
#include <libgen.h> | |
#endif | |
#ifndef FILE_MAPPING_READER | |
#ifdef _MAC_ | |
CFileReader::CFileReader() | |
: m_hFile(-1) | |
, m_llFileSize(0) | |
{ | |
} | |
#else | |
CFileReader::CFileReader() | |
: m_hFile(NULL) | |
{ | |
m_liFileSize.QuadPart = 0; | |
} | |
#endif | |
CFileReader::~CFileReader() | |
{ | |
Close(); | |
} | |
#ifdef _MAC_ | |
OSStatus CFileReader::ConvertUTF8NameToHFSUniStr255(const char* inName, HFSUniStr255* uniStr) | |
{ | |
OSStatus err = paramErr; | |
CFStringRef tempString; | |
tempString = CFStringCreateWithCString(kCFAllocatorDefault, inName, kCFStringEncodingUTF8); | |
if (tempString) | |
{ | |
err = FSGetHFSUniStrFromString(tempString, uniStr); | |
CFRelease(tempString); | |
} | |
return err; | |
} | |
OSStatus CFileReader::OpenFileAndGetDataForkRef(const char* fileName, SInt8 permissions, SInt16* forkRefNum) | |
{ | |
char *dirPath, *baseName; | |
FSRef ref; | |
OSStatus err; | |
HFSUniStr255 uniStr; | |
FSRef newFileRef; | |
dirPath = dirname(const_cast<char*>(fileName)); | |
err = FSPathMakeRef((UInt8 *)dirPath, &ref, NULL); | |
if(err != noErr) | |
{ | |
LogText("[OpenFileAndGetDataForkRef] failed - 1\n"); | |
} | |
baseName = basename(const_cast<char*>(fileName)); | |
err = ConvertUTF8NameToHFSUniStr255(baseName, &uniStr); | |
if(err != noErr) | |
{ | |
LogText("[OpenFileAndGetDataForkRef] failed - 2\n"); | |
} | |
err = FSMakeFSRefUnicode( | |
&ref, //const FSRef * parentRef, | |
uniStr.length, //UniCharCount nameLength, | |
uniStr.unicode, //const UniChar * name, | |
kTextEncodingUnknown, //TextEncoding textEncodingHint, | |
&newFileRef); //FSRef * newRef | |
if(err != noErr) | |
{ | |
LogText("[OpenFileAndGetDataForkRef] failed - 3\n"); | |
} | |
HFSUniStr255 dataForkName; | |
FSGetDataForkName(&dataForkName); | |
err = FSOpenFork( | |
&newFileRef, //const FSRef * ref, | |
dataForkName.length, //UniCharCount forkNameLength, | |
dataForkName.unicode, //const UniChar * forkName, | |
permissions, //SInt8 permissions, | |
forkRefNum); //SInt16 * forkRefNum | |
if(err != noErr) | |
{ | |
LogText("[OpenFileAndGetDataForkRef] failed - 4\n"); | |
} | |
return err; | |
} | |
bool CFileReader::Open(const WCHAR* lpFileName) | |
{ | |
if(m_hFile != -1) | |
{ | |
FSCloseFork(m_hFile); | |
m_hFile = -1; | |
m_llFileSize = 0; | |
} | |
char szFileName[255]; | |
wcstombs(szFileName, (const wchar_t*)lpFileName, 255); | |
LogData("begin to open file: %s\n", szFileName); | |
OSStatus err = OpenFileAndGetDataForkRef(szFileName, fsRdPerm, &m_hFile); | |
if(err != noErr) | |
{ | |
LogData("![ERROR] -- open file {%s} failed\n", szFileName); | |
m_hFile = -1; | |
m_llFileSize = 0; | |
return false; | |
} | |
LogData("# open file {%s} success\n", szFileName); | |
err = FSGetForkSize(m_hFile, &m_llFileSize); | |
if(err != noErr) | |
{ | |
FSCloseFork(m_hFile); | |
m_hFile = -1; | |
m_llFileSize = 0; | |
LogText("![ERROR] -- FSGetForkSize failed\n"); | |
return false; | |
} | |
LogData("# file size: %lld\n", m_llFileSize); | |
// err = FSSetForkPosition(m_hFile, fsFromStart, 0); | |
// if(err != noErr) | |
// { | |
// FSCloseFork(m_hFile); | |
// m_hFile = -1; | |
// m_llFileSize = 0; | |
// return false; | |
// } | |
return true; | |
} | |
#else | |
bool CFileReader::Open(const WCHAR* lpFileName) | |
{ | |
if(m_hFile) | |
{ | |
CloseHandle(m_hFile); | |
m_hFile = NULL; | |
m_liFileSize.QuadPart = 0; | |
} | |
m_hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, | |
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
if(m_hFile == INVALID_HANDLE_VALUE) | |
{ | |
LogData("![ERROR] -- open file [ %S ] failed\n", lpFileName); | |
m_hFile = NULL; | |
DWORD dwError = GetLastError(); | |
LogData("! Error Code : %d\n", dwError); | |
return false; | |
} | |
//LogData("# open file [ %S ] success\n", lpFileName); | |
//{{get file size | |
if(!GetFileSizeEx(m_hFile, &m_liFileSize)) | |
{ | |
CloseHandle(m_hFile); | |
m_hFile = NULL; | |
m_liFileSize.QuadPart = 0; | |
return false; | |
} | |
//LogData("# file size: %I64d\n", m_liFileSize.QuadPart); | |
//}} | |
LARGE_INTEGER li; | |
li.QuadPart = 0; | |
SetFilePointer(m_hFile, li.LowPart, &li.HighPart, FILE_BEGIN); | |
return true; | |
} | |
#endif | |
bool CFileReader::Close() | |
{ | |
#ifdef _MAC_ | |
if(m_hFile != -1) | |
{ | |
FSCloseFork(m_hFile); | |
m_hFile = -1; | |
m_llFileSize = 0; | |
} | |
#else | |
if(m_hFile) | |
{ | |
CloseHandle(m_hFile); | |
m_hFile = NULL; | |
m_liFileSize.QuadPart = 0; | |
} | |
#endif | |
return true; | |
} | |
#ifdef _MAC_ | |
DWORD CFileReader::Read(LONGLONG llReadPosition, DWORD dwBytesToRead, BYTE* pBuffer) | |
{ | |
if(pBuffer == NULL) return AVM_E_INVALID_PARAMETER; | |
if(llReadPosition >= m_llFileSize) return AVM_E_FILE_EOF; | |
OSStatus err = noErr; | |
// OSStatus err = FSSetForkPosition(m_hFile, fsFromStart, llReadPosition); | |
// if(err != noErr) | |
// { | |
// return AVM_E_FILE_READ_FAILED; | |
// } | |
ByteCount dwBytesRead = 0; | |
if(llReadPosition + dwBytesToRead <= m_llFileSize) | |
{ | |
err = FSReadFork(m_hFile, fsFromStart|noCacheMask, (SInt64)llReadPosition, dwBytesToRead, (void*)pBuffer, &dwBytesRead); | |
} | |
else | |
{ | |
DWORD dwRemainderData = (DWORD)(m_llFileSize - llReadPosition); | |
err = FSReadFork(m_hFile, fsFromStart|noCacheMask, (SInt64)llReadPosition, dwRemainderData, (void*)pBuffer, &dwBytesRead); | |
} | |
if(err != noErr) | |
{ | |
return AVM_E_FILE_READ_FAILED; | |
} | |
return AVM_OK; | |
} | |
#else | |
DWORD CFileReader::Read(LONGLONG llReadPosition, DWORD dwBytesToRead, BYTE* pBuffer) | |
{ | |
if(pBuffer == NULL) return AVM_E_INVALID_PARAMETER; | |
if(llReadPosition >= (LONGLONG)m_liFileSize.QuadPart) return AVM_E_FILE_EOF; | |
LARGE_INTEGER li; | |
li.QuadPart = llReadPosition; | |
//set read position of the file | |
SetFilePointer(m_hFile, li.LowPart, &li.HighPart, FILE_BEGIN); | |
LONG lReadResult = 0; | |
DWORD dwBytesRead = 0; | |
if(llReadPosition + dwBytesToRead <= (LONGLONG)m_liFileSize.QuadPart) | |
{ | |
lReadResult = ReadFile(m_hFile, pBuffer, dwBytesToRead, &dwBytesRead, NULL); | |
} | |
else | |
{ | |
DWORD dwRemainderData = (DWORD)(m_liFileSize.QuadPart - llReadPosition); | |
lReadResult = ReadFile(m_hFile, pBuffer, dwRemainderData, &dwBytesRead, NULL); | |
} | |
if(!lReadResult) | |
{ | |
//LogText("! [1]read file failed\n"); | |
return AVM_E_FILE_READ_FAILED; | |
} | |
else if(dwBytesRead == 0) | |
{ | |
//LogText("! [1]read at the end of file\n"); | |
return AVM_E_FILE_EOF; | |
} | |
return AVM_OK; | |
} | |
#endif | |
#else | |
CFileReader::CFileReader() | |
: m_hFileMapping(NULL) | |
, m_hFile(NULL) | |
, m_llFileSize(0) | |
{ | |
} | |
CFileReader::~CFileReader() | |
{ | |
Close(); | |
} | |
bool CFileReader::Open(const WCHAR* lpFileName) | |
{ | |
if (m_hFile) { | |
Close(); | |
} | |
m_hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
if (m_hFile == INVALID_HANDLE_VALUE) { | |
DWORD dwError = GetLastError(); | |
LogData("!!![ERROR] -- open file [ %S ] failed, ErrorCode : %d\n", lpFileName, dwError); | |
m_hFile = NULL; | |
return false; | |
} | |
//LogData("# open file [ %S ] success\n", lpFileName); | |
LARGE_INTEGER liFileSize; | |
if (!GetFileSizeEx(m_hFile, &liFileSize)) { | |
CloseHandle(m_hFile); | |
m_hFile = NULL; | |
m_llFileSize = 0; | |
return false; | |
} | |
m_llFileSize = liFileSize.QuadPart; | |
//LogData("# file size: %I64d\n", m_llFileSize); | |
m_hFileMapping = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); | |
if (m_hFileMapping == NULL) { | |
LogText("!!![ERROR] create file mapping failed\n"); | |
CloseHandle(m_hFile); | |
m_hFile = NULL; | |
m_llFileSize = 0; | |
return false; | |
} | |
return true; | |
} | |
bool CFileReader::Close() | |
{ | |
if(m_hFile) | |
{ | |
CloseHandle(m_hFile); | |
m_hFile = NULL; | |
m_llFileSize = 0; | |
CloseHandle(m_hFileMapping); | |
m_hFileMapping = NULL; | |
} | |
return true; | |
} | |
DWORD CFileReader::Read(LONGLONG llReadPosition, DWORD dwBytesToRead, BYTE* pBuffer) | |
{ | |
if(pBuffer == NULL) return AVM_E_INVALID_PARAMETER; | |
if(llReadPosition >= m_llFileSize) return AVM_E_FILE_EOF; | |
bool bEndOfFile = false; | |
DWORD dwBytesForMapping = dwBytesToRead; | |
if (llReadPosition + dwBytesToRead > m_llFileSize) { | |
dwBytesForMapping = (DWORD)(m_llFileSize - llReadPosition); | |
bEndOfFile = true; | |
} | |
SYSTEM_INFO SysInfo; | |
GetSystemInfo(&SysInfo); | |
DWORD dwBytesInBlock = SysInfo.dwAllocationGranularity; | |
LONGLONG llCopySize = dwBytesForMapping; | |
LONGLONG llStartOffset = llReadPosition; | |
LONGLONG nBlocks = 0; | |
DWORD nResidue = 0; | |
LONGLONG llOffset = 0; | |
DWORD dwCopyBlock = dwBytesInBlock; | |
while (llCopySize > 0) { | |
nBlocks = llStartOffset / dwBytesInBlock; | |
nResidue = (DWORD)(llStartOffset % dwBytesInBlock); | |
llOffset = nBlocks * dwBytesInBlock; | |
if (llCopySize < dwBytesInBlock) { | |
dwCopyBlock = (DWORD)llCopySize; | |
} | |
LPBYTE pAddress = (LPBYTE)MapViewOfFile(m_hFileMapping, FILE_MAP_READ, (DWORD)(llOffset >> 32), (DWORD)(llOffset & 0xFFFFFFFF), dwCopyBlock + nResidue); | |
if (pAddress == NULL) { | |
DWORD dwError = GetLastError(); | |
LogData("!!![EEROR] CFileReader::Read failed, ErrorCode: %d\n", dwError); | |
return AVM_E_FILE_READ_FAILED; | |
} | |
memcpy(pBuffer + (dwBytesForMapping - llCopySize), pAddress + nResidue, dwCopyBlock); | |
UnmapViewOfFile(pAddress); | |
llStartOffset += dwCopyBlock; | |
llCopySize -= dwCopyBlock; | |
} | |
if (bEndOfFile) { | |
return AVM_E_FILE_EOF; | |
} | |
return AVM_OK; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment