reman3/Rayman_X/cpa/tempgrp/SCR/SCR_Page.c

528 lines
19 KiB
C

/*
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
* SCR_Page.c
* Managment of pages for high level saving functions.
*
* Scripts, Beaudet Christophe
*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
/*
*=================================================================================================
* Includes.
*=================================================================================================
*/
#include <memory.h>
#include "SCR.h"
/*
*=================================================================================================
* Functions.
*=================================================================================================
*/
/*
*-------------------------------------------------------------------------------------------------
* To allocate and initialize a new page.
* Returns allocated structure.
*-------------------------------------------------------------------------------------------------
*/
SCR_tdst_Page_Description *fnp_st_Page_Allocate(void)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_tdst_Page_Description *p_stPage;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
fn_v_Mem_SetMode(0);
/*
* Allocate the page.
*/
SCR_M_Mem_Alloc(SCR_tdst_Page_Description, p_stPage, 1);
/*
* Initialize the page.
*/
SCR_M_Dbg_UpdateSizeOf_P(SCR_tdst_Page_Description, p_stPage);
p_stPage->iNumOfChars = 0;
p_stPage->p_stNext = p_stPage->p_stPrev = NULL;
SCR_M_Mem_Alloc(char, p_stPage->d_cBuffer, SCR_CV_ui_Cfg_SizePageBuf);
return p_stPage;
}
/*
*-------------------------------------------------------------------------------------------------
* To delete an existing page.
* Returns allocated structure.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_Free(SCR_tdst_Page_Description *_p_stPage)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_AssertStruct_P(SCR_tdst_Page_Description, _p_stPage);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
fn_v_Mem_SetMode(0);
SCR_M_Mem_Free(_p_stPage->d_cBuffer);
SCR_M_Mem_Free(_p_stPage);
}
/*
*-------------------------------------------------------------------------------------------------
* To delete all pages of a file.
* _p_stFile : File concerned.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_DeleteAll(SCR_tdst_File_Description *_p_stFile)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_tdst_Page_Description *p_stPage, *p_stNext;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
p_stPage = _p_stFile->d_stFirstPage;
while(p_stPage)
{
p_stNext = p_stPage->p_stNext;
fn_v_Page_Free(p_stPage);
p_stPage = p_stNext;
}
}
/*===============================================================================================*/
/*
*-------------------------------------------------------------------------------------------------
* Link a page after another one.
* _p_stFile : File concerned.
* _p_stPage : Page to link.
* _p_stRef : Reference page.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_LinkAfter
(
SCR_tdst_File_Description *_p_stFile,
SCR_tdst_Page_Description *_p_stPage,
SCR_tdst_Page_Description *_p_stRef
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_AssertStruct_P(SCR_tdst_Page_Description, _p_stPage);
SCR_M_Dbg_AssertStruct_P(SCR_tdst_Page_Description, _p_stRef);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
_p_stPage->p_stNext = _p_stRef->p_stNext;
_p_stPage->p_stPrev = _p_stRef;
if(_p_stRef->p_stNext)
_p_stRef->p_stNext->p_stPrev = _p_stPage;
else
_p_stFile->d_stLastPage = _p_stPage;
_p_stRef->p_stNext = _p_stPage;
}
/*
*-------------------------------------------------------------------------------------------------
* To unlink a page from a list of page.
* _p_stFile : File concerned.
* _p_stPage : Page to unlink.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_Unlink
(
SCR_tdst_File_Description *_p_stFile,
SCR_tdst_Page_Description *_p_stPage
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_AssertStruct_P(SCR_tdst_Page_Description, _p_stPage);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(_p_stFile->d_stFirstPage == _p_stPage)
{
_p_stFile->d_stFirstPage = _p_stPage->p_stNext;
if(_p_stFile->d_stFirstPage == NULL)
_p_stFile->d_stFirstPage = _p_stPage->p_stPrev;
}
if(_p_stFile->d_stLastPage == _p_stPage)
{
_p_stFile->d_stLastPage = _p_stPage->p_stNext;
if(_p_stFile->d_stLastPage == NULL)
_p_stFile->d_stLastPage = _p_stPage->p_stPrev;
}
if(_p_stPage->p_stNext)
_p_stPage->p_stNext->p_stPrev = _p_stPage->p_stPrev;
if(_p_stPage->p_stPrev)
_p_stPage->p_stPrev->p_stNext = _p_stPage->p_stNext;
}
/*
*-------------------------------------------------------------------------------------------------
* Split a full page in 2 parts.
* _p_stFile : File concerned.
* _p_stPage : Page to split.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_Split
(
SCR_tdst_File_Description *_p_stFile,
SCR_tdst_Page_Description *_p_stPage
)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_tdst_Page_Description *p_stNewPage;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_AssertStruct_P(SCR_tdst_Page_Description, _p_stPage);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*
* Allocate new page.
*/
p_stNewPage = fnp_st_Page_Allocate();
/*
* Copy second part of actual page to new one.
*/
memcpy
(
p_stNewPage->d_cBuffer,
&_p_stPage->d_cBuffer[SCR_CV_ui_Cfg_SizePageBuf2],
SCR_CV_ui_Cfg_SizePageBuf2
);
p_stNewPage->iNumOfChars = SCR_CV_ui_Cfg_SizePageBuf2;
_p_stPage->iNumOfChars -= SCR_CV_ui_Cfg_SizePageBuf2;
/*
* Update current position.
*/
if(_p_stFile->iCurPosInPage >= SCR_CV_ui_Cfg_SizePageBuf2)
{
_p_stFile->d_stCurPage = p_stNewPage;
_p_stFile->iCurPosInPage -= SCR_CV_ui_Cfg_SizePageBuf2;
}
/*
* Link new page after slitted one.
*/
fn_v_Page_LinkAfter(_p_stFile, p_stNewPage, _p_stPage);
}
/*===============================================================================================*/
/*
*-------------------------------------------------------------------------------------------------
* Insert a character at current position.
* _p_stFile : File concerned.
* _cChar : Character to insert.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_InsertChar(SCR_tdst_File_Description *_p_stFile, char _cChar)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_tdst_Page_Description *p_stPage;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
p_stPage = _p_stFile->d_stCurPage;
/*
* Current page is full.
*/
if(p_stPage->iNumOfChars == SCR_CV_ui_Cfg_SizePageBuf)
{
fn_v_Page_Split(_p_stFile, p_stPage);
p_stPage = _p_stFile->d_stCurPage;
}
/*
* Shift buffer of page.
*/
memmove
(
&p_stPage->d_cBuffer[_p_stFile->iCurPosInPage + 1],
&p_stPage->d_cBuffer[_p_stFile->iCurPosInPage],
p_stPage->iNumOfChars - _p_stFile->iCurPosInPage
);
/*
* Set character.
*/
p_stPage->d_cBuffer[_p_stFile->iCurPosInPage] = _cChar;
p_stPage->iNumOfChars++;
/*
* Increment current position.
*/
fn_v_Page_ToNextChar(_p_stFile);
}
/*
*-------------------------------------------------------------------------------------------------
* Delete character at current position.
* _p_stFile : File concerned.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_DeleteChar(SCR_tdst_File_Description *_p_stFile)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_tdst_Page_Description *p_stPage;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_Assert_P(_p_stFile->d_stCurPage != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* EOF ? */
p_stPage = _p_stFile->d_stCurPage;
if(p_stPage->d_cBuffer[_p_stFile->iCurPosInPage] == 0)
return;
/*
* We vill delete page ?.
*/
if(p_stPage->iNumOfChars == 1)
{
SCR_M_Dbg_Assert_P(p_stPage->p_stNext);
_p_stFile->d_stCurPage = p_stPage->p_stNext;
_p_stFile->iCurPosInPage = 0;
fn_v_Page_Unlink(_p_stFile, p_stPage);
fn_v_Page_Free(p_stPage);
}
else
{
/*
* We delete the last character of page.
* We compute the next current position.
*/
if(_p_stFile->iCurPosInPage == (p_stPage->iNumOfChars - 1))
{
SCR_M_Dbg_Assert_P(p_stPage->p_stNext != NULL);
_p_stFile->d_stCurPage = p_stPage->p_stNext;
_p_stFile->iCurPosInPage = 0;
p_stPage->iNumOfChars--;
}
/*
* Else we shift the buffer normally.
*/
else
{
memmove
(
&p_stPage->d_cBuffer[_p_stFile->iCurPosInPage],
&p_stPage->d_cBuffer[_p_stFile->iCurPosInPage + 1],
p_stPage->iNumOfChars - _p_stFile->iCurPosInPage - 1
);
p_stPage->iNumOfChars--;
}
}
}
/*===============================================================================================*/
/*
*-------------------------------------------------------------------------------------------------
* Go to next position.
* _p_stFile : File concerned.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_ToNextChar(SCR_tdst_File_Description *_p_stFile)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_Assert_P(_p_stFile->d_stFirstPage != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(_p_stFile->iCurPosInPage + 1 == _p_stFile->d_stCurPage->iNumOfChars)
{
if(_p_stFile->d_stCurPage->p_stNext)
{
_p_stFile->iCurPosInPage = 0;
_p_stFile->d_stCurPage = _p_stFile->d_stCurPage->p_stNext;
}
}
else
_p_stFile->iCurPosInPage++;
}
/*
*-------------------------------------------------------------------------------------------------
* Go to previous position.
* _p_stFile : File concerned.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_ToPrevChar(SCR_tdst_File_Description *_p_stFile)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_Assert_P(_p_stFile->d_stFirstPage != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(_p_stFile->iCurPosInPage == 0)
{
if(_p_stFile->d_stCurPage->p_stPrev)
{
_p_stFile->d_stCurPage = _p_stFile->d_stCurPage->p_stPrev;
_p_stFile->iCurPosInPage = _p_stFile->d_stCurPage->iNumOfChars - 1;
}
}
else
_p_stFile->iCurPosInPage--;
}
/*===============================================================================================*/
/*
*-------------------------------------------------------------------------------------------------
* Load a complete file in memory.
* _p_stFile : File concerned.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_LoadFile(SCR_tdst_File_Description *_p_stFile)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
size_t xRead;
SCR_tdst_Page_Description *p_stPage;
int iRes;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*
* Create first page.
*/
_p_stFile->d_stFirstPage = fnp_st_Page_Allocate();
_p_stFile->d_stLastPage = _p_stFile->d_stCurPage = _p_stFile->d_stFirstPage;
_p_stFile->iCurPosInPage = 0;
SCR_M_fseek(_p_stFile, 0, SEEK_SET, iRes);
if(iRes)
{
SCR_M_Err_UpdateSyntaxError();
sprintf
(
g_st_Err_GlobalError.a_szBufferTmp2,
"File is \"%s\".",
_p_stFile->a_szFileName
);
SCR_M_Err_RaiseError(SCR_EI_Err_ReadFile);
}
/*
* Read file.
*/
while(!SCR_M_feof(_p_stFile))
{
/* Read one page from file */
xRead = SCR_M_fread
(
_p_stFile->d_stLastPage->d_cBuffer,
sizeof(char),
SCR_CV_ui_Cfg_SizePageBuf2,
_p_stFile
);
_p_stFile->d_stLastPage->iNumOfChars = xRead;
/* Allocate a new page if this one is full */
if((xRead == SCR_CV_ui_Cfg_SizePageBuf2) && (!SCR_M_feof(_p_stFile)))
{
p_stPage = fnp_st_Page_Allocate();
fn_v_Page_LinkAfter(_p_stFile, p_stPage, _p_stFile->d_stLastPage);
}
}
/*
* Add an '\n' and an EOF character at the end of the file.
*/
if(_p_stFile->d_stLastPage->d_cBuffer[_p_stFile->d_stLastPage->iNumOfChars - 1] != '\n')
{
_p_stFile->d_stLastPage->d_cBuffer[_p_stFile->d_stLastPage->iNumOfChars ] = '\n';
_p_stFile->d_stLastPage->iNumOfChars++;
}
_p_stFile->d_stLastPage->d_cBuffer[_p_stFile->d_stLastPage->iNumOfChars] = '\0';
_p_stFile->d_stLastPage->iNumOfChars++;
}
/*
*-------------------------------------------------------------------------------------------------
* Save a complete memory file.
* _p_stFile : File concerned.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_SaveFile(SCR_tdst_File_Description *_p_stFile)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_tdst_Page_Description *p_stPage;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_Assert_P(_p_stFile->d_stFirstPage != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
p_stPage = _p_stFile->d_stFirstPage;
while(p_stPage)
{
if(p_stPage == _p_stFile->d_stLastPage) /* Cause of EOF */
p_stPage->iNumOfChars--;
SCR_M_fwrite(p_stPage->d_cBuffer, sizeof(char), p_stPage->iNumOfChars, _p_stFile);
p_stPage = p_stPage->p_stNext;
}
}
/*===============================================================================================*/
/*
*-------------------------------------------------------------------------------------------------
* To seek to a specific position.
* _p_stFile : File concerned.
* lOffset : Offset to seek.
* iOrigin : Origin to seek from.
*-------------------------------------------------------------------------------------------------
*/
void fn_v_Page_Seek(SCR_tdst_File_Description *_p_stFile, long lOffset, int iOrigin)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
long lCount;
SCR_tdst_Page_Description *p_stPage;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
SCR_M_Dbg_Assert_P(_p_stFile != NULL);
SCR_M_Dbg_Assert_P(_p_stFile->d_stFirstPage != NULL);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*
* Place current position from the end of file.
*/
if(iOrigin == SEEK_END)
{
p_stPage = _p_stFile->d_stLastPage;
lCount = p_stPage->iNumOfChars;
while(lCount <= lOffset)
{
p_stPage = p_stPage->p_stPrev;
lCount += p_stPage->iNumOfChars;
}
_p_stFile->d_stCurPage = p_stPage;
_p_stFile->iCurPosInPage = lCount - lOffset - 1;
}
/*
* Place current position from the beginning of file.
*/
else
{
SCR_M_Dbg_Assert_P(iOrigin == SEEK_SET);
p_stPage = _p_stFile->d_stFirstPage;
lCount = p_stPage->iNumOfChars;
while((lCount <= lOffset) && (p_stPage->p_stNext))
{
p_stPage = p_stPage->p_stNext;
lCount += p_stPage->iNumOfChars;
}
_p_stFile->d_stCurPage = p_stPage;
_p_stFile->iCurPosInPage = p_stPage->iNumOfChars - (lCount - lOffset);
if((p_stPage->p_stNext == NULL) && (lCount <= lOffset))
_p_stFile->iCurPosInPage = p_stPage->iNumOfChars - 1;
}
}