//
// C99 winzip crc function, by Scott Duplichan
//
#include <stdio.h>
#include <stdlib.h>

#if defined (_MSC_VER) // Microsoft
typedef unsigned long uint32_t;
typedef signed long int32_t;
typedef unsigned char uint8_t;
#else // standard C
#include <stdint.h>
#endif

//----------------------------------------------------------------------------
//
// winzipcrc - return winzip crc32 of data in buffer
//
static uint32_t winzipcrc(void *buffer, size_t size)
   {
   uint32_t crc = ~0;
   uint8_t  *position = buffer;

   while (size--) 
      {
      int bit;
      crc ^= *position++;
      for (bit = 0; bit < 8; bit++) 
         {
         int32_t out = crc & 1;
         crc >>= 1;
         crc ^= -out & 0xEDB88320;
         }
      }
   return ~crc;
   }

//----------------------------------------------------------------------------
//
// utility to demonstrate winzip crc function
// 
int main (int argc, char *argv [])
   {
   unsigned char  *buffer;
   uint32_t       crc;
   size_t         filelength;
   FILE           *stream;

   if (argc != 2)
      {
      fprintf (stderr, "use winzipcrc <filename>\n");
      return 1;
      }

   stream = fopen (argv [1], "rb");
   if (!stream)
      {
      fprintf (stderr, "failed to open input file %s\n", argv [1]);
      return 2;
      }

   buffer = NULL;
   filelength = 0;
   for (;;)
      {
      int ch = fgetc (stream);
      if (ch == EOF) break;
      buffer = realloc (buffer, filelength + 1);
      if (buffer == NULL) 
         {
         fprintf (stderr, "out of memory\n");
         return 3;
         }
      buffer [filelength++] = ch;
      }

   crc = winzipcrc (buffer, filelength);
   printf ("%s: crc=%lX\n", argv [1], (unsigned long) crc);

   free (buffer);
   fclose (stream);
   return 0;
   }

//----------------------------------------------------------------------------
