1 /*
2 Copyright (C) 2016-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4strmco.ctr
12 */
13
14 /** @file dk4strmco.c The dk4strmco module.
15 */
16
17
18 #include "dk4conf.h"
19
20 #if DK4_HAVE_ZLIB_H
21 #ifndef ZLIB_H_INCLUDED
22 #include <zlib.h>
23 #define ZLIB_H_INCLUDED 1
24 #endif
25 #endif
26
27 #if DK4_HAVE_LIMITS_H
28 #ifndef LIMITS_H_INCLUDED
29 #include <limits.h>
30 #define LIMITS_H_INCLUDED 1
31 #endif
32 #endif
33
34 #include <libdk4c/dk4rle.h>
35 #include <libdk4c/dk4a85e.h>
36 #include <libdk4c/dk4strmco.h>
37 #include <libdk4base/dk4mem.h>
38 #include <libdk4base/dk4memrs.h>
39 #include <libdk4c/dk4lzwe.h>
40
41 #if DK4_HAVE_ASSERT_H
42 #ifndef ASSERT_H_INCLUDED
43 #include <assert.h>
44 #define ASSERT_H_INCLUDED 1
45 #endif
46 #endif
47
48
49
50
51
52 #ifndef DK4_STRMCO_ZBUF_SIZE
53 #define DK4_STRMCO_ZBUF_SIZE 4096
54 #endif
55
56
57
58 /** Compressor data structure.
59 */
60 typedef struct {
61 char zbuf[DK4_STRMCO_ZBUF_SIZE]; /**< Output buffer. */
62 union {
63 #if DK4_HAVE_ZLIB_H
64 z_stream zs; /**< Flate compression structure. */
65 #endif
66 dk4_lzwe_t lzw; /**< LZW compression structure. */
67 } u_co; /**< Compression structures. */
68 union {
69 dk4_rl_enc_t rle; /**< Run-length encoder. */
70 } u_pp; /**< Preprocessing structures. */
71 union {
72 dk4_a85_enc_t a85; /**< ASCII-85 encoder. */
73 } u_oe; /**< Output encoding structures. */
74 dk4_stream_t *dststrm; /**< Destination stream. */
75 size_t ll; /**< Line length. */
76 int pp; /**< Preprocessing. */
77 int co; /**< Compression. */
78 int oe; /**< Output encoding. */
79 int fl; /**< Flags. */
80 } compressor_t;
81
82
83
84 /** Newline.
85 */
86 static char nl[] = {
87 '\n', '\0'
88 };
89
90
91
92 /** Carriage return and newline.
93 */
94 static char crnl[] = {
95 '\r', '\n', '\0'
96 };
97
98
99
100 /** Finalizer for ASCII-Hex encoding.
101 */
102 static char ahfin[] = {
103 '>', '\0'
104 };
105
106
107
108 /** Finalizer for ASCII-85 encoding.
109 */
110 static char a85fin[] = {
111 '~', '>', '\0'
112 };
113
114
115
116 /** Hexadecimal digits using lower case characters.
117 */
118 static char lower[] = {
119 '0', '1', '2', '3', '4', '5', '6', '7',
120 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', '\0'
121 };
122
123
124
125 /** Hexadecimal digits using upper case characters.
126 */
127 static char upper[] = {
128 '0', '1', '2', '3', '4', '5', '6', '7',
129 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '\0'
130 };
131
132
133
134 /** Write newline to destination stream.
135 @param co Compressor structure.
136 @return 1 on success, 0 on error.
137 */
138 static
139 int
dk4strmco_nl(compressor_t * co)140 dk4strmco_nl(compressor_t *co)
141 {
142 int back = 0;
143
144 #if DK4_USE_ASSERT
145 assert(NULL != co);
146 #endif
147 if (0 != (DK4_STRMCO_FL_CR_NL & (co->fl))) {
148 back = dk4stream_write(co->dststrm, crnl, 2, NULL);
149 }
150 else {
151 back = dk4stream_write(co->dststrm, nl, 1, NULL);
152 }
153
154 return back;
155 }
156
157
158
159
160 /** Write bytes to compressor at output encoding level.
161 @param co Compressor to write to.
162 @param b Buffer start address.
163 @param sz Number of bytes to write.
164 @param szo Address of variable for number of bytes written, may be NULL.
165 @return 1 on success, 0 on error.
166 */
167 static
168 int
dk4strmco_co_oe(compressor_t * co,const char * b,size_t sz,size_t * szo)169 dk4strmco_co_oe(
170 compressor_t *co,
171 const char *b,
172 size_t sz,
173 size_t *szo
174 )
175 {
176 char buf[8]; /* Buffer for hexadecimal digits. */
177 const char *dptr; /* Pointer to A85 encoding result. */
178 size_t osz = 0; /* Number of bytes processed. */
179 size_t szd = 0; /* A85 encoding result length. */
180 size_t i = 0; /* Index of current byte to process. */
181 size_t j = 0; /* Index of cur out char. */
182 int back = 0; /* Function result. */
183 int res; /* Result from various operations. */
184 unsigned us; /* Index in hex digits array. */
185 unsigned char uc; /* UC version of current character */
186
187 #if DK4_USE_ASSERT
188 assert(NULL != co);
189 assert(NULL != b);
190 assert(0 < sz);
191 #endif
192 switch (co->oe) {
193 case DK4_STRMCO_OE_ASCII85 : {
194
195 back = 1;
196 for (i = 0; ((i < sz) && (1 == back)); i++) {
197 switch (
198 dk4a85_enc_add(
199 &(co->u_oe.a85), (unsigned char)(b[i]), NULL
200 )
201 ) {
202 case DK4_EDSTM_ACCEPT : {
203 osz++;
204 } break;
205 case DK4_EDSTM_FINISHED : {
206 dptr = NULL;
207 szd = 0;
208 res = dk4a85_enc_output(
209 &dptr, &szd, &(co->u_oe.a85), NULL
210 );
211 if (0 < res) {
212 if (0 < szd) {
213 #if VERSION_BEFORE_20161019
214 res = dk4stream_write(
215 co->dststrm, dptr, szd, NULL
216 );
217 if (0 < res) {
218 osz++;
219 co->ll += szd;
220 if (0 != (DK4_STRMCO_FL_NL_OE & (co->fl))) {
221 if (74 <= co->ll) {
222 res = dk4strmco_nl(co);
223 if (0 < res) {
224 co->ll = 0;
225 }
226 else {
227 back = 0;
228 }
229 }
230 }
231 }
232 else {
233 back = 0;
234 }
235 #else
236 back = 1;
237 for (j = 0; ((j < szd) && (1 == back)); j++) {
238 res = dk4stream_write_byte(
239 co->dststrm, dptr[j], NULL
240 );
241 if (0 < res) {
242 osz++;
243 co->ll += 1;
244 if (75 <= co->ll) {
245 res = dk4strmco_nl(co);
246 if (0 < res) {
247 co->ll = 0;
248 }
249 else {
250 back = 0;
251 }
252 }
253 }
254 else {
255 back = 0;
256 }
257 }
258 #endif
259 }
260 else {
261 osz++;
262 }
263 }
264 else {
265 back = 0;
266 }
267 } break;
268 default : {
269 back = 0;
270 } break;
271 }
272 }
273 } break;
274 case DK4_STRMCO_OE_HEX : {
275
276 back = 1;
277 buf[2] = '\0';
278 for (i = 0; ((i < sz) && (1 == back)); i++) {
279 uc = (unsigned char)(b[i]);
280 us = 0x000FU & ((unsigned char)uc);
281 if (0 != (DK4_STRMCO_FL_UPPER_OE & (co->fl))) {
282 buf[1] = upper[us];
283 }
284 else {
285 buf[1] = lower[us];
286 }
287 us = 0x000FU & (((unsigned char)uc) >> 4);
288 if (0 != (DK4_STRMCO_FL_UPPER_OE & (co->fl))) {
289 buf[0] = upper[us];
290 }
291 else {
292 buf[0] = lower[us];
293 }
294 res = dk4stream_write(co->dststrm, buf, 2, NULL);
295 co->ll += 2;
296 if (0 < res) {
297 osz++;
298 if (0 != (DK4_STRMCO_FL_NL_OE & (co->fl))) {
299 if (78 <= co->ll) {
300 res = dk4strmco_nl(co);
301 if (0 < res) {
302 co->ll = 0;
303 }
304 else {
305 back = 0;
306 }
307 }
308 }
309 }
310 else {
311 back = 0;
312 }
313 }
314 } break;
315 default : {
316
317 back = dk4stream_write(co->dststrm, b, sz, NULL);
318 if (0 != back) {
319 osz = sz;
320 }
321 } break;
322 }
323 if (NULL != szo) { *szo = osz; }
324
325 return back;
326 }
327
328
329
330 /** Write bytes to compressor at compression level.
331 @param co Compressor to write to.
332 @param b Buffer start address.
333 @param sz Number of bytes to write.
334 @param szo Address of variable for number of bytes written, may be NULL.
335 @return 1 on success, 0 on error.
336 */
337 static
338 int
dk4strmco_co_co(compressor_t * co,const char * b,size_t sz,size_t * szo)339 dk4strmco_co_co(
340 compressor_t *co,
341 const char *b,
342 size_t sz,
343 size_t *szo
344 )
345 {
346 const unsigned char *cptr;
347 size_t osz = 0; /* Number of bytes processed successfully. */
348 size_t used = 0; /* Used bytes in output buffer. */
349 size_t i = 0; /* Index of current LZW byte to process. */
350 size_t lzwsz = 0; /* Bytes from LZW compression. */
351 int back = 0; /* Function result. */
352 int res = 0; /* Result from various operations. */
353
354 #if DK4_USE_ASSERT
355 assert(NULL != co);
356 assert(NULL != b);
357 assert(0 < sz);
358 #endif
359 switch (co->co) {
360 case DK4_STRMCO_CO_FLATE : {
361
362 if (((dk4_um_t)(UINT_MAX)) >= ((dk4_um_t)sz)) {
363 back = 1;
364 co->u_co.zs.next_in = (unsigned char *)b;
365 co->u_co.zs.avail_in = (unsigned int)sz;
366 do {
367 co->u_co.zs.next_out = (unsigned char *)(&(co->zbuf[0]));
368 co->u_co.zs.avail_out = DK4_STRMCO_ZBUF_SIZE;
369 res = deflate(&(co->u_co.zs), Z_NO_FLUSH);
370 switch (res) {
371 case Z_OK : {
372 used = DK4_STRMCO_ZBUF_SIZE - co->u_co.zs.avail_out;
373 if (0 < used) {
374 res = dk4strmco_co_oe(
375 co, &(co->zbuf[0]), used, NULL
376 );
377 if (0 < res) {
378 osz = sz - co->u_co.zs.avail_in;
379 }
380 else {
381 back = 0;
382 }
383 }
384 else {
385 osz = sz - co->u_co.zs.avail_in;
386 }
387 } break;
388 default : {
389 back = 0;
390 } break;
391 }
392 } while ((0 < co->u_co.zs.avail_in) && (1 == back));
393 if (NULL != szo) { *szo = osz; }
394 } else {
395 }
396 } break;
397 case DK4_STRMCO_CO_LZW : {
398 back = 1;
399 for (i = 0; ((1 == back) && (i < sz)); i++) {
400 res = dk4lzwe_add(&(co->u_co.lzw), (unsigned char)(b[i]), NULL);
401 switch (res) {
402 case DK4_EDSTM_ACCEPT : {
403 osz++;
404 } break;
405 case DK4_EDSTM_FINISHED : {
406 cptr = NULL;
407 lzwsz = 0;
408 res = dk4lzwe_output(
409 &cptr, &lzwsz, &(co->u_co.lzw), NULL
410 );
411 if ((0 != res) && (NULL != cptr) && (0 < lzwsz)) {
412 back = dk4strmco_co_oe(
413 co, (const char *)cptr, lzwsz, NULL
414 );
415 if (0 != back) {
416 osz++;
417 }
418 }
419 else {
420 back = 0;
421 }
422 } break;
423 case DK4_EDSTM_ERROR : {
424 back = 0;
425 } break;
426 }
427 }
428 if (NULL != szo) { *szo = osz; }
429 } break;
430 default : {
431
432 back = dk4strmco_co_oe(co, b, sz, szo);
433 } break;
434 }
435
436 return back;
437 }
438
439
440
441 /** Write bytes to compressor at preprocessor level.
442 @param co Compressor to write to.
443 @param b Buffer start address.
444 @param sz Number of bytes to write.
445 @param szo Address of variable for number of bytes written, may be NULL.
446 @return 1 on success, 0 on error.
447 */
448 static
449 int
dk4strmco_co_write(compressor_t * co,const char * b,size_t sz,size_t * szo)450 dk4strmco_co_write(
451 compressor_t *co,
452 const char *b,
453 size_t sz,
454 size_t *szo
455 )
456 {
457 const unsigned char *rleptr; /* RL encoding result */
458 size_t osz = 0; /* Bytes processed successfully */
459 size_t i; /* Running index of current byte */
460 size_t rlesz; /* Size of RL encoding result */
461 int back = 0; /* Function result */
462 int res; /* Result from various operations */
463
464 #if DK4_USE_ASSERT
465 assert(NULL != co);
466 #endif
467 switch (co->pp) {
468 case DK4_STRMCO_PP_RUNLENGTH : {
469
470 back = 1;
471 for (i = 0; ((i < sz) && (0 != back)); i++) {
472 switch (dk4rle_add(&(co->u_pp.rle),(unsigned char)(b[i]),NULL))
473 {
474 case DK4_EDSTM_FINISHED : {
475 rleptr = NULL;
476 rlesz = 0;
477 res = dk4rle_output(
478 &rleptr, &rlesz, &(co->u_pp.rle), NULL
479 );
480 if (0 != res) {
481 res = dk4strmco_co_co(
482 co, (const char *)rleptr, rlesz, NULL
483 );
484 if (0 != res) {
485 osz++;
486 }
487 else {
488 back = 0;
489 }
490 }
491 else {
492 back = 0;
493 }
494 } break;
495 case DK4_EDSTM_ERROR : {
496 back = 0;
497 } break;
498 default : {
499 osz++;
500 } break;
501 }
502 }
503 if (NULL != szo) { *szo = osz; }
504 } break;
505 default : {
506
507 back = dk4strmco_co_co(co, b, sz, szo);
508 } break;
509 }
510
511 return back;
512 }
513
514
515
516 /** Flush data in output encoders if used.
517 @param co Compressor structure.
518 @return 1 on success, 0 on error.
519 */
520 static
521 int
dk4strmco_co_oe_close(compressor_t * co)522 dk4strmco_co_oe_close(compressor_t *co)
523 {
524 const char *dptr = NULL;
525 size_t sz = 0;
526 size_t j = 0;
527 int back = 1;
528 int res = 0;
529
530 #if DK4_USE_ASSERT
531 assert(NULL != co);
532 #endif
533 switch (co->oe) {
534 case DK4_STRMCO_OE_ASCII85 : {
535
536 switch (dk4a85_enc_finish(&(co->u_oe.a85), NULL)) {
537 case DK4_EDSTM_FINISHED : {
538 if (0 < dk4a85_enc_output(&dptr,&sz,&(co->u_oe.a85),NULL)) {
539 if (0 < sz) {
540 #if VERSION_BEFORE_20161019
541 back = dk4stream_write(co->dststrm, dptr, sz, NULL);
542 #else
543 back = 1;
544 for (j = 0; ((j < sz) && (1 == back)); j++) {
545 res = dk4stream_write_byte(
546 co->dststrm, dptr[j], NULL
547 );
548 if (0 < res) {
549 co->ll += 1;
550 if (75 <= co->ll) {
551 res = dk4strmco_nl(co);
552 if (0 < res) {
553 co->ll = 0;
554 }
555 else {
556 back = 0;
557 }
558 }
559 }
560 else {
561 back = 0;
562 }
563 }
564 #endif
565 }
566 }
567 else {
568 back = 0;
569 }
570 } break;
571 }
572 if (0 != (DK4_STRMCO_FL_EOD_OE & (co->fl))) {
573
574 res = dk4stream_write(co->dststrm, a85fin, 2, NULL);
575 if (0 == res) {
576 back = 0;
577 }
578 }
579 if (0 != (DK4_STRMCO_FL_NL_OE & (co->fl))) {
580
581 if (0 == dk4strmco_nl(co)) {
582 back = 0;
583 }
584 }
585 } break;
586 case DK4_STRMCO_OE_HEX : {
587 if (0 != (DK4_STRMCO_FL_EOD_OE & (co->fl))) {
588
589 back = dk4stream_write(co->dststrm, ahfin, 1, NULL);
590 }
591 if (0 != (DK4_STRMCO_FL_NL_OE & (co->fl))) {
592
593 if (0 == dk4strmco_nl(co)) {
594 back = 0;
595 }
596 }
597 } break;
598 }
599
600 return back;
601 }
602
603
604
605 /** Flush data from flate compressor if used.
606 @param co Compressor structure.
607 @return 1 on success, 0 on error.
608 */
609 static
610 int
dk4strmco_co_co_close(compressor_t * co)611 dk4strmco_co_co_close(compressor_t *co)
612 {
613 const unsigned char *cptr;
614 size_t used = 0;
615 int back = 1;
616 int zres = Z_OK;
617 int res = 0;
618
619 #if DK4_USE_ASSERT
620 assert(NULL != co);
621 #endif
622 switch (co->co) {
623 case DK4_STRMCO_CO_FLATE : {
624
625 co->u_co.zs.next_in = (unsigned char *)nl;
626 co->u_co.zs.avail_in = 0;
627 do {
628 co->u_co.zs.next_out = (unsigned char *)(&(co->zbuf[0]));
629 co->u_co.zs.avail_out = DK4_STRMCO_ZBUF_SIZE;
630 zres = deflate(&(co->u_co.zs), Z_FINISH);
631
632 switch (zres) {
633 case Z_OK : case Z_STREAM_END : {
634 used = DK4_STRMCO_ZBUF_SIZE - co->u_co.zs.avail_out;
635
636 if (0 < used) {
637 res = dk4strmco_co_oe(co,&(co->zbuf[0]),used,NULL);
638 if (0 == res) {
639 back = 0;
640 }
641 }
642 } break;
643 default : {
644 back = 0;
645 } break;
646 }
647 } while ((Z_OK == zres) && (1 == back));
648
649 if (Z_OK != deflateEnd(&(co->u_co.zs))) {
650 back = 0;
651 }
652 } break;
653 case DK4_STRMCO_CO_LZW : {
654 res = dk4lzwe_finish(&(co->u_co.lzw), NULL);
655 switch (res) {
656 case DK4_EDSTM_FINISHED : {
657 cptr = NULL;
658 used = 0;
659 res = dk4lzwe_output(
660 &cptr, &used, &(co->u_co.lzw), NULL
661 );
662 if ((0 != res) && (NULL != cptr) && (0 < used)) {
663 back = dk4strmco_co_oe(
664 co, (const char *)cptr, used, NULL
665 );
666 }
667 else {
668 back = 0;
669 }
670 } break;
671 case DK4_EDSTM_ERROR : {
672 back = 0;
673 } break;
674 }
675 } break;
676 }
677
678 return back;
679 }
680
681
682
683 /** Flush data from run-length encoder if used.
684 @param co Compressor structure.
685 @return 1 on success, 0 on error.
686 */
687 static
688 int
dk4strmco_co_pp_close(compressor_t * co)689 dk4strmco_co_pp_close(compressor_t *co)
690 {
691 const unsigned char *dptr = NULL;
692 size_t szd = 0;
693 int back = 1;
694 int res;
695
696 #if DK4_USE_ASSERT
697 assert(NULL != co);
698 #endif
699 switch (co->pp) {
700 case DK4_STRMCO_PP_RUNLENGTH : {
701
702 switch (dk4rle_finish(&(co->u_pp.rle), NULL)) {
703 case DK4_EDSTM_ACCEPT : {
704 } break;
705 case DK4_EDSTM_FINISHED : {
706
707 if (0 < dk4rle_output(&dptr, &szd, &(co->u_pp.rle), NULL)) {
708 res = dk4strmco_co_write(
709 co, (const char *)dptr, szd, NULL
710 );
711 if (0 == res) {
712 back = 0;
713 }
714 }
715 else {
716 back = 0;
717 }
718 } break;
719 default : {
720 } break;
721 }
722 } break;
723 }
724
725 return back;
726 }
727
728
729
730 /** Finish output (flush data stored in the encoders).
731 @param co Compressor structure.
732 @return 1 on success, 0 on error.
733 */
734 static
735 int
dk4strmco_co_close(compressor_t * co)736 dk4strmco_co_close(compressor_t *co)
737 {
738 int back = 1;
739
740 #if DK4_USE_ASSERT
741 assert(NULL != co);
742 #endif
743 /* Flush preprocessor (run-length encoder).
744 */
745 if (0 == dk4strmco_co_pp_close(co)) {
746 back = 0;
747 }
748 /* Flush compressor (flate stream).
749 */
750 if (0 == dk4strmco_co_co_close(co)) {
751 back = 0;
752 }
753 /* Flush output encoder (ASCII-Hex or ASCII-85 encoder).
754 */
755 if (0 == dk4strmco_co_oe_close(co)) {
756 back = 0;
757 }
758 /* Release memory.
759 */
760
761 if (0 == dk4mem_reset_secure(co, sizeof(compressor_t), NULL)) {
762 back = 0;
763 }
764
765 dk4mem_free(co);
766
767 return back;
768 }
769
770
771
772 static
773 void
dk4strmco_handler(dk4_stream_api_t * api)774 dk4strmco_handler(dk4_stream_api_t *api)
775 {
776 compressor_t *co = NULL;
777
778 #if DK4_USE_ASSERT
779 assert(NULL != api);
780 #endif
781 if (NULL != api) {
782 api->res = 0;
783 api->sz_out = 0;
784 co = (compressor_t *)(api->d);
785 switch (api->cmd) {
786 case DK4_STREAM_API_WRITE : {
787 if (0 < api->sz_in) {
788 api->res = dk4strmco_co_write(
789 co, api->b, api->sz_in, &(api->sz_out)
790 );
791 }
792 else {
793 api->res = 1;
794 }
795 } break;
796 case DK4_STREAM_API_FLUSH : {
797 /*
798 Do nothing but indicate success.
799 Otherwise closing a stream will return an error.
800 */
801 api->res = 1;
802 } break;
803 case DK4_STREAM_API_CLOSE : {
804 api->res = dk4strmco_co_close(co);
805 } break;
806 case DK4_STREAM_API_ZERO_READ_IS_EOF : {
807 api->res = 0;
808 } break;
809 default : {
810 /* Error: Functions not available */
811 } break;
812 }
813 }
814
815 }
816
817
818
819 dk4_stream_t *
dk4strmco_open(dk4_stream_t * strm,enum dk4_strmco_pp pp,enum dk4_strmco_co co,enum dk4_strmco_oe oe,int fl,dk4_er_t * erp)820 dk4strmco_open(
821 dk4_stream_t *strm,
822 enum dk4_strmco_pp pp,
823 enum dk4_strmco_co co,
824 enum dk4_strmco_oe oe,
825 int fl,
826 dk4_er_t *erp
827 )
828 {
829 dk4_stream_t *back = NULL;
830 compressor_t *cc = NULL;
831
832 #if DK4_USE_ASSERT
833 assert(NULL != strm);
834 #endif
835 if (NULL != strm) {
836 /* Allocate compressor and set up.
837 */
838
839 cc = dk4mem_new(compressor_t,1,erp);
840 if (NULL != cc) {
841 cc->dststrm = strm;
842 cc->pp = pp;
843 cc->co = co;
844 cc->oe = oe;
845 cc->fl = fl;
846 cc->ll = 0;
847 switch (pp) {
848 case DK4_STRMCO_PP_RUNLENGTH : {
849
850 dk4rle_init(
851 &(cc->u_pp.rle),
852 ((0 != (DK4_STRMCO_FL_EOD_PP & fl)) ? 1 : 0),
853 NULL
854 );
855 } break;
856 default : {
857 } break;
858 }
859 switch (co) {
860 case DK4_STRMCO_CO_FLATE : {
861
862 cc->u_co.zs.zalloc = Z_NULL;
863 cc->u_co.zs.zfree = Z_NULL;
864 cc->u_co.zs.opaque = Z_NULL;
865
866 if (Z_OK != deflateInit(&(cc->u_co.zs), 9)) {
867
868 dk4mem_free(cc);
869 cc = NULL;
870
871 }
872 } break;
873 case DK4_STRMCO_CO_LZW : {
874
875 if (0 == dk4lzwe_init(&(cc->u_co.lzw), NULL)) {
876
877 dk4mem_free(cc);
878 cc = NULL;
879
880 }
881 } break;
882 default : {
883 } break;
884 }
885 switch (oe) {
886 case DK4_STRMCO_OE_ASCII85 : {
887
888 dk4a85_enc_init(&(cc->u_oe.a85), 1, NULL);
889 } break;
890 default : {
891 } break;
892 }
893 }
894 #if TRACE_DEBUG
895 else {
896 }
897 #endif
898 /* If the compressor was set up successfully, create stream.
899 */
900 if (NULL != cc) {
901
902 back = dk4stream_open(
903 cc, dk4strmco_handler, DK4_STREAM_WRITE, 0, 4096, erp
904 );
905 /*
906 When failed to create stream, we must release the compressor.
907 */
908 if (NULL == back) {
909 /*
910 Release dynamic resources assigned to components.
911 */
912
913 switch (co) {
914 case DK4_STRMCO_CO_FLATE : {
915
916 (void)deflateEnd(&(cc->u_co.zs));
917 } break;
918 case DK4_STRMCO_CO_LZW : {
919
920 (void)dk4lzwe_finish(&(cc->u_co.lzw), NULL);
921 } break;
922 default : {
923 } break;
924 }
925
926 dk4mem_free(cc);
927 }
928 #if TRACE_DEBUG
929 else {
930 }
931 #endif
932 }
933 }
934 else {
935 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
936 }
937
938 return back;
939 }
940
941
942
943 /* vim: set ai sw=4 ts=4 : */
944
945