Tcl Source Code

Check-in [584e69e4d2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:towards dictionary setting on transforms
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-400-impl
Files: files | file ages | folders
SHA1: 584e69e4d2fa738499250feb3712362e47ddc64e
User & Date: dkf 2012-04-11 07:16:45
Context
2012-04-14
06:45
merge trunk check-in: f054d4db25 user: dkf tags: tip-400-impl
2012-04-11
07:16
towards dictionary setting on transforms check-in: 584e69e4d2 user: dkf tags: tip-400-impl
2012-04-10
08:13
merge trunk check-in: a8711ad508 user: dkf tags: tip-400-impl
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclZlib.c.

91
92
93
94
95
96
97



98
99
100
101
102
103
104
    int inAllocated, outAllocated;
				/* Sizes of working buffers. */
    GzipHeader inHeader;	/* Header read from input stream, when
				 * decompressing a gzip stream. */
    GzipHeader outHeader;	/* Header to write to an output stream, when
				 * compressing a gzip stream. */
    Tcl_TimerToken timer;	/* Timer used for keeping events fresh. */



} ZlibChannelData;

/*
 * Value bits for the flags field. Definitions are:
 *	ASYNC -		Whether this is an asynchronous channel.
 *	IN_HEADER -	Whether the inHeader field has been registered with
 *			the input compressor.







>
>
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    int inAllocated, outAllocated;
				/* Sizes of working buffers. */
    GzipHeader inHeader;	/* Header read from input stream, when
				 * decompressing a gzip stream. */
    GzipHeader outHeader;	/* Header to write to an output stream, when
				 * compressing a gzip stream. */
    Tcl_TimerToken timer;	/* Timer used for keeping events fresh. */
    Tcl_Obj *compDictObj;	/* Byte-array object containing compression
				 * dictionary (not dictObj!) to use if
				 * necessary. */
} ZlibChannelData;

