home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / fileutil / scan.lha / src / asyncread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-21  |  11.7 KB  |  303 lines

  1. /*
  2.  *  xfi = xfropen(name,num)
  3.  *   n  = xfrread(xfi)
  4.  *  err = xfrclose(xfi)
  5.  *
  6.  *  RESTRICTIONS:   NO seeking.
  7.  *
  8.  *  Three buffers are used. When the 2nd buffer is 1st accessed,
  9.  *  an asynchronous read is started on the 3rd. The buffers cycle.
  10.  *  If the file has an .lzh extension, it is decompressed 1 buffer
  11.  *  at a time.
  12.  */
  13.  
  14. #include <exec/types.h>
  15. #include <libraries/dosextens.h>
  16. #include <exec/memory.h>
  17. #include "scan.h"
  18.  
  19. extern void *AllocMem();
  20. extern FH *Open();
  21. extern void *malloc(), *FindTask();
  22. extern long FillBufWithLZH();
  23. extern long WinSiz;  /* Size of each buffer */
  24. extern char EOBK;    /* Ptr 2 End of buf keywrd 2b put after last wrd in buf */
  25. extern char *BufIdx; /* Ptr 2 buffer user should start using after open/read */
  26.                      /* Note that this is modified at each buffer switch.    */
  27. extern char *EOCB;   /* Ptr 2 End+1 of buf that user is currently reading.   */
  28.                      /* Note that this is modified at each buffer switch.    */
  29. extern char *SOCB;   /* Ptr 2 Strt of buf user is currently reading from     */
  30.                      /* Note that this is modified at each buffer switch.    */
  31. extern XFI *FHandle;
  32. extern int KeyWrdOvlp;
  33. extern int OpenNew;  /* Set to 1 if finished with internal LZH archive file. */
  34. extern int LON;
  35. extern int EnableLZHDecomp;
  36. int FrstAsyncRd;
  37. char *filenm;
  38. char *TmpPtr;
  39. int flen;
  40. int ItsALZH;
  41. int FrstRd;
  42.  
  43. void *
  44. xfropen(file,num)
  45. char *file;
  46. long *num;
  47.  
  48. {
  49.     extern long xfrread();
  50.     XFI *xfi;
  51.     FHandle = AllocMem((ULONG)sizeof(XFI), MEMF_CLEAR | MEMF_PUBLIC);
  52.     xfi = FHandle; /* needed for abort/cleanup routine */
  53.     flen = strlen(file) - 1;
  54.     filenm = file;
  55.     ItsALZH = 0;
  56.     if( EnableLZHDecomp ) {
  57.        if( tolower( file[ flen--] ) == 'h' && tolower( file[ flen--] == 'z') &&
  58.            tolower( file[ flen--] ) == 'l' && file[ flen] == '.') ItsALZH = 1;
  59.        flen = strlen(file) - 1;
  60.        if( tolower( file[ flen--] ) == 'a' && tolower( file[ flen--] == 'h') &&
  61.            tolower( file[ flen--] ) == 'l' && file[ flen] == '.') ItsALZH = 1;
  62.     }
  63.     if( ItsALZH ) {
  64.        /* Allocate all 3 buffers with spare for buffer switch */
  65.        xfi->asbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
  66.        xfi->usbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
  67.        xfi->zsbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
  68.        /* Put end of buffer keyword before strt of 1st buffer to prevent */
  69.        /* backing up before data is valid.                               */
  70.        strncpy(xfi->asbuf - 4, &EOBK, 3);
  71.        /* Put newline char right before 1st char of 1st buffer to allow  */
  72.        /* matching article separtor with newline as it's 1st char.       */
  73.        strncpy(xfi->asbuf - 1, "\n", 1);
  74.        /* 0 <= x != buffer size -> end of file                               */
  75.        /* 0 <= x <= buffer size -> x = # of bytes read into buf              */
  76.        /*      x >  buffer size -> # of bytes read into buffer = buf size    */
  77.        /* 0 >  x                -> end of archive                            */
  78.        /* if no file matches the pattern a 0 is returned.                    */
  79.        /* if there are no more files in the archive to test, a -1 is returnd */
  80.        *num = FillBufWithLZH( file, xfi->asbuf);
  81.        OpenNew = 0;
  82.        if( *num >= 0 && *num != WinSiz ) {
  83.           if( *num > WinSiz ) *num = WinSiz;
  84.           OpenNew = 1; /* dont open new internal file in LHA/LZH archive */
  85.        }
  86.        FrstRd = 0;
  87.        LON = 1; /* set so we bypass closing archive */
  88.        if( *num < 0 ) {
  89.           *num = 0;
  90.           LON = 0;
  91.           OpenNew = 1;
  92.        }
  93.        strncpy( xfi->asbuf + *num, &EOBK , 3);
  94.        BufIdx = xfi->asbuf;
  95.        TmpPtr = xfi->asbuf;
  96.        SOCB = TmpPtr;               /* Pointer to start of current buffer */
  97.        EOCB = TmpPtr + *num;        /* Pointer to last byte in buffer + 1 */
  98.        xfi->asbuf = xfi->usbuf;     /* swap buffs */
  99.        xfi->usbuf = xfi->zsbuf;
  100.        xfi->zsbuf = TmpPtr;
  101.        Chk_Abort();
  102.     }
  103.     else {
  104.        OpenNew = 0;
  105.        LON = 0;
  106.        xfi->fh = Open(file, 1005);
  107.        if (xfi->fh) {
  108.           xfi->fh = (FH *)((long)xfi->fh << 2);
  109.           /* Allocate all 3 buffers with spare for buffer switch */
  110.           xfi->asbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
  111.           xfi->usbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
  112.           xfi->zsbuf = (char *)malloc(WinSiz + OVERLAP + 4) + OVERLAP;
  113.           /* Copy end of buffer indicator to end of each of the 3 buffers   */
  114.           strncpy(xfi->asbuf + WinSiz, &EOBK, 3);
  115.           strncpy(xfi->usbuf + WinSiz, &EOBK, 3);
  116.           strncpy(xfi->zsbuf + WinSiz, &EOBK, 3);
  117.           /* Put end of buffer keyword before strt of 1st buffer to prevent */
  118.           /* backing up before data is valid.                               */
  119.           strncpy(xfi->asbuf - 4, &EOBK, 3);
  120.           /* Put newline char right before 1st char of 1st buffer to allow  */
  121.           /* matching article separtor with newline as it's 1st char.       */
  122.           strncpy(xfi->asbuf - 1, "\n", 1);
  123.           FrstAsyncRd = 1;
  124.           /* Initialize reply port */
  125.           xfi->rp.mp_Node.ln_Type = NT_MSGPORT;
  126.           xfi->rp.mp_Node.ln_Name = "Async";
  127.           xfi->rp.mp_Flags = PA_SIGNAL;
  128.           xfi->rp.mp_SigBit = AllocSignal(-1);
  129.           if( xfi->rp.mp_SigBit == -1 ) ErrP("Could not allocate signal\n");
  130.           xfi->rp.mp_SigTask = FindTask(NULL);
  131.           NewList(&(xfi->rp.mp_MsgList));        /* Create a new list header */
  132.           /* Fill up 1st buffer and start the read for the 2nd */
  133.           SOCB = NULL;
  134.           EOCB = NULL;
  135.           Chk_Abort();
  136.           xfstartasync(xfi); /* Read into asbuf */
  137.           Chk_Abort();
  138.           *num = xfrread(xfi); /* Wait 4 prev read & then strt rd into usbuf */
  139.           Chk_Abort();
  140.        }
  141.        else {
  142.           FreeMem(FHandle,(ULONG)sizeof(XFI));
  143.           FHandle = 0;
  144.           xfi = NULL;
  145.        }
  146.     }
  147.     return(xfi);
  148. }
  149.  
  150. xfrclose(xfi)
  151. XFI *xfi;
  152. {
  153.     extern long *afp;
  154.     int err = 1;
  155.     if (xfi) {
  156.        if( ItsALZH ) {
  157.           err = 0;
  158.           if( afp != NULL ) { fclose( afp ); afp = NULL; }
  159.           if( xfi->asbuf != NULL ) free( xfi->asbuf - OVERLAP);
  160.           xfi->asbuf = NULL;
  161.           if( xfi->usbuf != NULL ) free( xfi->usbuf - OVERLAP);
  162.           xfi->usbuf = NULL;
  163.           if( xfi->zsbuf != NULL ) free( xfi->zsbuf - OVERLAP);
  164.           xfi->zsbuf = NULL;
  165.           FreeMem(xfi,(ULONG)sizeof(XFI));
  166.           FHandle = 0;
  167.        }
  168.        else {
  169.           if (xfi->pend) {
  170.              /* Wait for pending read to complete */
  171.              xfi->pend = 0;
  172.              WaitPort (&xfi->rp);
  173.              GetMsg   (&xfi->rp);
  174.           }
  175.           err = xfi->err;
  176.           if( xfi->fh != NULL ) Close((long)xfi->fh >> 2);
  177.           if( xfi->asbuf != NULL ) free( xfi->asbuf - OVERLAP);
  178.           xfi->asbuf = NULL;
  179.           if( xfi->usbuf != NULL ) free( xfi->usbuf - OVERLAP);
  180.           xfi->usbuf = NULL;
  181.           if( xfi->zsbuf != NULL ) free( xfi->zsbuf - OVERLAP);
  182.           xfi->zsbuf = NULL;
  183.           if( xfi->rp.mp_SigBit > 0 ) FreeSignal(xfi->rp.mp_SigBit);
  184.           xfi->rp.mp_SigBit = 0;
  185.           FreeMem(xfi,(ULONG)sizeof(XFI));
  186.           FHandle = 0;
  187.        }
  188.     }
  189.     return(err);
  190. }
  191.  
  192. /* Called to make sure a previous read is complete before swapping buffers */
  193. /* and then starting another async read.                                   */
  194.  
  195. long xfrread(xfi)
  196. XFI *xfi;
  197. {
  198.    long NumRead;
  199.    if( ItsALZH ) {
  200.       /* 0 <= x != buffer size -> end of file                               */
  201.       /* 0 <= x <= buffer size -> x = # of bytes read into buf              */
  202.       /*      x >  buffer size -> # of bytes read into buffer = buf size    */
  203.       /* 0 >  x                -> end of archive                            */
  204.       /* If an internal file name does not match the pattern, 0 is returned.*/
  205.       /* If there are no more internal files, -1 is returned.               */
  206.       if( !OpenNew ) {
  207.          if( FrstRd ) {
  208.             FrstRd = 0;
  209.             /* Put end of buffer keyword before strt of 1st buffer to prevent*/
  210.             /* backing up before data is valid.                              */
  211.             strncpy(xfi->asbuf - 4, &EOBK, 3);
  212.             /* Put newline char right before 1st char of 1st buffer to allow */
  213.             /* matching article separtor with newline as it's 1st char.      */
  214.             strncpy(xfi->asbuf - 1, "\n", 1);
  215.             BufIdx = xfi->asbuf;           /* Init pntr 2 new user workspace */
  216.          }
  217.          else {
  218.             /* if last read did not get an EOF, provide buffer overlap       */
  219.             memcpy(xfi->asbuf - OVERLAP,xfi->zsbuf + WinSiz - OVERLAP,OVERLAP);
  220.             BufIdx = xfi->asbuf - KeyWrdOvlp; /* Init pntr 2 new user wrkspc */
  221.          }
  222.          NumRead = FillBufWithLZH( filenm, xfi->asbuf);
  223.          OpenNew = 0;
  224.          if( NumRead >= 0 && NumRead != WinSiz ) { /* if EOF */
  225.             if( NumRead > WinSiz ) NumRead = WinSiz;
  226.             OpenNew = 1; /* finished with internal LZH/LHA archive file */
  227.          }
  228.          strncpy(xfi->asbuf + NumRead, &EOBK , 3);
  229.          if( NumRead < 0 ) LON = 0;
  230.       }
  231.       else { /* Comes here on xfrread after the last xfrread with >=0 retrnd.*/
  232.          /* Return -1 so EOF processing will be done.                        */
  233.          FrstRd = 1;
  234.          NumRead = -1;
  235.          OpenNew = 0;
  236.          BufIdx = xfi->asbuf;           /* Init pntr 2 new user workspace */
  237.          strncpy(xfi->asbuf, &EOBK , 3);
  238.       }
  239.       TmpPtr = xfi->asbuf;
  240.       SOCB = TmpPtr;               /* Pointer to start of current buffer */
  241.       EOCB = TmpPtr + NumRead;     /* Pointer to last byte in buffer + 1 */
  242.       xfi->asbuf = xfi->usbuf;     /* swap buffs */
  243.       xfi->usbuf = xfi->zsbuf;
  244.       xfi->zsbuf = TmpPtr;
  245.       Chk_Abort();
  246.    }
  247.    else {
  248.       if (xfi->pend != 0) {        /* if pending read has not finished */
  249.           WaitPort (&xfi->rp);     /* Wait for it */
  250.           GetMsg   (&xfi->rp);
  251.           xfi->pend = 0;
  252.       }
  253.       /* Copy last OVERLAP bytes of currently used buf to start of next buf */
  254.       if (!FrstAsyncRd)
  255.          memcpy(xfi->asbuf - OVERLAP, xfi->zsbuf + WinSiz - OVERLAP, OVERLAP);
  256.       if ((NumRead = xfi->sp.sp_Pkt.dp_Res1) <= 0) {              /* EOF    */
  257.          return(0);
  258.       }
  259.       /* Last read may not completely fill the buffer */
  260.       if ( NumRead < WinSiz ) {
  261.          /* copy end of buffer keyword after last byte in buffer */
  262.          /* No need to worry about overwriting EOB keyword after buffer */
  263.          /* because it is not needed anymore. The next file opened will */
  264.          /* call xfropen which will reinitialize the EOB's.             */
  265.          strncpy(xfi->asbuf + NumRead, &EOBK , 3);
  266.       }
  267.       /* On 1st read, start at 1st data read, on next reads, start a         */
  268.       /* little before data just read in to handle keywords spanning buffers */
  269.       if (FrstAsyncRd) {
  270.          BufIdx = xfi->asbuf;
  271.          FrstAsyncRd = 0;
  272.       }
  273.       else {
  274.          BufIdx = xfi->asbuf - KeyWrdOvlp; /* Init pntr 2 new user workspace */
  275.       }
  276.       TmpPtr = xfi->asbuf;
  277.       SOCB = TmpPtr;               /* Pointer to start of current buffer */
  278.       EOCB = TmpPtr + NumRead;     /* Pointer to last byte in buffer + 1 */
  279.       xfi->asbuf = xfi->usbuf;     /* swap buffs */
  280.       xfi->usbuf = xfi->zsbuf;
  281.       xfi->zsbuf = TmpPtr;
  282.       Chk_Abort();
  283.       xfstartasync(xfi);           /* new async read */
  284.    }
  285.    return(NumRead);
  286. }
  287.  
  288. static
  289. xfstartasync(xfi)
  290. XFI *xfi;
  291. {
  292.     xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt);
  293.     xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg);
  294.     xfi->sp.sp_Pkt.dp_Port = &xfi->rp;
  295.     xfi->sp.sp_Pkt.dp_Type = ACTION_READ;
  296.     xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1;
  297.     xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf;
  298.     xfi->sp.sp_Pkt.dp_Arg3 = WinSiz;
  299.     PutMsg (xfi->fh->fh_Type, &xfi->sp);
  300.     xfi->pend = 1;
  301. }
  302.  
  303.