home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / c / AsyncIO.lha / AsyncIO / src / ReadLineAsync.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-20  |  2.3 KB  |  114 lines

  1. #include "async.h"
  2.  
  3. #ifndef MIN
  4. #define MIN(a,b) ( ( a ) < ( b ) ? ( a ) : ( b ) )
  5. #endif
  6.  
  7.  
  8. _ASM _ARGS LONG
  9. ReadLineAsync( _REG( a0 ) AsyncFile *file, _REG( a1 ) STRPTR buffer, _REG( d0 ) LONG bufSize )
  10. {
  11.     /* Optimizations... Perhaps I should leave that for the compiler? :) */
  12.     LONG    ch,         /* Read char */
  13.         left,        /* Bytes left in user buffer */
  14.         bytesLeft;    /* Bytes left in asyncio buffer */
  15.     UBYTE    *offset,    /* Buffer with unread data */
  16.         sch;        /* Dummy read buffer */
  17.  
  18.     left = bufSize;
  19.     bytesLeft = file->af_BytesLeft;
  20.     offset = file->af_Offset;
  21.  
  22.     /* I find this implementation rather messy, but I don't
  23.      * really know how to improve the readability while keeping
  24.      * it (small and) fast! I do _not_ want to call
  25.      * ReadCharAsync() for each char... ;)
  26.      */
  27.  
  28.     do
  29.     {
  30.         /* Empty read buffer? */
  31.         if( !bytesLeft )
  32.         {
  33.             /* Yep, refill it. af_Offset doesn't need to be set. */
  34.             file->af_BytesLeft = 0;
  35.  
  36.             if( !( ch = ReadAsync( file, &sch, 1 ) ) )
  37.             {
  38.                 break;    /* EOF */
  39.             }
  40.  
  41.             /* Reset variables. -+1 to "undo" the above read.
  42.              * That way we don't need to handle the char
  43.              * just read here.
  44.              */
  45.             offset = file->af_Offset - 1;
  46.             bytesLeft = file->af_BytesLeft + 1;
  47.         }
  48.         else
  49.         {
  50.             if( left )
  51.             {
  52.                 /* There is space left in the user buffer, so
  53.                  * copy as much as we can to it.
  54.                  */
  55.                 LONG    i, j;
  56.  
  57.                 i = j = MIN( bytesLeft, left );
  58.  
  59.                 /* Copy string to buffer */
  60.                 do
  61.                 {
  62.                     ch = *buffer++ = *offset++;
  63.                     --i;
  64.                 } while( i && ( ch != '\n' ) );
  65.  
  66.                 i = j - i;    /* Number of bytes copied */
  67.                 bytesLeft -= i;    /* Want to keep these out of */
  68.                 left -= i;    /* the while loop above... */
  69.             }
  70.             else
  71.             {
  72.                 /* Skip to EOL */
  73.                 do
  74.                 {
  75.                     ch = *offset++;
  76.                 } while( --bytesLeft && ( ch != '\n' ) );
  77.             }
  78.         }
  79.     } while( ch != '\n' );
  80.  
  81.     /* Restore AsyncIO variables.. */
  82.     file->af_BytesLeft = bytesLeft;
  83.     file->af_Offset = offset;
  84.  
  85.     /* Truncate buffer correctly */
  86.     if( !left )
  87.     {
  88.         /* Buffer is full, so overwrite last byte with terminating null */
  89.         --buffer;
  90.  
  91.         /* Don't include NULL in return count */
  92.         ++left;
  93.  
  94.         if( ch == '\n' )
  95.         {
  96.             /* LF must be the last char in the string */
  97.             *( buffer - 1 ) = ch;
  98.         }
  99.     }
  100.  
  101.     *buffer = 0;
  102.  
  103.     if( ch == -1 )
  104.     {
  105.         /* Return error */
  106.         return( -1 );
  107.     }
  108.     else
  109.     {
  110.         /* Return number of bytes read into buffer */
  111.         return( bufSize - left );
  112.     }
  113. }
  114.