home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / anwor032.zip / antiword.0.32 / datalist.c < prev    next >
C/C++ Source or Header  |  2000-12-13  |  9KB  |  365 lines

  1. /*
  2.  * datalist.c
  3.  * Copyright (C) 2000 A.J. van Os; Released under GPL
  4.  *
  5.  * Description:
  6.  * Build, read and destroy a list of Word data blocks
  7.  */
  8.  
  9. #include <stdlib.h>
  10. #include <errno.h>
  11. #include "antiword.h"
  12.  
  13. #if defined(__riscos)
  14. #define EIO        42
  15. #endif /* __riscos */
  16.  
  17.  
  18. /*
  19.  * Private structure to hide the way the information
  20.  * is stored from the rest of the program
  21.  */
  22. typedef struct data_mem_tag {
  23.     data_block_type        tInfo;
  24.     struct data_mem_tag    *pNext;
  25. } data_mem_type;
  26.  
  27. /* Variable to describe the start of the data block list */
  28. static data_mem_type    *pAnchor = NULL;
  29. /* Variable needed to read the data block list */
  30. static data_mem_type    *pBlockLast = NULL;
  31. /* Variable needed to read the data block list */
  32. static data_mem_type    *pBlockCurrent = NULL;
  33. static long    lBlockOffset = 0;
  34. static size_t    tByteNext = 0;
  35. /* Last block read */
  36. static unsigned char    aucBlock[BIG_BLOCK_SIZE];
  37.  
  38.  
  39. /*
  40.  * vDestroyDataBlockList - destroy the data block list
  41.  */
  42. void
  43. vDestroyDataBlockList(void)
  44. {
  45.     data_mem_type    *pCurr, *pNext;
  46.  
  47.     DBG_MSG("vDestroyDataBlockList");
  48.  
  49.     pCurr = pAnchor;
  50.     while (pCurr != NULL) {
  51.         pNext = pCurr->pNext;
  52.         pCurr = xfree(pCurr);
  53.         pCurr = pNext;
  54.     }
  55.     pAnchor = NULL;
  56.     /* Reset all the control variables */
  57.     pBlockLast = NULL;
  58.     pBlockCurrent = NULL;
  59.     lBlockOffset = 0;
  60.     tByteNext = 0;
  61. } /* end of vDestroyDataBlockList */
  62.  
  63. /*
  64.  * bAdd2DataBlockList - add an element to the data block list
  65.  *
  66.  * Returns TRUE when successful, otherwise FALSE
  67.  */
  68. BOOL
  69. bAdd2DataBlockList(data_block_type *pDataBlock)
  70. {
  71.     data_mem_type    *pListMember;
  72.  
  73.     fail(pDataBlock == NULL);
  74.     fail(pDataBlock->lFileOffset < 0);
  75.     fail(pDataBlock->lDataOffset < 0);
  76.     fail(pDataBlock->lLength <= 0);
  77.  
  78.     NO_DBG_MSG("bAdd2DataBlockList");
  79.     NO_DBG_HEX(pDataBlock->lFileOffset);
  80.     NO_DBG_HEX(pDataBlock->lDataOffset);
  81.     NO_DBG_HEX(pDataBlock->lLength);
  82.  
  83.     if (pDataBlock->lFileOffset < 0 ||
  84.         pDataBlock->lDataOffset < 0 ||
  85.         pDataBlock->lLength <= 0) {
  86.         werr(0, "Software (datablock) error");
  87.         return FALSE;
  88.     }
  89.     /* Check for continuous blocks */
  90.     if (pBlockLast != NULL &&
  91.         pBlockLast->tInfo.lFileOffset +
  92.          pBlockLast->tInfo.lLength == pDataBlock->lFileOffset &&
  93.         pBlockLast->tInfo.lDataOffset +
  94.          pBlockLast->tInfo.lLength == pDataBlock->lDataOffset) {
  95.         /* These are continous blocks */
  96.         pBlockLast->tInfo.lLength += pDataBlock->lLength;
  97.         return TRUE;
  98.     }
  99.     /* Make a new block */
  100.     pListMember = xmalloc(sizeof(data_mem_type));
  101.     /* Add the block to the data list */
  102.     pListMember->tInfo = *pDataBlock;
  103.     pListMember->pNext = NULL;
  104.     if (pAnchor == NULL) {
  105.         pAnchor = pListMember;
  106.     } else {
  107.         fail(pBlockLast == NULL);
  108.         pBlockLast->pNext = pListMember;
  109.     }
  110.     pBlockLast = pListMember;
  111.     return TRUE;
  112. } /* end of bAdd2DataBlockList */
  113.  
  114. /*
  115.  * bSetDataOffset - set the offset in the data block list
  116.  *
  117.  * Make the given fileofset the current position in the data block list
  118.  */
  119. BOOL
  120. bSetDataOffset(FILE *pFile, long lFileOffset)
  121. {
  122.     data_mem_type    *pCurr;
  123.     size_t    tReadLen;
  124.  
  125.     DBG_HEX(lFileOffset);
  126.  
  127.     for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
  128.         if (lFileOffset < pCurr->tInfo.lFileOffset ||
  129.             lFileOffset >= pCurr->tInfo.lFileOffset +
  130.              pCurr->tInfo.lLength) {
  131.             /* The file offset is not in this block */
  132.             continue;
  133.         }
  134.         /* Compute the maximum number of bytes to read */
  135.         tReadLen = (size_t)(pCurr->tInfo.lFileOffset +
  136.                 pCurr->tInfo.lLength -
  137.                 lFileOffset);
  138.         /* Compute the real number of bytes to read */
  139.         if (tReadLen > sizeof(aucBlock)) {
  140.             tReadLen = sizeof(aucBlock);
  141.         }
  142.         /* Read the bytes */
  143.         if (!bReadBytes(aucBlock, tReadLen, lFileOffset, pFile)) {
  144.             return FALSE;
  145.         }
  146.         /* Set the control variables */
  147.         pBlockCurrent = pCurr;
  148.         lBlockOffset = lFileOffset - pCurr->tInfo.lFileOffset;
  149.         tByteNext = 0;
  150.         return TRUE;
  151.     }
  152.     return FALSE;
  153. } /* end of bSetDataOffset */
  154.  
  155. /*
  156.  * iNextByte - get the next byte from the data block list
  157.  */
  158. int
  159. iNextByte(FILE *pFile)
  160. {
  161.     long    lReadOff;
  162.     size_t    tReadLen;
  163.  
  164.     fail(pBlockCurrent == NULL);
  165.  
  166.     if (tByteNext >= sizeof(aucBlock) ||
  167.         lBlockOffset + (long)tByteNext >= pBlockCurrent->tInfo.lLength) {
  168.         if (lBlockOffset + (long)sizeof(aucBlock) <
  169.                     pBlockCurrent->tInfo.lLength) {
  170.             /* Same block, next part */
  171.             lBlockOffset += (long)sizeof(aucBlock);
  172.         } else {
  173.             /* Next block, first part */
  174.             pBlockCurrent = pBlockCurrent->pNext;
  175.             lBlockOffset = 0;
  176.         }
  177.         if (pBlockCurrent == NULL) {
  178.             /* Past the last part of the last block */
  179.             errno = EIO;
  180.             return EOF;
  181.         }
  182.         tReadLen = (size_t)
  183.                 (pBlockCurrent->tInfo.lLength - lBlockOffset);
  184.         if (tReadLen > sizeof(aucBlock)) {
  185.             tReadLen = sizeof(aucBlock);
  186.         }
  187.         lReadOff = pBlockCurrent->tInfo.lFileOffset + lBlockOffset;
  188.         if (!bReadBytes(aucBlock, tReadLen, lReadOff, pFile)) {
  189.             errno = EIO;
  190.             return EOF;
  191.         }
  192.         tByteNext = 0;
  193.     }
  194.     return (int)aucBlock[tByteNext++];
  195. } /* end of iNextByte */
  196.  
  197. /*
  198.  * usNextWord - get the next word from the data block list
  199.  *
  200.  * Read a two byte value in Little Endian order, that means MSB last
  201.  *
  202.  * All return values can be valid so errno is set in case of error
  203.  */
  204. unsigned short
  205. usNextWord(FILE *pFile)
  206. {
  207.     unsigned short    usLSB, usMSB;
  208.  
  209.     usLSB = (unsigned short)iNextByte(pFile);
  210.     if (usLSB == (unsigned short)EOF) {
  211.         errno = EIO;
  212.         return (unsigned short)EOF;
  213.     }
  214.     usMSB = (unsigned short)iNextByte(pFile);
  215.     if (usMSB == (unsigned short)EOF) {
  216.         DBG_MSG("usNextWord: Unexpected EOF");
  217.         errno = EIO;
  218.         return (unsigned short)EOF;
  219.     }
  220.     return (usMSB << 8) | usLSB;
  221. } /* end of usNextWord */
  222.  
  223. /*
  224.  * ulNextLong - get the next long from the data block list
  225.  *
  226.  * Read a four byte value in Little Endian order, that means MSW last
  227.  *
  228.  * All return values can be valid so errno is set in case of error
  229.  */
  230. unsigned long
  231. ulNextLong(FILE *pFile)
  232. {
  233.     unsigned long    ulLSW, ulMSW;
  234.  
  235.     ulLSW = usNextWord(pFile);
  236.     if (ulLSW == (unsigned long)EOF) {
  237.         errno = EIO;
  238.         return (unsigned long)EOF;
  239.     }
  240.     ulMSW = usNextWord(pFile);
  241.     if (ulMSW == (unsigned long)EOF) {
  242.         DBG_MSG("ulNextLong: Unexpected EOF");
  243.         errno = EIO;
  244.         return (unsigned long)EOF;
  245.     }
  246.     return (ulMSW << 16) | ulLSW;
  247. } /* end of ulNextLong */
  248.  
  249. /*
  250.  * usNextWordBE - get the next two byte value
  251.  *
  252.  * Read a two byte value in Big Endian order, that means MSB first
  253.  *
  254.  * All return values can be valid so errno is set in case of error
  255.  */
  256. unsigned short
  257. usNextWordBE(FILE *pFile)
  258. {
  259.     unsigned short usLSB, usMSB;
  260.  
  261.     usMSB = (unsigned short)iNextByte(pFile);
  262.     if (usMSB == (unsigned short)EOF) {
  263.         errno = EIO;
  264.         return (unsigned short)EOF;
  265.     }
  266.     usLSB = (unsigned short)iNextByte(pFile);
  267.     if (usLSB == (unsigned short)EOF) {
  268.         DBG_MSG("usNextWordBE: Unexpected EOF");
  269.         errno = EIO;
  270.         return (unsigned short)EOF;
  271.     }
  272.     return (usMSB << 8) | usLSB;
  273. } /* end of usNextWordBE */
  274.  
  275. /*
  276.  * ulNextLongBE - get the next four byte value
  277.  *
  278.  * Read a four byte value in Big Endian order, that means MSW first
  279.  *
  280.  * All return values can be valid so errno is set in case of error
  281.  */
  282. unsigned long
  283. ulNextLongBE(FILE *pFile)
  284. {
  285.     unsigned long ulLSW, ulMSW;
  286.  
  287.     ulMSW = usNextWordBE(pFile);
  288.     if (ulMSW == (unsigned long)EOF) {
  289.         errno = EIO;
  290.         return (unsigned long)EOF;
  291.     }
  292.     ulLSW = usNextWordBE(pFile);
  293.     if (ulLSW == (unsigned long)EOF) {
  294.         DBG_MSG("ulNextLongBE: Unexpected EOF");
  295.         errno = EIO;
  296.         return (unsigned long)EOF;
  297.     }
  298.     return (ulMSW << 16) | ulLSW;
  299. } /* end of ulNextLongBE */
  300.  
  301. /*
  302.  * iSkipBytes - skip over the given number of bytes
  303.  *
  304.  * Returns the number of skipped bytes
  305.  */
  306. int
  307. iSkipBytes(FILE *pFile, size_t tToSkip)
  308. {
  309.     size_t    tToGo, tMaxMove, tMove;
  310.  
  311.     fail(pFile == NULL);
  312.     fail(pBlockCurrent == NULL);
  313.  
  314.     tToGo = tToSkip;
  315.     while (tToGo != 0) {
  316.         /* Goto the end of the current block */
  317.         tMaxMove = min(sizeof(aucBlock) -
  318.                 tByteNext,
  319.                 (size_t)(pBlockCurrent->tInfo.lLength -
  320.                 lBlockOffset -
  321.                 (long)tByteNext));
  322.         tMove = min(tMaxMove, tToGo);
  323.         tByteNext += tMove;
  324.         tToGo -= tMove;
  325.         if (tToGo != 0) {
  326.             /* Goto the next block */
  327.             if (iNextByte(pFile) == EOF) {
  328.                 return (int)(tToSkip - tToGo);
  329.             }
  330.             tToGo--;
  331.         }
  332.     }
  333.     return (int)tToSkip;
  334. } /* end of iSkipBytes */
  335.  
  336. /*
  337.  * Translate the start from the begin of the data to an offset in the file.
  338.  *
  339.  * Returns:     -1: in case of error
  340.  *        >=0: the computed file offset
  341.  */
  342. long
  343. lDataOffset2FileOffset(long lDataOffset)
  344. {
  345.     data_mem_type    *pCurr;
  346.  
  347.     fail(lDataOffset < 0);
  348.  
  349.     for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
  350.         if (lDataOffset < pCurr->tInfo.lDataOffset ||
  351.             lDataOffset >= pCurr->tInfo.lDataOffset +
  352.              pCurr->tInfo.lLength) {
  353.             /* The data offset is not in this block, try the next */
  354.             continue;
  355.         }
  356.         /* The data offset is in the current block */
  357.         return pCurr->tInfo.lFileOffset +
  358.                 lDataOffset -
  359.                 pCurr->tInfo.lDataOffset;
  360.     }
  361.     /* Passed beyond the end of the list */
  362.     DBG_HEX_C(lDataOffset != 0, lDataOffset);
  363.     return -1;
  364. } /* end of lDataOffset2FileOffset */
  365.