func (z *reader) Read(p []byte) (int, error) { if z.err != nil { return 0, z.err } if len(p) == 0 { return 0, nil } // read and deflate until the output buffer is full z.strm.next_out = (*C.Bytef)(unsafe.Pointer(&p[0])) z.strm.avail_out = (C.uInt)(len(p)) for { // if we have no data to inflate, read more if !z.skipIn && z.strm.avail_in == 0 { var n int n, z.err = z.r.Read(z.in) if (z.err != nil && z.err != io.EOF) || (n == 0 && z.err == io.EOF) { C.inflateEnd(&z.strm) return 0, z.err } z.strm.next_in = (*C.Bytef)(unsafe.Pointer(&z.in[0])) z.strm.avail_in = (C.uInt)(n) } else { z.skipIn = false } // inflate some ret := C.inflate(&z.strm, C.Z_NO_FLUSH) switch ret { case Z_NEED_DICT: ret = Z_DATA_ERROR fallthrough case Z_DATA_ERROR, Z_MEM_ERROR: z.err = fmt.Errorf("cgzip: failed to inflate (%v): %v", ret, C.GoString(z.strm.msg)) C.inflateEnd(&z.strm) return 0, z.err } // if we read something, we're good have := len(p) - int(z.strm.avail_out) if have > 0 { z.skipIn = ret == Z_OK && z.strm.avail_out == 0 return have, z.err } } panic("Unreachable") }
// Close closes the Reader. It does not close the underlying io.Reader. func (z *reader) Close() error { if z.err != nil { if z.err != io.EOF { return z.err } return nil } C.inflateEnd(&z.strm) z.err = io.EOF return nil }
func (z *reader) Read(p []byte) (int, error) { if z.err != nil { return 0, z.err } if len(p) == 0 { return 0, nil } // read and deflate until the output buffer is full z.strm.next_out = (*C.Bytef)(unsafe.Pointer(&p[0])) z.strm.avail_out = (C.uInt)(len(p)) for { // if we have no data to inflate, read more if !z.skipIn && z.strm.avail_in == 0 { var n int n, z.err = z.r.Read(z.in) // If we got data and EOF, pretend we didn't get the // EOF. That way we will return the right values // upstream. Note this will trigger another read // later on, that should return (0, EOF). if n > 0 && z.err == io.EOF { z.err = nil } // FIXME(alainjobart) this code is not compliant with // the Reader interface. We should process all the // data we got from the reader, and then return the // error, whatever it is. if (z.err != nil && z.err != io.EOF) || (n == 0 && z.err == io.EOF) { C.inflateEnd(&z.strm) return 0, z.err } z.strm.next_in = (*C.Bytef)(unsafe.Pointer(&z.in[0])) z.strm.avail_in = (C.uInt)(n) } else { z.skipIn = false } // inflate some ret := C.inflate(&z.strm, C.Z_NO_FLUSH) switch ret { case Z_NEED_DICT: ret = Z_DATA_ERROR fallthrough case Z_DATA_ERROR, Z_MEM_ERROR: z.err = fmt.Errorf("cgzip: failed to inflate (%v): %v", ret, C.GoString(z.strm.msg)) C.inflateEnd(&z.strm) return 0, z.err } // if we read something, we're good have := len(p) - int(z.strm.avail_out) if have > 0 { z.skipIn = ret == Z_OK && z.strm.avail_out == 0 return have, z.err } } }