Read len bytes into buf from file, or less than len up to the end of the input. Return the number of bytes read. If zero is returned, either the end of file was reached, or there was an error. state->err must be consulted in that case to determine which. */
(state, buf, len)
| 295 | end of file was reached, or there was an error. state->err must be |
| 296 | consulted in that case to determine which. */ |
| 297 | local z_size_t gz_read(state, buf, len) |
| 298 | gz_statep state; |
| 299 | voidp buf; |
| 300 | z_size_t len; |
| 301 | { |
| 302 | z_size_t got; |
| 303 | unsigned n; |
| 304 | |
| 305 | /* if len is zero, avoid unnecessary operations */ |
| 306 | if (len == 0) |
| 307 | return 0; |
| 308 | |
| 309 | /* process a skip request */ |
| 310 | if (state->seek) { |
| 311 | state->seek = 0; |
| 312 | if (gz_skip(state, state->skip) == -1) |
| 313 | return 0; |
| 314 | } |
| 315 | |
| 316 | /* get len bytes to buf, or less than len if at the end */ |
| 317 | got = 0; |
| 318 | do { |
| 319 | /* set n to the maximum amount of len that fits in an unsigned int */ |
| 320 | n = -1; |
| 321 | if (n > len) |
| 322 | n = len; |
| 323 | |
| 324 | /* first just try copying data from the output buffer */ |
| 325 | if (state->x.have) { |
| 326 | if (state->x.have < n) |
| 327 | n = state->x.have; |
| 328 | memcpy(buf, state->x.next, n); |
| 329 | state->x.next += n; |
| 330 | state->x.have -= n; |
| 331 | } |
| 332 | |
| 333 | /* output buffer empty -- return if we're at the end of the input */ |
| 334 | else if (state->eof && state->strm.avail_in == 0) { |
| 335 | state->past = 1; /* tried to read past end */ |
| 336 | break; |
| 337 | } |
| 338 | |
| 339 | /* need output data -- for small len or new stream load up our output |
| 340 | buffer */ |
| 341 | else if (state->how == LOOK || n < (state->size << 1)) { |
| 342 | /* get more output, looking for header if required */ |
| 343 | if (gz_fetch(state) == -1) |
| 344 | return 0; |
| 345 | continue; /* no progress yet -- go back to copy above */ |
| 346 | /* the copy above assures that we will leave with space in the |
| 347 | output buffer, allowing at least one gzungetc() to succeed */ |
| 348 | } |
| 349 | |
| 350 | /* large len -- read directly into user buffer */ |
| 351 | else if (state->how == COPY) { /* read directly */ |
| 352 | if (gz_load(state, (unsigned char *)buf, n, &n) == -1) |
| 353 | return 0; |
| 354 | } |