#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gzip.h"

#define ZCHUNK 16384
#define BUFMIN 128
#define BUFCHUNK (1024*128)

int z_readfile(FILE *F,char **buf,size_t *size)
{
 z_stream zs;
 int r;
 unsigned char in[ZCHUNK];
 size_t bufsize;
 void *newbuf;

 memset(&zs,0,sizeof(zs));

 *buf = NULL;
 bufsize=*size=0;

 r=inflateInit2(&zs,47);
 if (r != Z_OK)  return r; 

 do
 {
   zs.avail_in = fread(in, 1, sizeof(in), F);
   if (ferror(F))
   {
     r = Z_ERRNO;
     goto zerr;
   }
   if (!zs.avail_in) break;
   zs.next_in = in;
   do
   {
     if ((bufsize-*size)<BUFMIN)
     {
       bufsize += BUFCHUNK;
       newbuf = *buf ? realloc(*buf,bufsize) : malloc(bufsize);
       if (!newbuf)
       {
         r = Z_MEM_ERROR;
         goto zerr;
       }
       *buf = newbuf;
     }
     zs.avail_out = bufsize - *size;
     zs.next_out = (unsigned char*)(*buf + *size);
     r = inflate(&zs, Z_NO_FLUSH);
     if (r!=Z_OK && r!=Z_STREAM_END) goto zerr;
     *size = bufsize - zs.avail_out;
   } while (r==Z_OK && zs.avail_in);
 } while (r==Z_OK);
 
 if (*size<bufsize)
 {
   // free extra space
   if (newbuf = realloc(*buf,*size)) *buf=newbuf;
 }

 inflateEnd(&zs);
 return Z_OK;

zerr:
 inflateEnd(&zs);
 if (*buf)
 {
   free(*buf);
   *buf = NULL;
 }
 return r;
}

bool is_gzip(FILE* F)
{
 unsigned char magic[2];
 bool b = !fseek(F,0,SEEK_SET) && fread(magic, 1, 2, F)==2 && magic[0]==0x1F && magic[1]==0x8B;
 fseek(F,0,SEEK_SET);
 return b;
}