Ejemplo n.º 1
0
// Calling Close does not close the wrapped io.Writer originally
// passed to NewWriterX.
func (z *Writer) Close() error {
	if z.err != nil {
		return z.err
	}
	z.write(nil, Z_FINISH)
	if z.err != nil {
		return z.err
	}
	C.deflateEnd(&z.strm)
	z.err = io.EOF
	return nil
}
Ejemplo n.º 2
0
// this is the main function: it advances the write with either
// new data or something else to do, like a flush
func (z *Writer) write(p []byte, flush int) int {
	if len(p) == 0 {
		z.strm.next_in = (*C.Bytef)(unsafe.Pointer(nil))
		z.strm.avail_in = 0
	} else {
		z.strm.next_in = (*C.Bytef)(unsafe.Pointer(&p[0]))
		z.strm.avail_in = (C.uInt)(len(p))
	}
	// we loop until we don't get a full output buffer
	// each loop completely writes the output buffer to the underlying
	// writer
	for {
		// deflate one buffer
		z.strm.next_out = (*C.Bytef)(unsafe.Pointer(&z.out[0]))
		z.strm.avail_out = (C.uInt)(len(z.out))
		ret := C.deflate(&z.strm, (C.int)(flush))
		if ret == Z_STREAM_ERROR {
			// all the other error cases are normal,
			// and this should never happen
			panic(fmt.Errorf("cgzip: Unexpected error (1)"))
		}

		// write everything
		from := 0
		have := len(z.out) - int(z.strm.avail_out)
		for have > 0 {
			var n int
			n, z.err = z.w.Write(z.out[from:have])
			if z.err != nil {
				C.deflateEnd(&z.strm)
				return 0
			}
			from += n
			have -= n
		}

		// we stop trying if we get a partial response
		if z.strm.avail_out != 0 {
			break
		}
	}
	// the library guarantees this
	if z.strm.avail_in != 0 {
		panic(fmt.Errorf("cgzip: Unexpected error (2)"))
	}
	return len(p)
}