/*
* depot.c
* Copyright (C) 1998-2002 A.J. van Os; Released under GPL
*
* Description:
* Functions to compute the depot offset
*/
#include "antiword.h"
#define SIZE_RATIO (BIG_BLOCK_SIZE/SMALL_BLOCK_SIZE)
static ULONG *aulSmallBlockList = NULL;
static size_t tSmallBlockListLen = 0;
/*
* vDestroySmallBlockList - destroy the small block list
*/
void
vDestroySmallBlockList(void)
{
DBG_MSG("vDestroySmallBlockList");
aulSmallBlockList = xfree(aulSmallBlockList);
tSmallBlockListLen = 0;
} /* end of vDestroySmalBlockList */
/*
* vCreateSmallBlockList - create the small block list
*
* returns: TRUE when successful, otherwise FALSE
*/
BOOL
bCreateSmallBlockList(ULONG ulStartblock, const ULONG *aulBBD, size_t tBBDLen)
{
ULONG ulTmp;
size_t tSize;
int iIndex;
fail(aulSmallBlockList != NULL);
fail(tSmallBlockListLen != 0);
fail(ulStartblock > MAX_BLOCKNUMBER && ulStartblock != END_OF_CHAIN);
fail(aulBBD == NULL);
fail(tBBDLen == 0);
/* Find the length of the small block list */
for (tSmallBlockListLen = 0, ulTmp = ulStartblock;
tSmallBlockListLen < tBBDLen && ulTmp != END_OF_CHAIN;
tSmallBlockListLen++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
}
DBG_DEC(tSmallBlockListLen);
if (tSmallBlockListLen == 0) {
/* There is no small block list */
fail(ulStartblock != END_OF_CHAIN);
aulSmallBlockList = NULL;
return TRUE;
}
/* Create the small block list */
tSize = tSmallBlockListLen * sizeof(ULONG);
aulSmallBlockList = xmalloc(tSize);
for (iIndex = 0, ulTmp = ulStartblock;
iIndex < (int)tBBDLen && ulTmp != END_OF_CHAIN;
iIndex++, ulTmp = aulBBD[ulTmp]) {
if (ulTmp >= (ULONG)tBBDLen) {
DBG_DEC(ulTmp);
DBG_DEC(tBBDLen);
werr(1, "The Big Block Depot is damaged");
}
aulSmallBlockList[iIndex] = ulTmp;
NO_DBG_DEC(aulSmallBlockList[iIndex]);
}
return TRUE;
} /* end of bCreateSmallBlockList */
/*
* ulDepotOffset - get the depot offset the block list
*/
ULONG
ulDepotOffset(ULONG ulIndex, size_t tBlockSize)
{
ULONG ulTmp;
size_t tTmp;
fail(ulIndex >= ULONG_MAX / BIG_BLOCK_SIZE);
switch (tBlockSize) {
case BIG_BLOCK_SIZE:
return (ulIndex + 1) * BIG_BLOCK_SIZE;
case SMALL_BLOCK_SIZE:
tTmp = (size_t)(ulIndex / SIZE_RATIO);
ulTmp = ulIndex % SIZE_RATIO;
if (aulSmallBlockList == NULL ||
tTmp >= tSmallBlockListLen) {
DBG_HEX(aulSmallBlockList);
DBG_DEC(tSmallBlockListLen);
DBG_DEC(tTmp);
return 0;
}
return ((aulSmallBlockList[tTmp] + 1) * SIZE_RATIO +
ulTmp) * SMALL_BLOCK_SIZE;
default:
DBG_DEC(tBlockSize);
DBG_FIXME();
return 0;
}
} /* end of ulDepotOffset */
|