From 1ea51e1fb6fb072c84c166e0831423b0c323558b Mon Sep 17 00:00:00 2001 From: dkf Date: Sat, 27 Dec 2008 00:04:17 +0000 Subject: Assorted minor corrections to the Zlib C API to make it work with the PNG implementation better. --- ChangeLog | 13 ++++++++ doc/TclZlib.3 | 39 ++++++++++++++--------- generic/tcl.decls | 4 +-- generic/tclDecls.h | 16 +++++----- generic/tclStubInit.c | 4 +-- generic/tclZlib.c | 85 +++++++++++++++++++++++++-------------------------- 6 files changed, 91 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index 03aa530..9daefa6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-12-27 Donal K. Fellows + + * generic/tclZlib.c (Tcl_ZlibStreamGet): Corrected the semantics of + this function to be useful to the PNG implementation. If the argument + object is empty, this gives the previous semantics. + (Tcl_ZlibStreamChecksum): Corrected name to be less misleading; it + only produced Adler-32 checksums when the stream was processing the + right type of compressed data format. + (Tcl_ZlibAdler32, Tcl_ZlibCRC32): Corrected types so that they work + naturally with the results of Tcl_GetByteArrayFromObj(). + *** POTENTIAL INCOMPATIBILITY *** for all above changes, but very + unlikely to be difficult for anyone to deal with. + 2008-12-26 Donal K. Fellows * generic/tcl.decls: Tidy up the commenting style, adding markers for diff --git a/doc/TclZlib.3 b/doc/TclZlib.3 index 1b2bb44..42d82b5 100644 --- a/doc/TclZlib.3 +++ b/doc/TclZlib.3 @@ -4,14 +4,14 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: TclZlib.3,v 1.3 2008/12/21 08:17:37 dkf Exp $ +'\" RCS: @(#) $Id: TclZlib.3,v 1.4 2008/12/27 00:04:17 dkf Exp $ '\" .so man.macros .TH TclZlib 3 8.6 Tcl "Tcl Library Procedures" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME -Tcl_ZlibAdler32, Tcl_ZlibCRC32, Tcl_ZlibDeflate, Tcl_ZlibInflate, Tcl_ZlibStreamAdler32, Tcl_ZlibStreamClose, Tcl_ZlibStreamEof, Tcl_ZlibStreamGet, Tcl_ZlibStreamGetCommandName, Tcl_ZlibStreamInit, Tcl_ZlibStreamPut \- compression and decompression functions +Tcl_ZlibAdler32, Tcl_ZlibCRC32, Tcl_ZlibDeflate, Tcl_ZlibInflate, Tcl_ZlibStreamChecksum, Tcl_ZlibStreamClose, Tcl_ZlibStreamEof, Tcl_ZlibStreamGet, Tcl_ZlibStreamGetCommandName, Tcl_ZlibStreamInit, Tcl_ZlibStreamPut \- compression and decompression functions .SH SYNOPSIS .nf #include @@ -41,7 +41,7 @@ int \fBTcl_ZlibStreamClose\fR(\fIzshandle\fR) .sp int -\fBTcl_ZlibStreamAdler32\fR(\fIzshandle\fR) +\fBTcl_ZlibStreamChecksum\fR(\fIzshandle\fR) .sp int \fBTcl_ZlibStreamPut\fR(\fIzshandle, dataObj, flush\fR) @@ -53,7 +53,8 @@ int .AS Tcl_ZlibStream *zshandlePtr out .AP Tcl_Interp *interp in The interpreter to store resulting compressed or uncompressed data in. Also -where any error messages are written. +where any error messages are written. For \fBTcl_ZlibStreamInit\fR, this can +be NULL to create a stream that is not bound to a command. .AP int format in What format of compressed data to work with. Must be one of \fBTCL_ZLIB_FORMAT_ZLIB\fR for zlib-format data, \fBTCL_ZLIB_FORMAT_GZIP\fR @@ -63,7 +64,7 @@ chosen which can automatically detect whether the compressed data was in zlib or gzip format. .AP Tcl_Obj *dataObj in/out A byte-array object containing the data to be compressed or decompressed, or -which is set to the data extracted from the stream when passed to +to which the data extracted from the stream is appended when passed to \fBTcl_ZlibStreamGet\fR. .AP int level in What level of compression to use. Should be a number from 0 to 9 or one of the @@ -122,18 +123,28 @@ bytes. Typical usage is: .CS checksum = \fBTcl_ZlibCRC32\fR(\fBTcl_ZlibCRC32\fR(0,NULL,0), data, length); .CE +.SS "ZLIB STREAMS" .PP \fBTcl_ZlibStreamInit\fR creates a compressing or decompressing stream that is linked to a Tcl command, according to its arguments, and provides an abstract -token for the stream; \fBTcl_ZlibStreamGetCommandName\fR returns the name of -that command given the stream token. Once a stream has been constructed, -\fBTcl_ZlibStreamPut\fR is used to add data to the stream and -\fBTcl_ZlibStreamGet\fR is used to retrieve data from the stream after -processing. \fBTcl_ZlibStreamAdler32\fR returns the checksum computed over the -uncompressed data, and \fBTcl_ZlibStreamEof\fR returns whether the end of the -uncompressed data has been reached. Finally, \fBTcl_ZlibStreamClose\fR will -clean up the stream and delete the associated command: using -\fBTcl_DeleteCommand\fR on the stream's command is equivalent. +token for the stream and returns a normal Tcl result code; +\fBTcl_ZlibStreamGetCommandName\fR returns the name of that command given the +stream token, or NULL if the stream has no command. +.PP +Once a stream has been constructed, \fBTcl_ZlibStreamPut\fR is used to add +data to the stream and \fBTcl_ZlibStreamGet\fR is used to retrieve data from +the stream after processing. Both return normal Tcl result codes. With +\fBTcl_ZlibStreamPut\fR, the data buffer object passed to it should not be +modified afterwards. With \fBTcl_ZlibStreamGet\fR, the data buffer object +passed to it will have the data bytes appended to it. +.PP +\fBTcl_ZlibStreamChecksum\fR returns the checksum computed over the +uncompressed data according to the format, and \fBTcl_ZlibStreamEof\fR returns +whether the end of the uncompressed data has been reached. +.PP +Finally, \fBTcl_ZlibStreamClose\fR will clean up the stream and delete the +associated command: using \fBTcl_DeleteCommand\fR on the stream's command is +equivalent. .SH "PORTABILITY NOTES" These functions will fail gracefully if Tcl is not linked with the zlib library. diff --git a/generic/tcl.decls b/generic/tcl.decls index 5a4b322..dff3242 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -12,7 +12,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: tcl.decls,v 1.165 2008/12/26 09:51:11 dkf Exp $ +# RCS: @(#) $Id: tcl.decls,v 1.166 2008/12/27 00:04:17 dkf Exp $ library tcl @@ -2265,7 +2265,7 @@ declare 616 generic { int Tcl_ZlibStreamEof(Tcl_ZlibStream zshandle) } declare 617 generic { - int Tcl_ZlibStreamAdler32(Tcl_ZlibStream zshandle) + int Tcl_ZlibStreamChecksum(Tcl_ZlibStream zshandle) } declare 618 generic { int Tcl_ZlibStreamPut(Tcl_ZlibStream zshandle, Tcl_Obj *data, int flush) diff --git a/generic/tclDecls.h b/generic/tclDecls.h index e2e4366..74284ed 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclDecls.h,v 1.166 2008/12/18 06:40:02 nijtmans Exp $ + * RCS: @(#) $Id: tclDecls.h,v 1.167 2008/12/27 00:04:17 dkf Exp $ */ #ifndef _TCLDECLS @@ -3731,10 +3731,10 @@ EXTERN Tcl_Obj * Tcl_ZlibStreamGetCommandName ( /* 616 */ EXTERN int Tcl_ZlibStreamEof (Tcl_ZlibStream zshandle); #endif -#ifndef Tcl_ZlibStreamAdler32_TCL_DECLARED -#define Tcl_ZlibStreamAdler32_TCL_DECLARED +#ifndef Tcl_ZlibStreamChecksum_TCL_DECLARED +#define Tcl_ZlibStreamChecksum_TCL_DECLARED /* 617 */ -EXTERN int Tcl_ZlibStreamAdler32 (Tcl_ZlibStream zshandle); +EXTERN int Tcl_ZlibStreamChecksum (Tcl_ZlibStream zshandle); #endif #ifndef Tcl_ZlibStreamPut_TCL_DECLARED #define Tcl_ZlibStreamPut_TCL_DECLARED @@ -4451,7 +4451,7 @@ typedef struct TclStubs { int (*tcl_ZlibStreamInit) (Tcl_Interp * interp, int mode, int format, int level, Tcl_Obj * dictObj, Tcl_ZlibStream * zshandle); /* 614 */ Tcl_Obj * (*tcl_ZlibStreamGetCommandName) (Tcl_ZlibStream zshandle); /* 615 */ int (*tcl_ZlibStreamEof) (Tcl_ZlibStream zshandle); /* 616 */ - int (*tcl_ZlibStreamAdler32) (Tcl_ZlibStream zshandle); /* 617 */ + int (*tcl_ZlibStreamChecksum) (Tcl_ZlibStream zshandle); /* 617 */ int (*tcl_ZlibStreamPut) (Tcl_ZlibStream zshandle, Tcl_Obj * data, int flush); /* 618 */ int (*tcl_ZlibStreamGet) (Tcl_ZlibStream zshandle, Tcl_Obj * data, int count); /* 619 */ int (*tcl_ZlibStreamClose) (Tcl_ZlibStream zshandle); /* 620 */ @@ -6999,9 +6999,9 @@ extern const TclStubs *tclStubsPtr; #define Tcl_ZlibStreamEof \ (tclStubsPtr->tcl_ZlibStreamEof) /* 616 */ #endif -#ifndef Tcl_ZlibStreamAdler32 -#define Tcl_ZlibStreamAdler32 \ - (tclStubsPtr->tcl_ZlibStreamAdler32) /* 617 */ +#ifndef Tcl_ZlibStreamChecksum +#define Tcl_ZlibStreamChecksum \ + (tclStubsPtr->tcl_ZlibStreamChecksum) /* 617 */ #endif #ifndef Tcl_ZlibStreamPut #define Tcl_ZlibStreamPut \ diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 926a45d..818abf1 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclStubInit.c,v 1.177 2008/12/18 04:38:01 dgp Exp $ + * RCS: @(#) $Id: tclStubInit.c,v 1.178 2008/12/27 00:04:17 dkf Exp $ */ #include "tclInt.h" @@ -1142,7 +1142,7 @@ static const TclStubs tclStubs = { Tcl_ZlibStreamInit, /* 614 */ Tcl_ZlibStreamGetCommandName, /* 615 */ Tcl_ZlibStreamEof, /* 616 */ - Tcl_ZlibStreamAdler32, /* 617 */ + Tcl_ZlibStreamChecksum, /* 617 */ Tcl_ZlibStreamPut, /* 618 */ Tcl_ZlibStreamGet, /* 619 */ Tcl_ZlibStreamClose, /* 620 */ diff --git a/generic/tclZlib.c b/generic/tclZlib.c index 4fc56e1..8db482a 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclZlib.c,v 1.18 2008/12/22 01:39:33 patthoyts Exp $ + * RCS: @(#) $Id: tclZlib.c,v 1.19 2008/12/27 00:04:17 dkf Exp $ */ #include "tclInt.h" @@ -818,8 +818,13 @@ Tcl_ZlibStreamGetCommandName( Tcl_ZlibStream zshandle) /* as obtained from Tcl_ZlibStreamInit */ { ZlibStreamHandle *zsh = (ZlibStreamHandle *) zshandle; - Tcl_Obj *objPtr = Tcl_NewObj(); + Tcl_Obj *objPtr; + if (!zsh->interp) { + return NULL; + } + + TclNewObj(objPtr); Tcl_GetCommandFullName(zsh->interp, zsh->cmd, objPtr); return objPtr; } @@ -855,7 +860,7 @@ Tcl_ZlibStreamEof( /* *---------------------------------------------------------------------- * - * Tcl_ZlibStreamAdler32 -- + * Tcl_ZlibStreamChecksum -- * * Return the checksum of the uncompressed data seen so far by the * stream. @@ -864,7 +869,7 @@ Tcl_ZlibStreamEof( */ int -Tcl_ZlibStreamAdler32( +Tcl_ZlibStreamChecksum( Tcl_ZlibStream zshandle) /* As obtained from Tcl_ZlibStreamInit */ { ZlibStreamHandle *zsh = (ZlibStreamHandle *) zshandle; @@ -877,7 +882,8 @@ Tcl_ZlibStreamAdler32( * * Tcl_ZlibStreamPut -- * - * Add data to the stream for compression or decompression. + * Add data to the stream for compression or decompression from a + * bytearray Tcl_Obj. * *---------------------------------------------------------------------- */ @@ -929,7 +935,7 @@ Tcl_ZlibStreamPut( * Now append the compressed data to the outData list. */ - Tcl_ListObjAppendElement(zsh->interp, zsh->outData, obj); + Tcl_ListObjAppendElement(NULL, zsh->outData, obj); } if (outSize < 0xFFFF) { outSize = 0xFFFF; /* There may be *lots* of data left to @@ -955,14 +961,14 @@ Tcl_ZlibStreamPut( * Now append the compressed data to the outData list. */ - Tcl_ListObjAppendElement(zsh->interp, zsh->outData, obj); + Tcl_ListObjAppendElement(NULL, zsh->outData, obj); } } else { /* * This is easy. Just append to the inData list. */ - Tcl_ListObjAppendElement(zsh->interp, zsh->inData, data); + Tcl_ListObjAppendElement(NULL, zsh->inData, data); /* * and we'll need the flush parameter for the Inflate call. @@ -979,7 +985,8 @@ Tcl_ZlibStreamPut( * * Tcl_ZlibStreamGet -- * - * Retrieve data (now compressed or decompressed) from the stream. + * Retrieve data (now compressed or decompressed) from the stream into a + * bytearray Tcl_Obj. * *---------------------------------------------------------------------- */ @@ -987,7 +994,7 @@ Tcl_ZlibStreamPut( int Tcl_ZlibStreamGet( Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */ - Tcl_Obj *data, /* A place to put the data */ + Tcl_Obj *data, /* A place to append the data. */ int count) /* Number of bytes to grab as a maximum, you * may get less! */ { @@ -995,6 +1002,7 @@ Tcl_ZlibStreamGet( int e, i, listLen, itemLen, dataPos = 0; Tcl_Obj *itemObj; unsigned char *dataPtr, *itemPtr; + int existing; /* * Getting beyond the of stream, just return empty string. @@ -1004,6 +1012,8 @@ Tcl_ZlibStreamGet( return TCL_OK; } + (void) Tcl_GetByteArrayFromObj(data, &existing); + if (zsh->mode == TCL_ZLIB_STREAM_INFLATE) { if (count == -1) { /* @@ -1018,7 +1028,8 @@ Tcl_ZlibStreamGet( * Prepare the place to store the data. */ - dataPtr = Tcl_SetByteArrayLength(data, count); + dataPtr = Tcl_SetByteArrayLength(data, existing+count); + dataPtr += existing; zsh->stream.next_out = dataPtr; zsh->stream.avail_out = count; @@ -1031,20 +1042,14 @@ Tcl_ZlibStreamGet( Tcl_DecrRefCount(zsh->currentInput); zsh->currentInput = NULL; } - if (Tcl_ListObjLength(zsh->interp, zsh->inData, - &listLen) != TCL_OK) { - return TCL_ERROR; - } + Tcl_ListObjLength(NULL, zsh->inData, &listLen); if (listLen > 0) { /* * There is more input available, get it from the list and * give it to zlib. */ - if (Tcl_ListObjIndex(zsh->interp, zsh->inData, 0, - &itemObj) != TCL_OK) { - return TCL_ERROR; - } + Tcl_ListObjIndex(NULL, zsh->inData, 0, &itemObj); itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); Tcl_IncrRefCount(itemObj); zsh->currentInput = itemObj; @@ -1061,11 +1066,9 @@ Tcl_ZlibStreamGet( } e = inflate(&zsh->stream, zsh->flush); - if (Tcl_ListObjLength(zsh->interp, zsh->inData, &listLen) != TCL_OK) { - return TCL_ERROR; - } + Tcl_ListObjLength(NULL, zsh->inData, &listLen); - while ((zsh->stream.avail_out > 0) && (e==Z_OK || e==Z_BUF_ERROR) + while ((zsh->stream.avail_out > 0) && (e == Z_OK || e == Z_BUF_ERROR) && (listLen > 0)) { /* * State: We have not satisfied the request yet and there may be @@ -1078,6 +1081,7 @@ Tcl_ZlibStreamGet( "Unexpected zlib internal state during decompression", TCL_STATIC); } + Tcl_SetByteArrayLength(data, existing); return TCL_ERROR; } @@ -1086,10 +1090,7 @@ Tcl_ZlibStreamGet( zsh->currentInput = 0; } - if (Tcl_ListObjIndex(zsh->interp, zsh->inData, 0, - &itemObj) != TCL_OK) { - return TCL_ERROR; - } + Tcl_ListObjIndex(zsh->interp, zsh->inData, 0, &itemObj); itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); Tcl_IncrRefCount(itemObj); zsh->currentInput = itemObj; @@ -1110,9 +1111,11 @@ Tcl_ZlibStreamGet( e = inflate(&zsh->stream, zsh->flush); } if (zsh->stream.avail_out > 0) { - Tcl_SetByteArrayLength(data, count - zsh->stream.avail_out); + Tcl_SetByteArrayLength(data, + existing + count - zsh->stream.avail_out); } if (!(e==Z_OK || e==Z_STREAM_END || e==Z_BUF_ERROR)) { + Tcl_SetByteArrayLength(data, existing); ConvertError(zsh->interp, e); return TCL_ERROR; } @@ -1125,18 +1128,11 @@ Tcl_ZlibStreamGet( inflateEnd(&zsh->stream); } } else { - if (Tcl_ListObjLength(zsh->interp, zsh->outData, - &listLen) != TCL_OK) { - return TCL_ERROR; - } - + Tcl_ListObjLength(NULL, zsh->outData, &listLen); if (count == -1) { count = 0; for (i=0; iinterp, zsh->outData, i, - &itemObj) != TCL_OK) { - return TCL_ERROR; - } + Tcl_ListObjIndex(NULL, zsh->outData, i, &itemObj); itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); if (i == 0) { count += itemLen - zsh->outPos; @@ -1150,11 +1146,12 @@ Tcl_ZlibStreamGet( * Prepare the place to store the data. */ - dataPtr = Tcl_SetByteArrayLength(data, count); + dataPtr = Tcl_SetByteArrayLength(data, existing + count); + dataPtr += existing; - while ((count > dataPos) && (Tcl_ListObjLength(zsh->interp, - zsh->outData, &listLen) == TCL_OK) && (listLen > 0)) { - Tcl_ListObjIndex(zsh->interp, zsh->outData, 0, &itemObj); + while ((count > dataPos) && (Tcl_ListObjLength(NULL, zsh->outData, + &listLen) == TCL_OK) && (listLen > 0)) { + Tcl_ListObjIndex(NULL, zsh->outData, 0, &itemObj); itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen); if (itemLen-zsh->outPos >= count-dataPos) { unsigned len = count - dataPos; @@ -1177,7 +1174,7 @@ Tcl_ZlibStreamGet( listLen--; } } - Tcl_SetByteArrayLength(data, dataPos); + Tcl_SetByteArrayLength(data, existing + dataPos); } return TCL_OK; } @@ -1537,7 +1534,7 @@ Tcl_ZlibInflate( unsigned int Tcl_ZlibCRC32( unsigned int crc, - const char *buf, + const unsigned char *buf, int len) { /* Nothing much to do, just wrap the crc32(). */ @@ -1547,7 +1544,7 @@ Tcl_ZlibCRC32( unsigned int Tcl_ZlibAdler32( unsigned int adler, - const char *buf, + const unsigned char *buf, int len) { return adler32(adler, (Bytef *) buf, (unsigned) len); -- cgit v0.12