/*
 * Value bits for the flags field. Definitions are:
 *	ASYNC -		Whether this is an asynchronous channel.
 *	IN_HEADER -	Whether the inHeader field has been registered with
 *			the input compressor.
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156

static void		ConvertError(Tcl_Interp *interp, int code);
static void		ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj);
static int		GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj,
			    GzipHeader *headerPtr, int *extraSizePtr);
static Tcl_Channel	ZlibStackChannelTransform(Tcl_Interp *interp,
			    int mode, int format, int level,
			    Tcl_Channel channel, Tcl_Obj *gzipHeaderDictPtr);

static void		ZlibStreamCleanup(ZlibStreamHandle *zshPtr);
static void		ZlibTransformTimerKill(ZlibChannelData *cd);
static void		ZlibTransformTimerRun(ClientData clientData);
static void		ZlibTransformTimerSetup(ZlibChannelData *cd);

/*
 * Type of zlib-based compressing and decompressing channels.







|
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

static void		ConvertError(Tcl_Interp *interp, int code);
static void		ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj);
static int		GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj,
			    GzipHeader *headerPtr, int *extraSizePtr);
static Tcl_Channel	ZlibStackChannelTransform(Tcl_Interp *interp,
			    int mode, int format, int level,
			    Tcl_Channel channel, Tcl_Obj *gzipHeaderDictPtr,
			    Tcl_Obj *compDictObj);
static void		ZlibStreamCleanup(ZlibStreamHandle *zshPtr);
static void		ZlibTransformTimerKill(ZlibChannelData *cd);
static void		ZlibTransformTimerRun(ClientData clientData);
static void		ZlibTransformTimerSetup(ZlibChannelData *cd);

/*
 * Type of zlib-based compressing and decompressing channels.
443
444
445
446
447
448
449




























450
451
452
453
454
455
456
		Tcl_NewStringObj(headerPtr->text ? "text" : "binary", -1));
    }

    if (latin1enc != NULL) {
	Tcl_FreeEncoding(latin1enc);
    }
}





























/*
 *----------------------------------------------------------------------
 *
 * Tcl_ZlibStreamInit --
 *
 *	This command initializes a (de)compression context/handle for







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
		Tcl_NewStringObj(headerPtr->text ? "text" : "binary", -1));
    }

    if (latin1enc != NULL) {
	Tcl_FreeEncoding(latin1enc);
    }
}

static int
SetInflateDictionary(
    z_streamp strm,
    Tcl_Obj *compDictObj)
{
    if (compDictObj != NULL) {
	int length;
	unsigned char *bytes = Tcl_GetByteArrayFromObj(compDictObj, &length);

	return inflateSetDictionary(strm, bytes, (unsigned) length);
    }
    return Z_OK;
}

static int
SetDeflateDictionary(
    z_streamp strm,
    Tcl_Obj *compDictObj)
{
    if (compDictObj != NULL) {
	int length;
	unsigned char *bytes = Tcl_GetByteArrayFromObj(compDictObj, &length);

	return deflateSetDictionary(strm, bytes, (unsigned) length);
    }
    return Z_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ZlibStreamInit --
 *
 *	This command initializes a (de)compression context/handle for
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600



601
602
603
604
605
606
607
	e = deflateInit2(&zshPtr->stream, level, Z_DEFLATED, wbits,
		MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
	if (e == Z_OK && zshPtr->gzHeaderPtr) {
	    e = deflateSetHeader(&zshPtr->stream,
		    &zshPtr->gzHeaderPtr->header);
	}
	if (e == Z_OK && zshPtr->compDictObj) {
	    int dictLen;
	    unsigned char *dictBytes =
		    Tcl_GetByteArrayFromObj(zshPtr->compDictObj, &dictLen);

	    e = deflateSetDictionary(&zshPtr->stream, dictBytes,
		    (unsigned) dictLen);
	}
    } else {
	e = inflateInit2(&zshPtr->stream, wbits);
	if (e == Z_OK && zshPtr->gzHeaderPtr) {
	    e = inflateGetHeader(&zshPtr->stream,
		    &zshPtr->gzHeaderPtr->header);



	}
    }

    if (e != Z_OK) {
	ConvertError(interp, e);
	goto error;
    }







<
<
<
<
|
<






>
>
>







614
615
616
617
618
619
620




621

622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	e = deflateInit2(&zshPtr->stream, level, Z_DEFLATED, wbits,
		MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
	if (e == Z_OK && zshPtr->gzHeaderPtr) {
	    e = deflateSetHeader(&zshPtr->stream,
		    &zshPtr->gzHeaderPtr->header);
	}
	if (e == Z_OK && zshPtr->compDictObj) {




	    e = SetDeflateDictionary(&zshPtr->stream, zshPtr->compDictObj);

	}
    } else {
	e = inflateInit2(&zshPtr->stream, wbits);
	if (e == Z_OK && zshPtr->gzHeaderPtr) {
	    e = inflateGetHeader(&zshPtr->stream,
		    &zshPtr->gzHeaderPtr->header);
	}
	if (format==TCL_ZLIB_FORMAT_RAW && zshPtr->compDictObj && e==Z_OK) {
	    e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
	}
    }

    if (e != Z_OK) {
	ConvertError(interp, e);
	goto error;
    }
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848




849
850
851
852
853
854
855
     * No output buffer available yet.
     */

    if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	e = deflateInit2(&zshPtr->stream, zshPtr->level, Z_DEFLATED,
		zshPtr->wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
	if (e == Z_OK && zshPtr->compDictObj) {
	    int dictLen;
	    unsigned char *dictBytes =
		    Tcl_GetByteArrayFromObj(zshPtr->compDictObj, &dictLen);

	    e = deflateSetDictionary(&zshPtr->stream, dictBytes,
		    (unsigned) dictLen);
	}
    } else {
	e = inflateInit2(&zshPtr->stream, zshPtr->wbits);




    }

    if (e != Z_OK) {
	ConvertError(zshPtr->interp, e);
	/* TODO:cleanup */
	return TCL_ERROR;
    }







<
<
<
<
|
<



>
>
>
>







863
864
865
866
867
868
869




870

