diff options
Diffstat (limited to 'go/cbrotli/cbrotli.go')
-rwxr-xr-x | go/cbrotli/cbrotli.go | 254 |
1 files changed, 0 insertions, 254 deletions
diff --git a/go/cbrotli/cbrotli.go b/go/cbrotli/cbrotli.go deleted file mode 100755 index a7009d0..0000000 --- a/go/cbrotli/cbrotli.go +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Distributed under MIT license. -// See file LICENSE for detail or copy at https://opensource.org/licenses/MIT - -// Package cbrotli compresses and decompresses data with C-Brotli library. -package cbrotli - -import ( - "bytes" - "io" - - "github.com/google/brotli/go/cbrotli/internal/decoder" - "github.com/google/brotli/go/cbrotli/internal/encoder" -) - -// An internalError reports an error in the (c-)brotli code itself. -type internalError string - -func (e internalError) Error() string { - return "cbrotli: internal error: " + string(e) -} - -//------------------------------------------------------------------------------ -// Encoder -//------------------------------------------------------------------------------ - -// WriterOptions configures Writer. -type WriterOptions struct { - // Quality controls the compression-speed vs compression-density trade-offs. - // The higher the quality, the slower the compression. Range is 0 to 11. - Quality int - // LGWin is the base 2 logarithm of the sliding window size. - // Range is 10 to 24. 0 indicates automatic configuration based on Quality. - LGWin int -} - -// Writer implements io.WriteCloser, an io.Writer decorator that produces -// Brotli-encoded data. -type Writer struct { - dst io.Writer - encoder encoder.Encoder - closed bool -} - -// NewWriter initializes new Writer instance. -// Close MUST be called to free resources. -func NewWriter(dst io.Writer, options WriterOptions) *Writer { - return &Writer{ - dst: dst, - encoder: encoder.New(options.Quality, options.LGWin), - } -} - -// Close implements io.Closer. Close MUST be invoked to free native resources. -// Also Close implicitly flushes remaining data to the decorated writer. -func (z *Writer) Close() error { - if z.closed { - return nil - } - defer z.encoder.Close() - _, err := z.writeChunk(nil, encoder.Finish) - z.closed = true - return err -} - -func (z *Writer) writeChunk(p []byte, op encoder.Operation) (int, error) { - if z.closed { - return 0, internalError("write after close") - } - var totalBytesConsumed int - var err error - for { - bytesConsumed, output, status := z.encoder.CompressStream(p, op) - if status == encoder.Error { - err = internalError("encoder failure") - break - } - p = p[bytesConsumed:] - totalBytesConsumed += bytesConsumed - _, err = z.dst.Write(output) - if err != nil { - break - } - if len(p) == 0 && status == encoder.Done { - break - } - } - return totalBytesConsumed, err -} - -// Write implements io.Writer. -func (z *Writer) Write(p []byte) (int, error) { - return z.writeChunk(p, encoder.Process) -} - -// Flush outputs encoded data for all input provided to Write. The resulting -// output can be decoded to match all input before Flush, but the stream is -// not yet complete until after Close. -// Flush has a negative impact on compression. -func (z *Writer) Flush() error { - _, err := z.writeChunk(nil, encoder.Finish) - return err -} - -// Encode returns content encoded with Brotli. -func Encode(content []byte, options WriterOptions) ([]byte, error) { - var buf bytes.Buffer - writer := NewWriter(&buf, options) - defer writer.Close() - _, err := writer.Write(content) - if err != nil { - return nil, err - } - if err := writer.Close(); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -//------------------------------------------------------------------------------ -// Decoder -//------------------------------------------------------------------------------ - -// Reader implements io.ReadCloser, an io.Reader decorator that decodes -// Brotli-encoded data. -type Reader struct { - src io.Reader - decoder decoder.Decoder - buf []byte // intermediate read buffer pointed to by next - eof bool // true if all compressed stream is decoded - next []byte // buffered data to be passed to decoder - output []byte // data produced by decoder, but not yet consumed - srcErr error // last source reader error - err error // reader state; nil if it is OK to read further - closed bool // true is stream is already closed -} - -// NewReader initializes new Reader instance. -// Close MUST be called to free resources. -func NewReader(src io.Reader) *Reader { - return &Reader{ - src: src, - decoder: decoder.New(), - buf: make([]byte, 32*1024), - eof: false, - } -} - -// Close implements io.Closer. Close MUST be invoked to free native resources. -func (z *Reader) Close() error { - if z.closed { - return nil - } - z.decoder.Close() - z.err = internalError("read after close") - z.closed = true - return nil -} - -func isEOF(src io.Reader) bool { - n, err := src.Read(make([]byte, 1)) - return n == 0 && err == io.EOF -} - -// Read implements io.Reader. -func (z *Reader) Read(p []byte) (int, error) { - // Any error state is unrecoverable. - if z.err != nil { - return 0, z.err - } - // See io.Reader documentation. - if len(p) == 0 { - return 0, nil - } - - var totalOutBytes int - - // There is no practical limit for amount of bytes being consumed by decoder - // before producing any output. Continue feeding decoder until some data is - // produced - for { - // Push already produced output first. - if outBytes := len(z.output); outBytes != 0 { - outBytes = copy(p, z.output) - p = p[outBytes:] - z.output = z.output[outBytes:] - totalOutBytes += outBytes - // Output buffer is full. - if len(p) == 0 { - break - } - continue - } - // No more produced output left. - // If no more output is expected, then we are finished. - if z.eof { - z.err = io.EOF - break - } - // Replenish buffer (might cause blocking read), only if necessary. - if len(z.next) == 0 && totalOutBytes == 0 && z.srcErr != io.EOF { - var n int - n, z.srcErr = z.src.Read(z.buf) - z.next = z.buf[:n] - if z.srcErr != nil && z.srcErr != io.EOF { - z.err = z.srcErr - break - } - } - // Do decoding. - consumed, output, status := z.decoder.DecompressStream(z.next) - z.output = output - z.next = z.next[consumed:] - if status == decoder.Error { - // When error happens, the remaining output does not matter. - z.err = internalError("decoder failure") - break - } else if status == decoder.Done { - // Decoder stream is closed; no further input is expected. - if len(z.next) != 0 || (z.srcErr != io.EOF && !isEOF(z.src)) { - z.err = internalError("excessive input") - break - } - // No more output is expected; keep pushing output. - z.eof = true - continue - } else { - // If can not move any further... - if consumed == 0 && len(z.output) == 0 { - // Unexpected end of input. - if z.srcErr == io.EOF || totalOutBytes == 0 { - z.err = io.ErrUnexpectedEOF - } - // Postpone blocking reads for the next invocation. - break - } - // Continue pushing output. - } - } - return totalOutBytes, z.err -} - -// Decode decodes Brotli encoded data. -func Decode(encodedData []byte) ([]byte, error) { - var buf bytes.Buffer - reader := NewReader(bytes.NewReader(encodedData)) - defer reader.Close() - _, err := io.Copy(&buf, reader) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} |