Move cgozstd dictionary init earlier, into Reset
diff --git a/lib/cgozstd/cgozstd.go b/lib/cgozstd/cgozstd.go index 3be51dc..6cae64b 100644 --- a/lib/cgozstd/cgozstd.go +++ b/lib/cgozstd/cgozstd.go
@@ -184,6 +184,13 @@ return "cgozstd: unknown error" } +func slicePointer(s []uint8) unsafe.Pointer { + if len(s) == 0 { + return nil + } + return unsafe.Pointer(&s[0]) +} + // ReaderRecycler can lessen the new memory allocated when calling Reader.Reset // on a bound Reader. // @@ -217,8 +224,6 @@ i, j uint32 r io.Reader - dictionary []byte - readErr error zstdErr error @@ -243,8 +248,29 @@ dictionary = dictionary[len(dictionary)-maxLen:] } + z := (*C.ZSTD_DCtx)(nil) + if (r.recycler != nil) && !r.recycler.closed && (r.recycler.z != nil) { + z, r.recycler.z = r.recycler.z, nil + } else { + z = C.ZSTD_createDStream() + if z == nil { + return errOutOfMemory + } + } + + if e := errCode(C.cgozstd_decompress_start(z, + (*C.uint8_t)(slicePointer(dictionary)), + (C.uint32_t)(len(dictionary)), + )); e != 0 { + C.ZSTD_freeDCtx(z) + if e < 0 { + return errZstdVersionTooSmall + } + return e + } + r.r = reader - r.dictionary = dictionary + r.z = z return nil } @@ -281,37 +307,6 @@ return 0, errMissingResetCall } - if r.z == nil { - if (r.recycler != nil) && !r.recycler.closed && (r.recycler.z != nil) { - r.z, r.recycler.z = r.recycler.z, nil - } else { - r.z = C.ZSTD_createDStream() - if r.z == nil { - return 0, errOutOfMemory - } - } - - e := errCode(0) - if len(r.dictionary) == 0 { - e = errCode(C.cgozstd_decompress_start(r.z, - (*C.uint8_t)(nil), - (C.uint32_t)(0), - )) - } else { - e = errCode(C.cgozstd_decompress_start(r.z, - (*C.uint8_t)(unsafe.Pointer(&r.dictionary[0])), - (C.uint32_t)(len(r.dictionary)), - )) - } - if e < 0 { - r.zstdErr = errZstdVersionTooSmall - return 0, r.zstdErr - } else if e != 0 { - r.zstdErr = e - return 0, r.zstdErr - } - } - if len(p) > maxLen { p = p[:maxLen] } @@ -393,12 +388,9 @@ // // The zero value is not usable until Reset is called. type Writer struct { - buf [65536]byte - j uint32 - w io.Writer - level compression.Level - - dictionary []byte + buf [65536]byte + j uint32 + w io.Writer writeErr error @@ -408,8 +400,8 @@ a C.advances } -func (w *Writer) zstdCompressionLevel() int32 { - return w.level.Interpolate(1, 2, 3, 15, 22) +func zstdCompressionLevel(level compression.Level) int32 { + return level.Interpolate(1, 2, 3, 15, 22) } // Reset implements compression.Writer. @@ -425,9 +417,30 @@ dictionary = dictionary[len(dictionary)-maxLen:] } + z := (*C.ZSTD_CCtx)(nil) + if (w.recycler != nil) && !w.recycler.closed && (w.recycler.z != nil) { + z, w.recycler.z = w.recycler.z, nil + } else { + z = C.ZSTD_createCStream() + if z == nil { + return errOutOfMemory + } + } + + if e := errCode(C.cgozstd_compress_start(z, + (*C.uint8_t)(slicePointer(dictionary)), + (C.uint32_t)(len(dictionary)), + C.int(zstdCompressionLevel(level)), + )); e != 0 { + C.ZSTD_freeCCtx(z) + if e < 0 { + return errZstdVersionTooSmall + } + return e + } + w.w = writer - w.level = level - w.dictionary = dictionary + w.z = z return nil } @@ -512,39 +525,6 @@ panic("unreachable") } - if w.z == nil { - if (w.recycler != nil) && !w.recycler.closed && (w.recycler.z != nil) { - w.z, w.recycler.z = w.recycler.z, nil - } else { - w.z = C.ZSTD_createCStream() - if w.z == nil { - return errOutOfMemory - } - } - - e := errCode(0) - if len(w.dictionary) == 0 { - e = errCode(C.cgozstd_compress_start(w.z, - (*C.uint8_t)(nil), - (C.uint32_t)(0), - C.int(w.zstdCompressionLevel()), - )) - } else { - e = errCode(C.cgozstd_compress_start(w.z, - (*C.uint8_t)(unsafe.Pointer(&w.dictionary[0])), - (C.uint32_t)(len(w.dictionary)), - C.int(w.zstdCompressionLevel()), - )) - } - if e < 0 { - w.writeErr = errZstdVersionTooSmall - return w.writeErr - } else if e != 0 { - w.writeErr = e - return w.writeErr - } - } - for (len(p) > 0) || final { if w.j == uint32(len(w.buf)) { if err := w.flush(false); err != nil {