871
872
873
874
875
876
877
878
879
880
881
882
883
884
     * No output buffer available yet.
     */

    if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
	e = deflateInit2(&zshPtr->stream, zshPtr->level, Z_DEFLATED,
		zshPtr->wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
	if (e == Z_OK && zshPtr->compDictObj) {




	    e = SetDeflateDictionary(&zshPtr->stream, zshPtr->compDictObj);

	}
    } else {
	e = inflateInit2(&zshPtr->stream, zshPtr->wbits);
	if (zshPtr->format == TCL_ZLIB_FORMAT_RAW && zshPtr->compDictObj
		&& e == Z_OK) {
	    e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
	}
    }

    if (e != Z_OK) {
	ConvertError(zshPtr->interp, e);
	/* TODO:cleanup */
	return TCL_ERROR;
    }
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
		 * And remove it from the list
		 */

		Tcl_ListObjReplace(NULL, zshPtr->inData, 0, 1, 0, NULL);
	    }
	}

	while (1) {
	    e = inflate(&zshPtr->stream, zshPtr->flush);
	    if (e != Z_NEED_DICT || zshPtr->compDictObj == NULL) {
		break;
	    } else {
		int dictLen;
		unsigned char *dictBytes =
			Tcl_GetByteArrayFromObj(zshPtr->compDictObj,&dictLen);

		e = inflateSetDictionary(&zshPtr->stream, dictBytes,
			(unsigned) dictLen);
		if (e != Z_OK) {
		    break;
		}
	    }
	}
	Tcl_ListObjLength(NULL, zshPtr->inData, &listLen);

	while ((zshPtr->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
	     * more to inflate.







<
|
|
<
<
<
<
|
|
|
<
<
<
|
|
<







1183
1184
1185
1186
1187
1188
1189

1190
1191




1192
1193
1194



1195
1196

1197
1198
1199
1200
1201
1202
1203
		 * And remove it from the list
		 */

		Tcl_ListObjReplace(NULL, zshPtr->inData, 0, 1, 0, NULL);
	    }
	}


	e = inflate(&zshPtr->stream, zshPtr->flush);
	if (e == Z_NEED_DICT && zshPtr->compDictObj) {




	    e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
	    if (e == Z_OK) {
		e = inflate(&zshPtr->stream, zshPtr->flush);



	    }
	};

	Tcl_ListObjLength(NULL, zshPtr->inData, &listLen);

	while ((zshPtr->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
	     * more to inflate.
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
	    Tcl_ListObjReplace(NULL, zshPtr->inData, 0, 1, 0, NULL);
	    listLen--;

	    /*
	     * And call inflate again.
	     */

	    while (1) {
		e = inflate(&zshPtr->stream, zshPtr->flush);
		if (e != Z_NEED_DICT || zshPtr->compDictObj == NULL) {
		    break;
		} else {
		    int dictLen;
		    unsigned char *dictBytes =
			    Tcl_GetByteArrayFromObj(zshPtr->compDictObj,
			    &dictLen);

		    e = inflateSetDictionary(&zshPtr->stream, dictBytes,
			    (unsigned) dictLen);
		    if (e != Z_OK) {
			break;
		    }
		}
	    }
	}
	if (zshPtr->stream.avail_out > 0) {
	    Tcl_SetByteArrayLength(data,
		    existing + count - zshPtr->stream.avail_out);
	}







<
|
|
<
<
<
<
|
<
|
|
<
<
<
<







1243
1244
1245
1246
1247
1248
1249

1250
1251




1252

1253
1254




1255
1256
1257
1258
1259
1260
1261
	    Tcl_ListObjReplace(NULL, zshPtr->inData, 0, 1, 0, NULL);
	    listLen--;

	    /*
	     * And call inflate again.
	     */


	    e = inflate(&zshPtr->stream, zshPtr->flush);
	    if (e == Z_NEED_DICT && zshPtr->compDictObj) {




		e = SetInflateDictionary(&zshPtr->stream,zshPtr->compDictObj);

		if (e == Z_OK) {
		    e = inflate(&zshPtr->stream, zshPtr->flush);




		}
	    }
	}
	if (zshPtr->stream.avail_out > 0) {
	    Tcl_SetByteArrayLength(data,
		    existing + count - zshPtr->stream.avail_out);
	}
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
		    limit = 1;
		}
		break;
	    }
	}

	if (ZlibStackChannelTransform(interp, mode, format, level, chan,
		headerObj) == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, objv[3]);
	return TCL_OK;
    }
    };








|







2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
		    limit = 1;
		}
		break;
	    }
	}

	if (ZlibStackChannelTransform(interp, mode, format, level, chan,
		headerObj, NULL) == NULL) {
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, objv[3]);
	return TCL_OK;
    }
    };

