Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * 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 */