/* *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * SCR_Page.c * Managment of pages for high level saving functions. * * Scripts, Beaudet Christophe *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ /* *================================================================================================= * Includes. *================================================================================================= */ #include #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; } }