2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
	    }
	    if (cd->outStream.avail_out != (unsigned) cd->outAllocated) {
		if (Tcl_WriteRaw(cd->parent, cd->outBuffer,
			cd->outAllocated - cd->outStream.avail_out) < 0) {
		    /* TODO: is this the right way to do errors on close?
		     * Note: when close is called from FinalizeIOSubsystem
		     * then interp may be NULL */
		    if (!TclInThreadExit()) {
			if (interp) {
			    Tcl_AppendResult(interp,
				    "error while finalizing file: ",
				    Tcl_PosixError(interp), NULL);
			}
		    }
		    result = TCL_ERROR;
		    break;
		}
	    }
	} while (e != Z_STREAM_END);
	e = deflateEnd(&cd->outStream);







|
<
|
|
|
<







2487
2488
2489
2490
2491
2492
2493
2494

2495
2496
2497

2498
2499
2500
2501
2502
2503
2504
	    }
	    if (cd->outStream.avail_out != (unsigned) cd->outAllocated) {
		if (Tcl_WriteRaw(cd->parent, cd->outBuffer,
			cd->outAllocated - cd->outStream.avail_out) < 0) {
		    /* TODO: is this the right way to do errors on close?
		     * Note: when close is called from FinalizeIOSubsystem
		     * then interp may be NULL */
		    if (!TclInThreadExit() && interp) {

			Tcl_AppendResult(interp,
				"error while finalizing file: ",
				Tcl_PosixError(interp), NULL);

		    }
		    result = TCL_ERROR;
		    break;
		}
	    }
	} while (e != Z_STREAM_END);
	e = deflateEnd(&cd->outStream);
2534
2535
2536
2537
2538
2539
2540






