home *** CD-ROM | disk | FTP | other *** search
- #ifndef XPKMASTER_SEEK_C
- #define XPKMASTER_SEEK_C
-
- /* Routinesheader
-
- Name: seek.c
- Main: xpkmaster
- Versionstring: $VER: seek.c 1.0 (30.10.1998)
- Author: SDI
- Distribution: Freeware
- Description: Implementation of XpkSeek
-
- 1.0 30.10.98 : first version
- */
-
- #include <exec/memory.h>
- #include <proto/exec.h>
- #include <proto/xpkmaster.h>
- #include "xpkmaster.h"
-
- /* get chunk header and and seek data when necessary */
- XPK_ALLINONE LONG addseek(struct XpkBuffer *xbuf)
- {
- LONG ulen;
- struct SeekDataList *sdl;
-
- if(!(xbuf->xb_Flags & XMF_SEEK))
- return 0;
-
- ulen = xbuf->xb_UCur;
-
- /* check if already included */
- sdl = xbuf->xb_SeekDataList;
- while(sdl && sdl->sdl_Next)
- sdl = sdl->sdl_Next;
- if(sdl && sdl->sdl_Data[sdl->sdl_Used-1].sd_ULen >= ulen)
- return 0; /* already done, so we quit */
- if(!sdl || sdl->sdl_Used == SEEKENTRYNUM)
- {
- struct SeekDataList *sdl2;
- if(!(sdl2 = (struct SeekDataList *)
- AllocMem(sizeof(struct SeekDataList), MEMF_CLEAR|MEMF_PUBLIC)))
- return (xbuf->xb_Result = XPKERR_NOMEM);
- if(!xbuf->xb_SeekDataList)
- xbuf->xb_SeekDataList = sdl2;
- else
- sdl->sdl_Next = sdl2;
- sdl = sdl2;
- }
-
- sdl->sdl_Data[sdl->sdl_Used].sd_FilePos = xbuf->xb_InBufferPos;
- sdl->sdl_Data[sdl->sdl_Used].sd_ULen = ulen;
- sdl->sdl_Data[(sdl->sdl_Used)++].sd_CLen = xbuf->xb_CCur;
-
- #ifdef DEBUG
- DebugRunTime("addseek: added entry (pos %ld, ulen %ld)",
- xbuf->xb_InBufferPos, ulen);
- #endif
-
- return 0;
- }
-
- XPK_ALLINONE void freeseek(struct XpkBuffer *xbuf)
- {
- struct SeekDataList *sdl, *sdl2;
-
- sdl = xbuf->xb_SeekDataList;
- while(sdl)
- {
- sdl2 = sdl->sdl_Next;
- FreeMem(sdl, sizeof(struct SeekDataList));
- sdl = sdl2;
- }
- xbuf->xb_SeekDataList = 0;
- }
-
- LONG doseek(struct XpkBuffer *xbuf, LONG pos)
- {
- LONG ulen, clen;
- XpkChunkHeader *lochdr = &(xbuf->xb_Headers.h_Loc);
- struct SeekDataList *sdl;
-
- if(pos > xbuf->xb_Fib.xf_ULen)
- return XPKERR_BADPARAMS;
-
- if(xbuf->xb_Format == XPKMODE_UPUP)
- {
- xbuf->xb_Flags &= ~XMF_EOF;
-
- if(!(hookread(xbuf, XIO_SEEK, 0, pos - xbuf->xb_InBufferPos)))
- return xbuf->xb_Result;
-
- xbuf->xb_Fib.xf_CCur = xbuf->xb_Fib.xf_UCur = xbuf->xb_InBufferPos;
- xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
- DEFAULTCHUNKSIZE) + XPK_MARGIN;
-
- return 0;
- }
-
- for(sdl = xbuf->xb_SeekDataList; sdl; sdl = sdl->sdl_Next)
- {
- LONG i;
- for(i = 0; i < sdl->sdl_Used; ++i)
- {
- if(sdl->sdl_Data[i].sd_ULen > pos)
- {
- if(!(hookread(xbuf, XIO_SEEK, 0, sdl->sdl_Data[i].sd_FilePos -
- xbuf->xb_Headers.h_LocSize - xbuf->xb_InBufferPos)))
- return xbuf->xb_Result;
- if(!(hookread(xbuf, XIO_READ, lochdr, xbuf->xb_Headers.h_LocSize)))
- return xbuf->xb_Result;
- getUClen(xbuf, &ulen, &clen);
- xbuf->xb_UCur = sdl->sdl_Data[i].sd_ULen - ulen;
- xbuf->xb_CCur = sdl->sdl_Data[i].sd_CLen - clen;
- updatefib(xbuf);
- return (LONG) (pos - xbuf->xb_Fib.xf_UCur);
- }
- }
- }
-
- /* this is called when need a forward seek and we do not have the seek
- entries */
- while(xbuf->xb_UCur <= pos)
- {
- if(lochdr->xch_Word.xchw_Type == XPKCHUNK_END)
- return XPKERR_BADPARAMS;
-
- getUClen(xbuf, &ulen, &clen);
- if(!(hookread(xbuf, XIO_SEEK, 0, ROUNDLONG(clen))))
- return xbuf->xb_Result;
- if(!(hookread(xbuf, XIO_READ, lochdr, xbuf->xb_Headers.h_LocSize)))
- return xbuf->xb_Result;
- if(updatefib(xbuf))
- return xbuf->xb_Result;
- }
- return (LONG) (pos - xbuf->xb_Fib.xf_UCur);
- }
-
- /**************************************************************************
- *
- * XpkSeek() - move around on a compressed file
- *
- */
-
- /* Return codes < 0 are error codes. Codes >= 0 are file position */
- ASM(LONG) LIBXpkSeek(REG(a0, struct XpkBuffer *xbuf), REG(d0, LONG dist),
- REG(d1, LONG mode))
- {
- LONG err = XPKERR_BADPARAMS;
-
- if((xbuf->xb_Format != XPKMODE_UPSTD && xbuf->xb_Format != XPKMODE_UPUP) ||
- (xbuf->xb_SubInfo->xi_Flags & (XPKIF_NOSEEK|XPKIF_PREREADHDR)))
- err = XPKERR_NOFUNC;
- else if(xbuf->xb_Flags & XMF_SEEK)
- {
- switch(mode)
- {
- case XPKSEEK_CURRENT: err = doseek(xbuf, xbuf->xb_Fib.xf_UCur + dist); break;
- case XPKSEEK_BEGINNING: err = doseek(xbuf, dist); break;
- case XPKSEEK_END: err = doseek(xbuf, xbuf->xb_Fib.xf_ULen + dist); break;
- /* default: err = XPKERR_BADPARAMS; break; */
- }
- #ifdef DEBUG
- DebugRunTime("XpkSeek: position after seek (pos %ld, ulen %ld)",
- xbuf->xb_InBufferPos, xbuf->xb_Fib.xf_UCur);
- #endif
- }
-
- return err;
- }
-
- #endif /* XPKMASTER_SEEK_C */
-