Skip to content

Instantly share code, notes, and snippets.

@shanewfx
Created January 6, 2013 03:05
Show Gist options
  • Save shanewfx/4464961 to your computer and use it in GitHub Desktop.
Save shanewfx/4464961 to your computer and use it in GitHub Desktop.
[C++] FileReader.cpp
#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