home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / KEYMGMT / STREAM.C < prev    next >
C/C++ Source or Header  |  1996-09-27  |  12KB  |  465 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                                The STREAM Class                            *
  4. *                        Copyright Peter Gutmann 1993-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <string.h>
  9. #if defined( INC_ALL ) || defined( INC_CHILD )
  10.   #include "stream.h"
  11. #else
  12.   #include "keymgmt/stream.h"
  13. #endif /* Compiler-specific includes */
  14.  
  15. /****************************************************************************
  16. *                                                                            *
  17. *                                Stream I/O Functions                        *
  18. *                                                                            *
  19. ****************************************************************************/
  20.  
  21. /* Read a byte from a stream */
  22.  
  23. int sgetc( STREAM *stream )
  24.     {
  25.     int ch;
  26.  
  27.     /* If there's a problem with the stream, don't try to do anything */
  28.     if( stream->status != STREAM_OK )
  29.         return( stream->status );
  30.     if( stream->isNull )
  31.         {
  32.         stream->status = STREAM_EMPTY;
  33.         return( STREAM_EMPTY );
  34.         }
  35.  
  36.     /* If we ungot a char, return this */
  37.     if( stream->ungetChar )
  38.         {
  39.         ch = stream->lastChar;
  40.         stream->ungetChar = FALSE;
  41.         return( ch );
  42.         }
  43.  
  44.     /* If it's a memory stream, read the data from the buffer */
  45.     if( stream->bufSize )
  46.         {
  47.         if( stream->bufSize != STREAMSIZE_UNKNOWN && \
  48.             stream->bufPos >= stream->bufEnd )
  49.             {
  50.             stream->status = STREAM_EMPTY;
  51.             return( STREAM_EMPTY );
  52.             }
  53.         return( stream->lastChar = stream->buffer[ stream->bufPos++ ] );
  54.         }
  55.  
  56.     /* It's a file stream, read the data from the file */
  57.     if( ( ch = getc( stream->filePtr ) ) == EOF )
  58.         {
  59.         stream->status = STREAM_READ;
  60.         return( STREAM_READ );
  61.         }
  62.     return( stream->lastChar = ch );
  63.     }
  64.  
  65. /* Write a byte to a stream */
  66.  
  67. int sputc( STREAM *stream, int data )
  68.     {
  69.     register int regData = data;
  70.  
  71.     /* With any luck localData is now in a register, so we can try to destroy
  72.        the copy of the data on the stack.  We do this by assigning a live
  73.        value to it and using it a little later on.  A really good optimizing
  74.        compiler should detect that this is a nop, but with any luck most
  75.        compilers won't */
  76.     data = stream->status;
  77.  
  78.     /* If there's a problem with the stream, don't try to do anything until
  79.        the error is cleared */
  80.     if( data != STREAM_OK )
  81.         return( data );        /* Equal to stream->status, force reuse of data */
  82.  
  83.     /* If it's a null stream, just record the write and return */
  84.     if( stream->isNull )
  85.         {
  86.         stream->bufPos++;
  87.         return( STREAM_OK );
  88.         }
  89.  
  90.     /* If it's a memory stream, deposit the data in the buffer */
  91.     if( stream->bufSize )
  92.         {
  93.         if( stream->bufSize != STREAMSIZE_UNKNOWN && \
  94.             stream->bufPos >= stream->bufSize )
  95.             {
  96.             stream->status = STREAM_FULL;
  97.             return( STREAM_FULL );
  98.             }
  99.         stream->buffer[ stream->bufPos++ ] = regData;
  100.         stream->bufEnd = stream->bufPos;
  101.         return( STREAM_OK );
  102.         }
  103.  
  104.     /* It's a file stream, write the data to the file */
  105.     if( putc( regData, stream->filePtr ) == EOF )
  106.         {
  107.         stream->status = STREAM_WRITE;
  108.         return( STREAM_WRITE );
  109.         }
  110.     return( STREAM_OK );
  111.     }
  112.  
  113. /* Unget a byte from a stream */
  114.  
  115. int sungetc( STREAM *stream )
  116.     {
  117.     stream->ungetChar = TRUE;
  118.     return( STREAM_OK );
  119.     }
  120.  
  121. /* Read a block of data from a stream.  If not enough data is available it
  122.    will fail with STREAM_EMPTY rather than trying to read as much as it
  123.    can, which mirrors the behaviour of most read()/fread() implementations */
  124.  
  125. int sread( STREAM *stream, void *buffer, int length )
  126.     {
  127.     BYTE *bufPtr = buffer;
  128.  
  129.     /* If there's a problem with the stream, don't try to do anything */
  130.     if( stream->status != STREAM_OK )
  131.         return( stream->status );
  132.     if( stream->isNull )
  133.         {
  134.         stream->status = STREAM_EMPTY;
  135.         return( STREAM_EMPTY );
  136.         }
  137.     if( length == 0 )
  138.         return( STREAM_OK );
  139.  
  140.     /* If we ungot a char, return this first */
  141.     if( stream->ungetChar )
  142.         {
  143.         *bufPtr++ = stream->lastChar;
  144.         stream->ungetChar = FALSE;
  145.         if( !--length )
  146.             return( STREAM_OK );
  147.         }
  148.  
  149.     /* If it's a memory stream, read the data from the buffer */
  150.     if( stream->bufSize )
  151.         {
  152.         if( stream->bufSize != STREAMSIZE_UNKNOWN && \
  153.             stream->bufPos + length > stream->bufEnd )
  154.             {
  155.             stream->status = STREAM_EMPTY;
  156.             return( STREAM_EMPTY );
  157.             }
  158.         memcpy( buffer, stream->buffer + stream->bufPos, length );
  159.         stream->bufPos += length;
  160.         return( STREAM_OK );
  161.         }
  162.  
  163.     /* It's a file stream, read the data from the file */
  164.     if( fread( bufPtr, 1, length, stream->filePtr ) != ( size_t ) length )
  165.         {
  166.         stream->status = STREAM_READ;
  167.         return( STREAM_READ );
  168.         }
  169.     return( STREAM_OK );
  170.     }
  171.  
  172. /* Write a block of data from a stream.  If not enough data is available it
  173.    will fail with STREAM_FULL rather than trying to write as much as it
  174.    can, which mirrors the behaviour of most write()/fwrite()
  175.    implementations */
  176.  
  177. int swrite( STREAM *stream, const void *buffer, const int length )
  178.     {
  179.     /* If there's a problem with the stream, don't try to do anything until
  180.        the error is cleared */
  181.     if( stream->status != STREAM_OK )
  182.         return( stream->status );
  183.     if( length == 0 )
  184.         return( STREAM_OK );
  185.  
  186.     /* If it's a null stream, just record the write and return */
  187.     if( stream->isNull )
  188.         {
  189.         stream->bufPos += length;
  190.         return( STREAM_OK );
  191.         }
  192.  
  193.     /* If it's a memory stream, deposit the data in the buffer */
  194.     if( stream->bufSize )
  195.         {
  196.         if( stream->bufSize != STREAMSIZE_UNKNOWN && \
  197.             stream->bufPos + length > stream->bufSize )
  198.             {
  199.             stream->status = STREAM_FULL;
  200.             return( STREAM_FULL );
  201.             }
  202.         memcpy( stream->buffer + stream->bufPos, buffer, length );
  203.         stream->bufEnd += length;
  204.         stream->bufPos += length;
  205.         return( STREAM_OK );
  206.         }
  207.  
  208.     /* It's a file stream, write the data to the file */
  209.     if( fwrite( buffer, 1, length, stream->filePtr ) != ( size_t ) length )
  210.         {
  211.         stream->status = STREAM_WRITE;
  212.         return( STREAM_WRITE );
  213.         }
  214.     return( STREAM_OK );
  215.     }
  216.  
  217. /* Skip a number of bytes in a stream */
  218.  
  219. int sSkip( STREAM *stream, const int length )
  220.     {
  221.     /* If there's a problem with the stream, don't try to do anything */
  222.     if( stream->status != STREAM_OK )
  223.         return( stream->status );
  224.     if( stream->isNull )
  225.         {
  226.         stream->status = STREAM_EMPTY;
  227.         return( STREAM_EMPTY );
  228.         }
  229.     if( length == 0 )
  230.         return( STREAM_OK );
  231.  
  232.     /* If it's a memory stream, move ahead in the buffer */
  233.     if( stream->bufSize )
  234.         {
  235.         if( stream->bufSize != STREAMSIZE_UNKNOWN && \
  236.             stream->bufPos + length > stream->bufEnd )
  237.             {
  238.             stream->status = STREAM_EMPTY;
  239.             return( STREAM_EMPTY );
  240.             }
  241.         stream->bufPos += length;
  242.         return( STREAM_OK );
  243.         }
  244.  
  245.     /* It's a file stream, skip the data in the file */
  246.     if( fseek( stream->filePtr, ( long ) length, SEEK_CUR ) )
  247.         {
  248.         stream->status = STREAM_READ;
  249.         return( STREAM_READ );
  250.         }
  251.     return( STREAM_OK );
  252.     }
  253.  
  254. /****************************************************************************
  255. *                                                                            *
  256. *                            Memory Stream Functions                            *
  257. *                                                                            *
  258. ****************************************************************************/
  259.  
  260. /* Open a memory stream */
  261.  
  262. int sMemOpen( STREAM *stream, void *buffer, const int length )
  263.     {
  264.     /* Make sure all parameters are in order */
  265.     if( stream == NULL || buffer == NULL || \
  266.         ( length < 1 && length != STREAMSIZE_UNKNOWN ) )
  267.         return( STREAM_BADPARAM );
  268.  
  269.     /* Initialise the stream structure */
  270.     memset( stream, 0, sizeof( STREAM ) );
  271.     stream->buffer = buffer;
  272.     stream->bufSize = stream->bufEnd = length;
  273.     if( stream->bufSize != STREAMSIZE_UNKNOWN )
  274.         memset( stream->buffer, 0, stream->bufSize );
  275.  
  276.     return( STREAM_OK );
  277.     }
  278.  
  279. /* Create a null stream to serve as a data sink - this is useful for
  280.    implementing sizeof() functions by writing data to null streams */
  281.  
  282. int sMemNullOpen( STREAM *stream )
  283.     {
  284.     /* Make sure all parameters are in order */
  285.     if( stream == NULL )
  286.         return( STREAM_BADPARAM );
  287.  
  288.     /* Initialise the stream structure */
  289.     memset( stream, 0, sizeof( STREAM ) );
  290.     stream->isNull = TRUE;
  291.  
  292.     return( STREAM_OK );
  293.     }
  294.  
  295. /* Close a memory stream */
  296.  
  297. int sMemClose( STREAM *stream )
  298.     {
  299.     /* Make sure all parameters are in order */
  300.     if( stream == NULL )
  301.         return( STREAM_BADPARAM );
  302.  
  303.     /* Clear the stream structure */
  304.     if( stream->buffer != NULL && stream->bufSize != STREAMSIZE_UNKNOWN )
  305.         zeroise( stream->buffer, stream->bufSize );
  306.     zeroise( stream, sizeof( STREAM ) );
  307.  
  308.     return( STREAM_OK );
  309.     }
  310.  
  311. /* Connect a memory stream without destroying the buffer contents */
  312.  
  313. int sMemConnect( STREAM *stream, void *buffer, const int length )
  314.     {
  315.     /* Make sure all parameters are in order */
  316.     if( stream == NULL || buffer == NULL || \
  317.         ( length < 1 && length != STREAMSIZE_UNKNOWN ) )
  318.         return( STREAM_BADPARAM );
  319.  
  320.     /* Initialise the stream structure */
  321.     memset( stream, 0, sizeof( STREAM ) );
  322.     stream->buffer = buffer;
  323.     stream->bufSize = stream->bufEnd = length;
  324.  
  325.     return( STREAM_OK );
  326.     }
  327.  
  328. /* Disconnect a memory stream without destroying the buffer contents */
  329.  
  330. int sMemDisconnect( STREAM *stream )
  331.     {
  332.     /* Make sure all parameters are in order */
  333.     if( stream == NULL )
  334.         return( STREAM_BADPARAM );
  335.  
  336.     /* Clear the stream structure */
  337.     memset( stream, 0, sizeof( STREAM ) );
  338.  
  339.     return( STREAM_OK );
  340.     }
  341.  
  342. /* Move the read/write pointer to a certain position in the stream */
  343.  
  344. int sMemSeek( STREAM *stream, const size_t position )
  345.     {
  346.     /* Make sure all parameters are in order.  We don't need to check for
  347.        position < 0 because size_t is always unsigned */
  348.     if( stream == NULL || ( stream->bufSize != STREAMSIZE_UNKNOWN && \
  349.                             ( int ) position > stream->bufSize ) )
  350.         return( STREAM_BADPARAM );
  351.  
  352.     /* Set the new R/W position */
  353.     stream->bufPos = ( int ) position;
  354.     return( STREAM_OK );
  355.     }
  356.  
  357. /* Reset the buffer contents to empty */
  358.  
  359. int sMemReset( STREAM *stream )
  360.     {
  361.     /* Make sure all parameters are in order */
  362.     if( stream == NULL )
  363.         return( STREAM_BADPARAM );
  364.  
  365.     /* Reset the buffer information for an empty stream */
  366.     if( stream->buffer != NULL && stream->bufSize != STREAMSIZE_UNKNOWN )
  367.         zeroise( stream->buffer, stream->bufSize );
  368.     stream->bufPos = stream->bufEnd = 0;
  369.  
  370.     return( STREAM_OK );
  371.     }
  372.  
  373. /* Evaluate the size of the stream */
  374.  
  375. int sMemSize( STREAM *stream )
  376.     {
  377.     /* Make sure all parameters are in order */
  378.     if( stream == NULL )
  379.         return( STREAM_BADPARAM );
  380.  
  381.     return( stream->bufPos );
  382.     }
  383.  
  384. /****************************************************************************
  385. *                                                                            *
  386. *                            File Stream Functions                            *
  387. *                                                                            *
  388. ****************************************************************************/
  389.  
  390. /* Open a file stream */
  391.  
  392. int sFileOpen( STREAM *stream, const char *fileName, const char *mode )
  393.     {
  394.     /* Make sure all parameters are in order */
  395.     if( stream == NULL || fileName == NULL || mode == NULL )
  396.         return( STREAM_BADPARAM );
  397.  
  398.     /* Initialise the stream structure */
  399.     memset( stream, 0, sizeof( STREAM ) );
  400.     if( ( stream->filePtr = fopen( fileName, mode ) ) == NULL )
  401.         return( STREAM_OPEN );
  402.  
  403.     return( STREAM_OK );
  404.     }
  405.  
  406. /* Close a file stream */
  407.  
  408. int sFileClose( STREAM *stream )
  409.     {
  410.     /* Make sure all parameters are in order */
  411.     if( stream == NULL )
  412.         return( STREAM_BADPARAM );
  413.  
  414.     /* Close the file and clear the stream structure */
  415.     if( fclose( stream->filePtr ) )
  416.         return( STREAM_CLOSE );
  417.     zeroise( stream, sizeof( STREAM ) );
  418.  
  419.     return( STREAM_OK );
  420.     }
  421.  
  422. /* Connect a file with a stream */
  423.  
  424. int sFileConnect( STREAM *stream, FILE *filePtr )
  425.     {
  426.     /* Make sure all parameters are in order */
  427.     if( stream == NULL || filePtr == NULL )
  428.         return( STREAM_BADPARAM );
  429.  
  430.     /* Initialise the stream structure */
  431.     memset( stream, 0, sizeof( STREAM ) );
  432.     stream->filePtr = filePtr;
  433.  
  434.     return( STREAM_OK );
  435.     }
  436.  
  437. /* Disconnect a file from a stream */
  438.  
  439. int sFileDisconnect( STREAM *stream )
  440.     {
  441.     /* Make sure all parameters are in order */
  442.     if( stream == NULL )
  443.         return( STREAM_BADPARAM );
  444.  
  445.     /* Clear the stream structure */
  446.     zeroise( stream, sizeof( STREAM ) );
  447.  
  448.     return( STREAM_OK );
  449.     }
  450.  
  451. /* Seek to a position in a file stream */
  452.  
  453. int sFileSeek( STREAM *stream, const long position )
  454.     {
  455.     /* Make sure all parameters are in order */
  456.     if( stream == NULL )
  457.         return( STREAM_BADPARAM );
  458.  
  459.     /* Seek to the position in the file */
  460.     if( fseek( stream->filePtr, position, SEEK_SET ) )
  461.         return( STREAM_SEEK );
  462.  
  463.     return( STREAM_OK );
  464.     }
  465.