2541
2542
2543
2544
2545
2546
2547
    cd->inStream.next_out = (Bytef *) buf;
    cd->inStream.avail_out = toRead;
    if (cd->inStream.next_in == NULL) {
	goto doReadFirst;
    }
    while (1) {
	e = inflate(&cd->inStream, flush);






	if ((e == Z_STREAM_END) || (e==Z_OK && cd->inStream.avail_out==0)) {
	    return toRead - cd->inStream.avail_out;
	}

	/*
	 * Z_BUF_ERROR can be ignored as per http://www.zlib.net/zlib_how.html
	 *







>
>
>
>
>
>







2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
    cd->inStream.next_out = (Bytef *) buf;
    cd->inStream.avail_out = toRead;
    if (cd->inStream.next_in == NULL) {
	goto doReadFirst;
    }
    while (1) {
	e = inflate(&cd->inStream, flush);
	if (e == Z_NEED_DICT && cd->compDictObj) {
	    e = SetInflateDictionary(&cd->inStream, cd->compDictObj);
	    if (e == Z_OK) {
		continue;
	    }
	}
	if ((e == Z_STREAM_END) || (e==Z_OK && cd->inStream.avail_out==0)) {
	    return toRead - cd->inStream.avail_out;
	}

	/*
	 * Z_BUF_ERROR can be ignored as per http://www.zlib.net/zlib_how.html
	 *
2647
2648
2649
2650
2651
2652
2653
2654
2655




2656
2657
2658
2659
2660
2661
2662
    Tcl_Interp *interp,
    const char *optionName,
    const char *value)
{
    ZlibChannelData *cd = instanceData;
    Tcl_DriverSetOptionProc *setOptionProc =
	    Tcl_ChannelSetOptionProc(Tcl_GetChannelType(cd->parent));
    static const char *chanOptions = "flush";
    int haveFlushOpt = (cd->mode == TCL_ZLIB_STREAM_DEFLATE);





    if (haveFlushOpt && optionName && strcmp(optionName, "-flush") == 0) {
	int flushType;

	if (value[0] == 'f' && strcmp(value, "full") == 0) {
	    flushType = Z_FULL_FLUSH;
	} else if (value[0] == 's' && strcmp(value, "sync") == 0) {







|

>
>
>
>







2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
    Tcl_Interp *interp,
    const char *optionName,
    const char *value)
{
    ZlibChannelData *cd = instanceData;
    Tcl_DriverSetOptionProc *setOptionProc =
	    Tcl_ChannelSetOptionProc(Tcl_GetChannelType(cd->parent));
    static const char *chanOptions = "dictionary flush";
    int haveFlushOpt = (cd->mode == TCL_ZLIB_STREAM_DEFLATE);

    if (optionName && strcmp(optionName, "-dictionary") == 0) {
	// TODO dictionary option
    }

    if (haveFlushOpt && optionName && strcmp(optionName, "-flush") == 0) {
	int flushType;

	if (value[0] == 'f' && strcmp(value, "full") == 0) {
	    flushType = Z_FULL_FLUSH;
	} else if (value[0] == 's' && strcmp(value, "sync") == 0) {
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
    Tcl_Interp *interp,
    const char *optionName,
    Tcl_DString *dsPtr)
{
    ZlibChannelData *cd = instanceData;
    Tcl_DriverGetOptionProc *getOptionProc =
	    Tcl_ChannelGetOptionProc(Tcl_GetChannelType(cd->parent));
    static const char *chanOptions = "checksum header";

    /*
     * The "crc" option reports the current CRC (calculated with the Adler32
     * or CRC32 algorithm according to the format) given the data that has
     * been processed so far.
     */








|







2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
    Tcl_Interp *interp,
    const char *optionName,
    Tcl_DString *dsPtr)
{
    ZlibChannelData *cd = instanceData;
    Tcl_DriverGetOptionProc *getOptionProc =
	    Tcl_ChannelGetOptionProc(Tcl_GetChannelType(cd->parent));
    static const char *chanOptions = "checksum dictionary header";

    /*
     * The "crc" option reports the current CRC (calculated with the Adler32
     * or CRC32 algorithm according to the format) given the data that has
     * been processed so far.
     */

2738
2739
2740
2741
2742
2743
2744




2745
2746
2747
2748
2749
2750
2751
	    Tcl_DStringAppendElement(dsPtr, "-checksum");
	    Tcl_DStringAppendElement(dsPtr, buf);
	} else {
	    Tcl_DStringAppend(dsPtr, buf, -1);
	    return TCL_OK;
	}
    }





    /*
     * The "header" option, which is only valid on inflating gzip channels,
     * reports the header that has been read from the start of the stream.
     */

    if ((cd->flags & IN_HEADER) && ((optionName == NULL) ||







>
>
>
>







2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
	    Tcl_DStringAppendElement(dsPtr, "-checksum");
	    Tcl_DStringAppendElement(dsPtr, buf);
	} else {
	    Tcl_DStringAppend(dsPtr, buf, -1);
	    return TCL_OK;
	}
    }

    if (optionName == NULL || strcmp(optionName, "-dictionary") == 0) {
	// TODO dictionary option
    }

    /*
     * The "header" option, which is only valid on inflating gzip channels,
     * reports the header that has been read from the start of the stream.
     */

    if ((cd->flags & IN_HEADER) && ((optionName == NULL) ||
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906



2907
2908
2909
2910
2911
2912
2913
    int format,			/* One of the TCL_ZLIB_FORMAT_* values that
				 * indicates what compressed format to allow.
				 * TCL_ZLIB_FORMAT_AUTO is only supported for
				 * decompressing transforms. */
    int level,			/* What compression level to use. Ignored for
				 * decompressing transforms. */
    Tcl_Channel channel,	/* The channel to attach to. */
    Tcl_Obj *gzipHeaderDictPtr)	/* A description of header to use, or NULL to
				 * use a default. Ignored if not compressing
				 * to produce gzip-format data. */



{
    ZlibChannelData *cd = ckalloc(sizeof(ZlibChannelData));
    Tcl_Channel chan;
    int wbits = 0;
    int e;

    if (mode != TCL_ZLIB_STREAM_DEFLATE && mode != TCL_ZLIB_STREAM_INFLATE) {







|


>
>
>







2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
    int format,			/* One of the TCL_ZLIB_FORMAT_* values that
				 * indicates what compressed format to allow.
				 * TCL_ZLIB_FORMAT_AUTO is only supported for
				 * decompressing transforms. */
    int level,			/* What compression level to use. Ignored for
				 * decompressing transforms. */
    Tcl_Channel channel,	/* The channel to attach to. */
    Tcl_Obj *gzipHeaderDictPtr,	/* A description of header to use, or NULL to
				 * use a default. Ignored if not compressing
				 * to produce gzip-format data. */
    Tcl_Obj *compDictObj)	/* Byte-array object containing compression
				 * dictionary (not dictObj!) to use if
				 * necessary. */
{
    ZlibChannelData *cd = ckalloc(sizeof(ZlibChannelData));
    Tcl_Channel chan;
    int wbits = 0;
    int e;

    if (mode != TCL_ZLIB_STREAM_DEFLATE && mode != TCL_ZLIB_STREAM_INFLATE) {
2932
2933
2934
2935
2936
2937
2938






2939
2940
2941
2942
2943
2944
2945
		    &cd->inHeader.nativeFilenameBuf;
	    cd->inHeader.header.name_max = MAXPATHLEN - 1;
	    cd->inHeader.header.comment = (Bytef *)
		    &cd->inHeader.nativeCommentBuf;
	    cd->inHeader.header.comm_max = MAX_COMMENT_LEN - 1;
	}
    }







    if (format == TCL_ZLIB_FORMAT_RAW) {
	wbits = WBITS_RAW;
    } else if (format == TCL_ZLIB_FORMAT_ZLIB) {
	wbits = WBITS_ZLIB;
    } else if (format == TCL_ZLIB_FORMAT_GZIP) {
	wbits = WBITS_GZIP;







>
>
>
>
>
>







2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
		    &cd->inHeader.nativeFilenameBuf;
	    cd->inHeader.header.name_max = MAXPATHLEN - 1;
	    cd->inHeader.header.comment = (Bytef *)
		    &cd->inHeader.nativeCommentBuf;
	    cd->inHeader.header.comm_max = MAX_COMMENT_LEN - 1;
	}
    }

    if (compDictObj != NULL) {
	cd->compDictObj = Tcl_DuplicateObj(compDictObj);
	Tcl_IncrRefCount(cd->compDictObj);
	Tcl_GetByteArrayFromObj(cd->compDictObj, NULL);
    }

    if (format == TCL_ZLIB_FORMAT_RAW) {
	wbits = WBITS_RAW;
    } else if (format == TCL_ZLIB_FORMAT_ZLIB) {
	wbits = WBITS_ZLIB;
    } else if (format == TCL_ZLIB_FORMAT_GZIP) {
	wbits = WBITS_GZIP;
2976
2977
2978
2979
2980
2981
2982






2983
2984
2985
2986
2987
2988
2989
	cd->outBuffer = ckalloc(cd->outAllocated);
	if (cd->flags & OUT_HEADER) {
	    e = deflateSetHeader(&cd->outStream, &cd->outHeader.header);
	    if (e != Z_OK) {
		goto error;
	    }
	}






    }

    chan = Tcl_StackChannel(interp, &zlibChannelType, cd,
	    Tcl_GetChannelMode(channel), channel);
    if (chan == NULL) {
	goto error;
    }







>
>
>
>
>
>







3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
	cd->outBuffer = ckalloc(cd->outAllocated);
	if (cd->flags & OUT_HEADER) {
	    e = deflateSetHeader(&cd->outStream, &cd->outHeader.header);
	    if (e != Z_OK) {
		goto error;
	    }
	}
	if (cd->compDictObj) {
	    e = SetDeflateDictionary(&cd->outStream, cd->compDictObj);
	    if (e != Z_OK) {
		goto error;
	    }
	}
    }

    chan = Tcl_StackChannel(interp, &zlibChannelType, cd,
	    Tcl_GetChannelMode(channel), channel);
    if (chan == NULL) {
	goto error;
    }
2997
2998
2999
3000
3001
3002
3003



3004
3005
3006
3007
3008
3009
3010
	ckfree(cd->inBuffer);
	inflateEnd(&cd->inStream);
    }
    if (cd->outBuffer) {
	ckfree(cd->outBuffer);
	deflateEnd(&cd->outStream);
    }



    ckfree(cd);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *	Finally, the TclZlibInit function. Used to install the zlib API.







>
>
>







3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
	ckfree(cd->inBuffer);
	inflateEnd(&cd->inStream);
    }
    if (cd->outBuffer) {
	ckfree(cd->outBuffer);
	deflateEnd(&cd->outStream);
    }
    if (cd->compDictObj) {
	Tcl_DecrRefCount(cd->compDictObj);
    }
    ckfree(cd);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *	Finally, the TclZlibInit function. Used to install the zlib API.