📄 datalist.c
字号:
/* * datalist.c * Copyright (C) 2000-2002 A.J. van Os; Released under GPL * * Description: * Build, read and destroy a list of Word data blocks */#include <stdlib.h>#include <errno.h>#include "antiword.h"#if defined(__riscos)#define EIO 42#endif /* __riscos *//* * Private structure to hide the way the information * is stored from the rest of the program */typedef struct data_mem_tag { data_block_type tInfo; struct data_mem_tag *pNext;} data_mem_type;/* Variable to describe the start of the data block list */static data_mem_type *pAnchor = NULL;/* Variable needed to read the data block list */static data_mem_type *pBlockLast = NULL;/* Variable needed to read the data block list */static data_mem_type *pBlockCurrent = NULL;static ULONG ulBlockOffset = 0;static size_t tByteNext = 0;/* Last block read */static UCHAR aucBlock[BIG_BLOCK_SIZE];/* * vDestroyDataBlockList - destroy the data block list */voidvDestroyDataBlockList(void){ data_mem_type *pCurr, *pNext; DBG_MSG("vDestroyDataBlockList"); pCurr = pAnchor; while (pCurr != NULL) { pNext = pCurr->pNext; pCurr = xfree(pCurr); pCurr = pNext; } pAnchor = NULL; /* Reset all the control variables */ pBlockLast = NULL; pBlockCurrent = NULL; ulBlockOffset = 0; tByteNext = 0;} /* end of vDestroyDataBlockList *//* * bAdd2DataBlockList - add an element to the data block list * * Returns TRUE when successful, otherwise FALSE */BOOLbAdd2DataBlockList(const data_block_type *pDataBlock){ data_mem_type *pListMember; fail(pDataBlock == NULL); fail(pDataBlock->ulFileOffset == FC_INVALID); fail(pDataBlock->ulDataPos == CP_INVALID); fail(pDataBlock->ulLength == 0); NO_DBG_MSG("bAdd2DataBlockList"); NO_DBG_HEX(pDataBlock->ulFileOffset); NO_DBG_HEX(pDataBlock->ulDataPos); NO_DBG_HEX(pDataBlock->ulLength); if (pDataBlock->ulFileOffset == FC_INVALID || pDataBlock->ulDataPos == CP_INVALID || pDataBlock->ulLength == 0) { werr(0, "Software (datablock) error"); return FALSE; } /* Check for continuous blocks */ if (pBlockLast != NULL && pBlockLast->tInfo.ulFileOffset + pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset && pBlockLast->tInfo.ulDataPos + pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) { /* These are continous blocks */ pBlockLast->tInfo.ulLength += pDataBlock->ulLength; return TRUE; } /* Make a new block */ pListMember = xmalloc(sizeof(data_mem_type)); /* Add the block to the data list */ pListMember->tInfo = *pDataBlock; pListMember->pNext = NULL; if (pAnchor == NULL) { pAnchor = pListMember; } else { fail(pBlockLast == NULL); pBlockLast->pNext = pListMember; } pBlockLast = pListMember; return TRUE;} /* end of bAdd2DataBlockList *//* * ulGetDataOffset - get the offset in the data block list * * Get the fileoffset the current position in the data block list */ULONGulGetDataOffset(FILE *pFile){ return pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset + tByteNext;} /* end of ulGetDataOffset *//* * bSetDataOffset - set the offset in the data block list * * Make the given fileoffset the current position in the data block list */BOOLbSetDataOffset(FILE *pFile, ULONG ulFileOffset){ data_mem_type *pCurr; size_t tReadLen; DBG_HEX(ulFileOffset); for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { if (ulFileOffset < pCurr->tInfo.ulFileOffset || ulFileOffset >= pCurr->tInfo.ulFileOffset + pCurr->tInfo.ulLength) { /* The file offset is not in this block */ continue; } /* Compute the maximum number of bytes to read */ tReadLen = (size_t)(pCurr->tInfo.ulFileOffset + pCurr->tInfo.ulLength - ulFileOffset); /* Compute the real number of bytes to read */ if (tReadLen > sizeof(aucBlock)) { tReadLen = sizeof(aucBlock); } /* Read the bytes */ if (!bReadBytes(aucBlock, tReadLen, ulFileOffset, pFile)) { return FALSE; } /* Set the control variables */ pBlockCurrent = pCurr; ulBlockOffset = ulFileOffset - pCurr->tInfo.ulFileOffset; tByteNext = 0; return TRUE; } return FALSE;} /* end of bSetDataOffset *//* * iNextByte - get the next byte from the data block list */intiNextByte(FILE *pFile){ ULONG ulReadOff; size_t tReadLen; fail(pBlockCurrent == NULL); if (tByteNext >= sizeof(aucBlock) || ulBlockOffset + tByteNext >= pBlockCurrent->tInfo.ulLength) { if (ulBlockOffset + sizeof(aucBlock) < pBlockCurrent->tInfo.ulLength) { /* Same block, next part */ ulBlockOffset += sizeof(aucBlock); } else { /* Next block, first part */ pBlockCurrent = pBlockCurrent->pNext; ulBlockOffset = 0; } if (pBlockCurrent == NULL) { /* Past the last part of the last block */ errno = EIO; return EOF; } tReadLen = (size_t) (pBlockCurrent->tInfo.ulLength - ulBlockOffset); if (tReadLen > sizeof(aucBlock)) { tReadLen = sizeof(aucBlock); } ulReadOff = pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset; if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) { errno = EIO; return EOF; } tByteNext = 0; } return (int)aucBlock[tByteNext++];} /* end of iNextByte *//* * usNextWord - get the next word from the data block list * * Read a two byte value in Little Endian order, that means MSB last * * All return values can be valid so errno is set in case of error */USHORTusNextWord(FILE *pFile){ USHORT usLSB, usMSB; usLSB = (USHORT)iNextByte(pFile); if (usLSB == (USHORT)EOF) { errno = EIO; return (USHORT)EOF; } usMSB = (USHORT)iNextByte(pFile); if (usMSB == (USHORT)EOF) { DBG_MSG("usNextWord: Unexpected EOF"); errno = EIO; return (USHORT)EOF; } return (usMSB << 8) | usLSB;} /* end of usNextWord *//* * ulNextLong - get the next long from the data block list * * Read a four byte value in Little Endian order, that means MSW last * * All return values can be valid so errno is set in case of error */ULONGulNextLong(FILE *pFile){ ULONG ulLSW, ulMSW; ulLSW = (ULONG)usNextWord(pFile); if (ulLSW == (ULONG)EOF) { errno = EIO; return (ULONG)EOF; } ulMSW = (ULONG)usNextWord(pFile); if (ulMSW == (ULONG)EOF) { DBG_MSG("ulNextLong: Unexpected EOF"); errno = EIO; return (ULONG)EOF; } return (ulMSW << 16) | ulLSW;} /* end of ulNextLong *//* * usNextWordBE - get the next two byte value * * Read a two byte value in Big Endian order, that means MSB first * * All return values can be valid so errno is set in case of error */USHORTusNextWordBE(FILE *pFile){ USHORT usLSB, usMSB; usMSB = (USHORT)iNextByte(pFile); if (usMSB == (USHORT)EOF) { errno = EIO; return (USHORT)EOF; } usLSB = (USHORT)iNextByte(pFile); if (usLSB == (USHORT)EOF) { DBG_MSG("usNextWordBE: Unexpected EOF"); errno = EIO; return (USHORT)EOF; } return (usMSB << 8) | usLSB;} /* end of usNextWordBE *//* * ulNextLongBE - get the next four byte value * * Read a four byte value in Big Endian order, that means MSW first * * All return values can be valid so errno is set in case of error */ULONGulNextLongBE(FILE *pFile){ ULONG ulLSW, ulMSW; ulMSW = (ULONG)usNextWordBE(pFile); if (ulMSW == (ULONG)EOF) { errno = EIO; return (ULONG)EOF; } ulLSW = (ULONG)usNextWordBE(pFile); if (ulLSW == (ULONG)EOF) { DBG_MSG("ulNextLongBE: Unexpected EOF"); errno = EIO; return (ULONG)EOF; } return (ulMSW << 16) | ulLSW;} /* end of ulNextLongBE *//* * tSkipBytes - skip over the given number of bytes * * Returns the number of skipped bytes */size_ttSkipBytes(FILE *pFile, size_t tToSkip){ size_t tToGo, tMaxMove, tMove; fail(pFile == NULL); fail(pBlockCurrent == NULL); tToGo = tToSkip; while (tToGo != 0) { /* Goto the end of the current block */ tMaxMove = min(sizeof(aucBlock) - tByteNext, (size_t)(pBlockCurrent->tInfo.ulLength - ulBlockOffset - tByteNext)); tMove = min(tMaxMove, tToGo); tByteNext += tMove; tToGo -= tMove; if (tToGo != 0) { /* Goto the next block */ if (iNextByte(pFile) == EOF) { return tToSkip - tToGo; } tToGo--; } } return tToSkip;} /* end of tSkipBytes *//* * Translate a data position to an offset in the file. * Logical to physical offset. * * Returns: FC_INVALID: in case of error * otherwise: the computed file offset */ULONGulDataPos2FileOffset(ULONG ulDataPos){ data_mem_type *pCurr; fail(ulDataPos == CP_INVALID); for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { if (ulDataPos < pCurr->tInfo.ulDataPos || ulDataPos >= pCurr->tInfo.ulDataPos + pCurr->tInfo.ulLength) { /* The data offset is not in this block, try the next */ continue; } /* The data offset is in the current block */ return pCurr->tInfo.ulFileOffset + ulDataPos - pCurr->tInfo.ulDataPos; } /* Passed beyond the end of the list */ DBG_HEX_C(ulDataPos != 0, ulDataPos); return FC_INVALID;} /* end of ulDataPos2FileOffset */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -