📄 filemap.c
字号:
/*===========================================================================
包明辉 CFileMap , 读文件缓冲 , 分为3块缓冲区。
主要方法:boolean CFileMap_GetData(CFileMap* pMap , uint32 nIndex , uint32 nSize , boolean* bEnd)
FILE: FileMap.c
===========================================================================*/
#include "FileMap.h"
//////////////////////////////////////////////////////////////////////////
//构造
CFileMap* CFileMap_New(IFileMgr* pFileMgr , const char* pszFileName , PFNRBBNOTIFY pReCall , void* pvUser , AEEApplet* pThis)
{
CFileMap* pRet = NULL;
FileInfo tagFinfo;
//////////////////////////////////////////////////////////////////////////
//验证参数
if(NULL == pFileMgr || NULL == pszFileName || NULL == pReCall || NULL == pvUser || NULL == pThis)
goto ferr;
//////////////////////////////////////////////////////////////////////////
//分配对象结构
pRet = MALLOC(sizeof(CFileMap));
if(NULL == pRet)
goto ferr;
MEMSET(pRet , 0 , sizeof(CFileMap));
//////////////////////////////////////////////////////////////////////////
//建立要读的文件
pRet->m_pFile = IFILEMGR_OpenFile(pFileMgr , pszFileName , _OFM_READ);
if(NULL == pRet->m_pFile)
goto ferr;
MEMSET(&tagFinfo , 0 , sizeof(FileInfo));
if(SUCCESS != IFILE_GetInfo(pRet->m_pFile , &tagFinfo))
goto ferr;
//////////////////////////////////////////////////////////////////////////
//预读文件
pRet->m_pThis = pThis;
pRet->m_tagNotifyPar.m_pvUser = pvUser;
pRet->m_pReCall = pReCall;
pRet->m_nTotalSize = tagFinfo.dwSize;
if(pRet->m_nTotalSize <= (3 * BUFFERSIZE)) //判断是否需要分3块缓冲
{
pRet->m_bIsBu = FALSE;
pRet->m_nTotalPage = 0;
pRet->m_nLstPgSize = 0;
pRet->m_tagNotifyPar.m_nMaxDataSize = pRet->m_nTotalSize - 1;
pRet->m_tagNotifyPar.m_pDataBeg = (void*)pRet->m_Buffer[0];
pRet->m_tagNotifyPar.m_pDataEnd = (void*)pRet->m_Buffer[0];
MEMSET(pRet->m_Buffer[0] , 0 , BUFFERSIZE + BUFFERSIZE + BUFFERSIZE);
FileRead(pRet , 0 , pRet->m_nTotalSize);
}
else
{ pRet->m_bIsBu = TRUE;
pRet->m_nTotalPage = tagFinfo.dwSize / BUFFERSIZE; //一共叶数字
pRet->m_nLstPgSize = tagFinfo.dwSize % BUFFERSIZE; //最后一叶大小
pRet->m_tagNotifyPar.m_nMaxDataSize = BUFFERSIZE + BUFFERSIZE - 1;
pRet->m_tagNotifyPar.m_pDataBeg = pRet->m_Buffer[1];
pRet->m_tagNotifyPar.m_pDataEnd = pRet->m_Buffer[1];
FileRead(pRet , 1 , 2 * BUFFERSIZE);
}
//至此文件信息获得完毕,计算需要的数据
//////////////////////////////////////////////////////////////////////////
//返回值错误
return pRet;
ferr:
FILEMAP_FREE(pRet);
return NULL;
}
//////////////////////////////////////////////////////////////////////////
//释放资源
void CFileMap_Release(CFileMap** ppFileMap)
{
if(ppFileMap && *ppFileMap)
{
if((*ppFileMap)->m_pFile)
IFILE_Release((*ppFileMap)->m_pFile);
(*ppFileMap)->m_pFile = NULL;
FREEIF(*ppFileMap);
*ppFileMap = NULL;
}
}
//////////////////////////////////////////////////////////////////////////
//获得数据
boolean CFileMap_GetData(CFileMap* pMap , uint32 nIndex , uint32 nSize , boolean* bEnd)
{
boolean bRet = TRUE;
uint32 nNowBegin = 0; //读文件的开始部分
uint32 nNowEnd = 0; //读文件结素部分
//////////////////////////////////////////////////////////////////////////
//简单检查必要参数
if(NULL == pMap || NULL == bEnd)
return FALSE;
*bEnd = FALSE;
//////////////////////////////////////////////////////////////////////////
//确定读文件的开始位置
nNowBegin = (NOW_READ == nIndex) ? pMap->m_nIndex : nIndex;
if(nNowBegin >= pMap->m_nTotalSize) return FALSE;
//////////////////////////////////////////////////////////////////////////
//进行缓冲计算
if(pMap->m_bIsBu)
{
//////////////////////////////////////////////////////////////////////////
//分块缓冲
uint32 nReadSize = 0; //读文件的大小
int32 nNowPage = 0; //当前页
int32 nGotPage = 0; //要跳转的页
int32 nThiPage = 0; //跳转开始页
uint32 nPageIndex = 0; //当前叶内偏移
uint32 nPageEndIndex = 0; //移动结束叶内偏移
uint32 nMaxLengh = 0; //跳转的最大长度如果超过这个长度说明缓冲区不够大
nPageIndex = nNowBegin % BUFFERSIZE; //求得当前开始读文件地方的叶内偏移
nMaxLengh = ((BUFFERSIZE + BUFFERSIZE) - nPageIndex - 1);//求的能读文件的最大长度
if(nSize > nMaxLengh) return FALSE; //缓冲区不够用直接返回失败
nNowEnd = (NOW_READ == nSize) ? nMaxLengh : MIN((nNowBegin + nSize) , pMap->m_nTotalSize);
nPageEndIndex = nNowEnd % BUFFERSIZE;
nNowPage = (int32)(pMap->m_nIndex / BUFFERSIZE);//求得当前页
nGotPage = (int32)(nNowEnd / BUFFERSIZE); //求得要跳转的页
nThiPage = (int32)(nNowBegin / BUFFERSIZE); //求得跳转开始页
pMap->m_nIndex = nNowEnd;
pMap->m_tagNotifyPar.m_nMaxDataSize = (nGotPage + 1) < pMap->m_nTotalPage ? ((2 * BUFFERSIZE) - nPageEndIndex - 1) : (pMap->m_nTotalSize - nNowEnd);
switch(nGotPage - nThiPage)
{
case 0:
pMap->m_tagNotifyPar.m_pDataBeg = pMap->m_Buffer[ANOW_PAGE] + nPageIndex;
pMap->m_tagNotifyPar.m_pDataEnd = pMap->m_Buffer[ANOW_PAGE] + nPageEndIndex;
break;
case 1:
pMap->m_tagNotifyPar.m_pDataBeg = pMap->m_Buffer[PERV_PAGE] + nPageIndex;
pMap->m_tagNotifyPar.m_pDataEnd = pMap->m_Buffer[ANOW_PAGE] + nPageEndIndex;
break;
default:
pMap->m_tagNotifyPar.m_nMaxDataSize = 0;
pMap->m_tagNotifyPar.m_pDataEnd = NULL;
pMap->m_tagNotifyPar.m_pDataBeg = NULL; //到这里出现错误
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
switch(nGotPage - nNowPage)
{
case 0:
bRet = ReCall(pMap , FILEMAP_REDA);
break;
case 1:
MEMCPY(pMap->m_Buffer[PERV_PAGE] , pMap->m_Buffer[ANOW_PAGE] , BUFFERSIZE);
MEMCPY(pMap->m_Buffer[ANOW_PAGE] , pMap->m_Buffer[NEXT_PAGE] , BUFFERSIZE);
switch(nGotPage - pMap->m_nTotalPage)
{
case 0:
bRet = ReCall(pMap , FILEMAP_REDA);
break;
default:
if(EFAILED != MoveFilePoint(pMap , nGotPage + 1))
{
nReadSize = (nGotPage + 1) >= pMap->m_nTotalPage ? pMap->m_nLstPgSize : BUFFERSIZE;
MEMSET(pMap->m_Buffer[NEXT_PAGE] , 0 , BUFFERSIZE);
FileRead(pMap , 2 , nReadSize);
}
else
bRet = FALSE;
}
break;
case 2:
MEMCPY(pMap->m_Buffer[PERV_PAGE] , pMap->m_Buffer[NEXT_PAGE] , BUFFERSIZE);
if(EFAILED != MoveFilePoint(pMap , nGotPage))
{
nReadSize = (nGotPage + 1) >= pMap->m_nTotalPage ? (BUFFERSIZE + pMap->m_nLstPgSize) : (BUFFERSIZE + BUFFERSIZE);
FileRead(pMap , 1 , nReadSize);
}
else
bRet = FALSE;
break;
case -1:
MEMCPY(pMap->m_Buffer[NEXT_PAGE] , pMap->m_Buffer[ANOW_PAGE] , BUFFERSIZE);
MEMCPY(pMap->m_Buffer[ANOW_PAGE] , pMap->m_Buffer[PERV_PAGE] , BUFFERSIZE);
switch(nGotPage)
{
case 0:
bRet = ReCall(pMap , FILEMAP_REDA);
break;
default:
if(EFAILED != MoveFilePoint(pMap , nGotPage - 1))
FileRead(pMap , 0 , BUFFERSIZE);
else
bRet = FALSE;
}
break;
case -2:
{
MEMCPY(pMap->m_Buffer[NEXT_PAGE] , pMap->m_Buffer[PERV_PAGE] , BUFFERSIZE);
if(EFAILED != MoveFilePoint(pMap , nGotPage - 1))
FileRead(pMap , 0 , BUFFERSIZE + BUFFERSIZE);
else
bRet = FALSE;
}
break;
default:
MEMSET(pMap->m_Buffer[0] , 0 , BUFFERSIZE + BUFFERSIZE + BUFFERSIZE);
if(0 < nGotPage)
{
if(EFAILED != MoveFilePoint(pMap , nGotPage - 1))
{
switch(pMap->m_nTotalPage - nGotPage)
{
case 0:
nReadSize = BUFFERSIZE + pMap->m_nLstPgSize;
break;
case 1:
nReadSize = BUFFERSIZE + BUFFERSIZE + pMap->m_nLstPgSize;
break;
default:
nReadSize = BUFFERSIZE + BUFFERSIZE + BUFFERSIZE;
break;
}
FileRead(pMap , 0 , nReadSize);
}
else
bRet = FALSE;
}
else
{
if(EFAILED != MoveFilePoint(pMap , 0))
FileRead(pMap , 1 , BUFFERSIZE + BUFFERSIZE);
else
bRet = FALSE;
}
}//End switch(nGotPage - nNowPage)
}
else
{
nNowEnd = (NOW_READ == nSize) ? pMap->m_nTotalSize : MIN((nNowBegin + nSize) , pMap->m_nTotalSize);
pMap->m_nIndex = nNowEnd;
pMap->m_tagNotifyPar.m_nMaxDataSize = pMap->m_nTotalSize - nNowEnd;
pMap->m_tagNotifyPar.m_pDataBeg = pMap->m_Buffer[0] + nNowBegin;
pMap->m_tagNotifyPar.m_pDataEnd = pMap->m_Buffer[0] + nNowEnd;
if(FALSE == ReCall(pMap , FILEMAP_REDA))
return FALSE;
}
if(pMap->m_nIndex == 309500)
pMap->m_nIndex = pMap->m_nIndex;
if((pMap->m_nIndex + 1) >= pMap->m_nTotalSize)
*bEnd = TRUE;
return bRet;
}
uint32 MoveFilePoint(CFileMap* pMap , int32 nGotoPage)
{
int32 nFileIndex; //当前位置
nFileIndex = IFILE_Seek(pMap->m_pFile , _SEEK_CURRENT , 0);
return IFILE_Seek(pMap->m_pFile , _SEEK_CURRENT , (nGotoPage * BUFFERSIZE) - nFileIndex);//1位偏移
}
//////////////////////////////////////////////////////////////////////////
//获得文件大小
uint32 CFileMap_GetFileSize(CFileMap* pMap)
{
if(NULL == pMap)
return 0;
return pMap->m_nTotalSize;
}
//////////////////////////////////////////////////////////////////////////
//过得当前读文件的位置
uint32 CFileMap_GetFileIndex(CFileMap* pMap)
{
if(NULL == pMap)
return 0;
return pMap->m_nIndex;
}
//////////////////////////////////////////////////////////////////////////
//读文件回调
void FileReadStep(CFileMap* pMap) //必须保证回调用
{
int32 nRead = 0;
nRead = IFILE_Read(pMap->m_pFile , pMap->m_Buffer[pMap->m_nBlockIdx] + pMap->m_nReadIdx , MIN(READSIZE , pMap->m_nReadSize - pMap->m_nReadIdx));
switch(nRead)
{
case 0: //出现了错误
if(pMap->m_nReadIdx < pMap->m_nReadSize)
{
if(FALSE == ReCall(pMap , FILEMAP_IERR))
ISHELL_CloseApplet(pMap->m_pThis->m_pIShell , TRUE);
}
else
{
if(FALSE == ReCall(pMap , FILEMAP_REDA))
ISHELL_CloseApplet(pMap->m_pThis->m_pIShell , TRUE);
}
return;
default:
pMap->m_nReadIdx += nRead;
if(pMap->m_nReadIdx >= pMap->m_nReadSize)
{
if(FALSE == ReCall(pMap , FILEMAP_REDA))
ISHELL_CloseApplet(pMap->m_pThis->m_pIShell , TRUE);
return;
}
}
IFILE_Readable(pMap->m_pFile, (PFNNOTIFY)FileReadStep, (void*)pMap);
}
boolean FileRead(CFileMap* pMap ,
byte nBufferBlock ,
uint32 nBufferCount)
{
pMap->m_nBlockIdx = nBufferBlock;//要写的内存块
pMap->m_nReadSize = nBufferCount;//要读的文件大小字节
pMap->m_nReadIdx = 0; //读文件的位置
FileReadStep(pMap);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
//包装的回调函数
boolean ReCall(CFileMap* pMap , FileMapNotifyCode code)
{
pMap->m_tagNotifyPar.m_code = code;
if(SUCCESS == ISHELL_SetTimer(pMap->m_pThis->m_pIShell , 0 , (PFNNOTIFY)pMap->m_pReCall , (void*)&pMap->m_tagNotifyPar))
return TRUE;
else
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -