Esempio n. 1
0
char * ZEXPORT gzgets(gzFile file, char *buf, int len)
{
   unsigned left, n;
   char *str;
   unsigned char *eol;
   gz_statep state;

   /* check parameters and get internal structure */
   if (file == NULL || buf == NULL || len < 1)
      return NULL;
   state = (gz_statep)file;

   /* check that we're reading and that there's no (serious) error */
   if (state->mode != GZ_READ ||
         (state->err != Z_OK && state->err != Z_BUF_ERROR))
      return NULL;

   /* process a skip request */
   if (state->seek) {
      state->seek = 0;
      if (gz_skip(state, state->skip) == -1)
         return NULL;
   }

   /* copy output bytes up to new line or len - 1, whichever comes first --
      append a terminating zero to the string (we don't check for a zero in
      the contents, let the user worry about that) */
   str = buf;
   left = (unsigned)len - 1;
   if (left) do {
      /* assure that something is in the output buffer */
      if (state->x.have == 0 && gz_fetch(state) == -1)
         return NULL;                /* error */
      if (state->x.have == 0) {       /* end of file */
         state->past = 1;            /* read past end */
         break;                      /* return what we have */
      }

      /* look for end-of-line in current output buffer */
      n = state->x.have > left ? left : state->x.have;
      eol = (unsigned char *)memchr(state->x.next, '\n', n);
      if (eol != NULL)
         n = (unsigned)(eol - state->x.next) + 1;

      /* copy through end-of-line, or remainder if not found */
      memcpy(buf, state->x.next, n);
      state->x.have -= n;
      state->x.next += n;
      state->x.pos += n;
      left -= n;
      buf += n;
   } while (left && eol == NULL);

   /* return terminated string, or if nothing, end of file */
   if (buf == str)
      return NULL;
   buf[0] = 0;
   return str;
}
Esempio n. 2
0
/* -- see zlib.h -- */
int ZEXPORT gzungetc(
    int c,
    gzFile file)
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;

    /* check that we're reading and that there's no (serious) error */
    if (state->mode != GZ_READ ||
        (state->err != Z_OK && state->err != Z_BUF_ERROR))
        return -1;

    /* process a skip request */
    if (state->seek) {
        state->seek = 0;
        if (gz_skip(state, state->skip) == -1)
            return -1;
    }

    /* can't push EOF */
    if (c < 0)
        return -1;

    /* if output buffer empty, put byte at end (allows more pushing) */
    if (state->x.have == 0) {
        state->x.have = 1;
        state->x.next = state->out + (state->size << 1) - 1;
        state->x.next[0] = c;
        state->x.pos--;
        state->past = 0;
        return c;
    }

    /* if no room, give up (must have already done a gzungetc()) */
    if (state->x.have == (state->size << 1)) {
        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
        return -1;
    }

    /* slide output data if needed and insert byte before existing data */
    if (state->x.next == state->out) {
        unsigned char *src = state->out + state->x.have;
        unsigned char *dest = state->out + (state->size << 1);
        while (src > state->out)
            *--dest = *--src;
        state->x.next = dest;
    }
    state->x.have++;
    state->x.next--;
    state->x.next[0] = c;
    state->x.pos--;
    state->past = 0;
    return c;
}
Esempio n. 3
0
/* -- see zlib.h -- */
int ZEXPORT
gzread (gzFile file, voidp buf, unsigned len)
{
  unsigned got, n;
  gz_statep state;
  z_streamp strm;

  /* get internal structure */
  if (file == NULL)
    return -1;
  state = (gz_statep) file;
  strm = &(state->strm);

  /* check that we're reading and that there's no (serious) error */
  if (state->mode != GZ_READ ||
      (state->err != Z_OK && state->err != Z_BUF_ERROR))
    return -1;

  /* since an int is returned, make sure len fits in one, otherwise return
     with an error (this avoids the flaw in the interface) */
  if ((int) len < 0)
    {
      gz_error (state, Z_DATA_ERROR, "requested length does not fit in int");
      return -1;
    }

  /* if len is zero, avoid unnecessary operations */
  if (len == 0)
    return 0;

  /* process a skip request */
  if (state->seek)
    {
      state->seek = 0;
      if (gz_skip (state, state->skip) == -1)
	return -1;
    }

  /* get len bytes to buf, or less than len if at the end */
  got = 0;
  do
    {
      /* first just try copying data from the output buffer */
      if (state->x.have)
	{
	  n = state->x.have > len ? len : state->x.have;
	  memcpy (buf, state->x.next, n);
	  state->x.next += n;
	  state->x.have -= n;
	}

      /* output buffer empty -- return if we're at the end of the input */
      else if (state->eof && strm->avail_in == 0)
	{
	  state->past = 1;	/* tried to read past end */
	  break;
	}

      /* need output data -- for small len or new stream load up our output
         buffer */
      else if (state->how == LOOK || len < (state->size << 1))
	{
	  /* get more output, looking for header if required */
	  if (gz_fetch (state) == -1)
	    return -1;
	  continue;		/* no progress yet -- go back to copy above */
	  /* the copy above assures that we will leave with space in the
	     output buffer, allowing at least one gzungetc() to succeed */
	}

      /* large len -- read directly into user buffer */
      else if (state->how == COPY)
	{			/* read directly */
	  if (gz_load (state, (unsigned char *) buf, len, &n) == -1)
	    return -1;
	}

      /* large len -- decompress directly into user buffer */
      else
	{			/* state->how == GZIP */
	  strm->avail_out = len;
	  strm->next_out = (unsigned char *) buf;
	  if (gz_decomp (state) == -1)
	    return -1;
	  n = state->x.have;
	  state->x.have = 0;
	}

      /* update progress */
      len -= n;
      buf = (char *) buf + n;
      got += n;
      state->x.pos += n;
    }
  while (len);

  /* return number of bytes read into user buffer (will fit in int) */
  return (int) got;
}