/* Copyright (c) 2000-2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dkof.c Output filtering module. */ /** Inside the dkof module. */ #define DK_OF_C 1 #include "dkof.h" #include "dkstream.h" #include "dkmem.h" #include "dkerror.h" #include "dksto.h" $(trace-include) /** Convert size_t to unsigned long. */ #define TR_UL(x) ((unsigned long)x) /** LZW flag: Have a table entry. */ #define LZW_FLAG_HAVE_STRING 1 /** LZW flag: Error occured. */ #define LZW_FLAG_ERROR_OCCURED 2 /** LZW compression table entry. */ typedef struct { dk_uword r; /**< Result of combintation \a s+c. */ dk_uword s; /**< Previous combination. */ unsigned char c; /**< Current input. */ } lzw_entry; static size_t add_to_cell DK_PR((dk_of_t *o,dk_of_cell_t *c,size_t n,char *b,size_t l)); /** Coefficients used for ASCII-85 encoding. */ static unsigned long a85[] = { (85UL * 85UL * 85UL * 85UL), (85UL * 85UL * 85UL), (85UL * 85UL), 85UL, 1UL }; /** Characters to show hexadecimal numbers. */ static char hex_digits[] = { "0123456789ABCDEF" }; /** Line end with carriage return. */ static char eol1[] = { "\r\n" }; /** Line end without carriage return. */ static char eol2[] = { "\n" }; /** Finalizer for ASCII-85 encoded data. */ static char a85end[] = { "~>" }; /** Finalizer for ASCII-Hex encoded data. */ static char ahend[] = { ">" }; #if 0 static unsigned short bits[] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000 }; #endif /** Bit masks to mask trailing bits. */ static unsigned char mask_trailing_bits[] = { /* 1111 1111 */ 0xFF, /* 1111 1110 */ 0xFE, /* 1111 1100 */ 0xFC, /* 1111 1000 */ 0xF8, /* 1111 0000 */ 0xF0, /* 1110 0000 */ 0xE0, /* 1100 0000 */ 0xC0, /* 1000 0000 */ 0x80, /* 0000 0000 */ 0x00 }; /** Bit masks to mask leading bits. */ static unsigned char mask_leading_bits[] = { /* 0000 0000 */ 0x00, /* 0000 0001 */ 0x01, /* 0000 0011 */ 0x03, /* 0000 0111 */ 0x07, /* 0000 1111 */ 0x0f, /* 0001 1111 */ 0x1f, /* 0011 1111 */ 0x3f, /* 0111 1111 */ 0x7f, /* 1111 1111 */ 0xff }; /** Shift \a c \a n bits to the left and reset the trailing bits. */ #define SHIFTBITS(c,n) (n ? (\ (c << n) & mask_trailing_bits[n]\ ) : c) /** Get the last \a r bits from \a c shifted \a (n-r) to the right. */ #define GETBITS(c,n,r) (n ? (r ? (\ (unsigned char)(((n > r) ? (c >> (n - r)) : c) & mask_leading_bits[r])\ ) : 0) : 0) /** Write data from a cell downwards into the filter chain. @param o Output filter. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_from_cell DK_P4(dk_of_t *,o,size_t,n,char *,b,size_t,l) { size_t back = 0; $? "+ add_from_cell %s %lu %s %lu", TR_PTR(o), TR_UL(n), TR_PTR(b), TR_UL(l) if(n) { $? ". adding to downside cell %lu", TR_UL((n-1)) back = add_to_cell(o,&((o->cells)[(n-1)]),(n-1),b,l); $? ". add_to_cell()=%d", back } else { $? ". adding to target stream" if(o->target) { back = dkstream_write(o->target, b, l); $? ". dkstream_write()=%d", back } else { $? "! setup problem, no target stream" } } $? "- add_from_cell (%lu) %lu", TR_UL(n), TR_UL(back) return back; } #if DK_HAVE_ZLIB_H /** Write data into a filter cell (not final write operation). @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return 1 on success, 0 on error. */ static int write_flate_not_final DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; int err, cc; uLong odiff; size_t sz; $? "+ write_flate_not_final %s %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n) cc = 1; ((c->c).flate.zs)->next_in = (c->c).flate.ibuffer; ((c->c).flate.zs)->avail_in = (c->c).flate.used; back = 1; while(cc) { cc = 0; ((c->c).flate.zs)->next_out = (c->c).flate.obuffer; ((c->c).flate.zs)->avail_out = (c->c).flate.o_length; err = deflate((c->c).flate.zs, 0); switch(err) { case Z_OK: { if(((c->c).flate.zs)->avail_in) { cc = 1; } odiff = (c->c).flate.o_length - ((c->c).flate.zs)->avail_out; sz = (size_t)odiff; if(add_from_cell(o,n,(char *)((c->c).flate.obuffer),sz) != sz) { back = 0; } } break; default: { back = 0; (c->c).flate.stillok = -1; } break; } } $? "- write_flate_not_final %d", back return back; } /** Write data into a flate compressing cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_flate_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; char *ptr; size_t i; $? "+ add_to_flate_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) if(((c->c).flate.zs) && ((c->c).flate.ibuffer) && ((c->c).flate.obuffer)) { if(((c->c).flate.i_length) && ((c->c).flate.o_length)) { if(((c->c).flate.stillok) == 1) { ptr = b; for(i = 0; i < l; i++) { ((c->c).flate.ibuffer)[(c->c).flate.used] = (Bytef)(*(ptr++)); (c->c).flate.used += (uLong)1UL; if(((c->c).flate.used) >= ((c->c).flate.i_length)) { if(write_flate_not_final(o,c,n)) { back++; } (c->c).flate.used = (uLong)0UL; } else { back++; } } } else { $? "! we already had an error" } } else { $? "! setup problem" } } else { $? "! setup problem" } $? "- add_to_flate_cell %lu", TR_UL(back) return back; } #endif /** Write data into an ASCII-85 encoding cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @return 1 on success, 0 on error */ static int write_a85_buffer DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; char buffer[6]; unsigned long v, ul; unsigned char uc; size_t i; $? "+ write_a85_buffer %s %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n) v = (c->c).a85.a85val; for(i = 0; i < 5; i++) { ul = 33UL + v / a85[i]; v = v % a85[i]; uc = (unsigned char)((unsigned)ul); buffer[i] = uc; } if(add_from_cell(o,n,buffer,(1 + (c->c).a85.used)) == (1 + (c->c).a85.used)) { back = 1; } (c->c).a85.linepos += (1 + (c->c).a85.used); if(((c->c).a85.maxlinepos) > 0) { if(((c->c).a85.linepos) >= (c->c).a85.maxlinepos) { if((o->flags) & 1) { if(add_from_cell(o,n,eol1,2) != 2) { back = 0; } } else { if(add_from_cell(o,n,eol2,1) != 1) { back = 0; } } (c->c).a85.linepos = 0; } } (c->c).a85.a85val = 0UL; (c->c).a85.used = 0; $? "- write_a85_buffer %d", back return back; } #if DK_HAVE_LZW /** Clear LZW compression table of LZW compressing cell. @param c Filter cell. */ static void clear_lzw_table DK_P1(dk_of_cell_t *,c) { lzw_entry *ep; $? "+ clear_lzw_table" if((c->c).lzw.table) { if((c->c).lzw.ti) { dksto_it_reset((c->c).lzw.ti); while((ep = (lzw_entry *)dksto_it_next((c->c).lzw.ti)) != NULL) { dk_delete(ep); } dksto_remove_all((c->c).lzw.table); } } (c->c).lzw.ob = 9; (c->c).lzw.lte = 257; $? "- clear_lzw_table" } /** Add output bit to an LZW compressing cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param i Bit value. @return 1 on success, 0 on error. */ static int lzw_output_bit DK_P4(dk_of_t *,o, dk_of_cell_t *,c, size_t,n, int, i) { int back = 1; char buffer[2]; $? "+ lzw_output_bit %d", (i ? 1 : 0) (c->c).lzw.oc = (c->c).lzw.oc << 1; if(i) { (c->c).lzw.oc |= 0x01; } else { (c->c).lzw.oc &= 0xFE; } $? ". bitsused = %d back=%d", (int)((c->c).lzw.bitsused), back (c->c).lzw.bitsused += 1; if((c->c).lzw.bitsused >= 8) { $? ". must flush" buffer[0] = (char)((c->c).lzw.oc); buffer[1] = 0x00; $? ". back = %d", back if(add_from_cell(o, n, buffer, 1) != 1) { $? "! error in add_from_cell" back = 0; } (c->c).lzw.bitsused = 0; } $? "- lzw_output_bit %d", back return back; } /** Output a string produced by LZW compression. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param chr 9-to-12 bit character to add. @return 1 on success, 0 on error. */ static int lzw_output_string DK_P4(dk_of_t *,o, dk_of_cell_t *,c, size_t,n, dk_uword,chr) { int back = 1; /* 1 indicates success, 0 error */ unsigned char buffer; /* buffer character */ unsigned short bu; unsigned short br; /* number of output bits remaining */ unsigned short itl; /* number of bits to handle in current loop */ br = (c->c).lzw.ob; buffer = (c->c).lzw.oc; bu = (c->c).lzw.bitsused; do { itl = 8 - bu; itl = ((itl > br) ? br : itl); /* change buffer */ buffer = SHIFTBITS(buffer,itl) | GETBITS(chr,br,itl); br -= itl; bu += itl; if(bu >= 8) { bu = 0; if(add_from_cell(o, n, (char *)(&buffer), 1) != 1) { back = 0; } buffer = 0x00; } } while((br > 0) && (back)); (c->c).lzw.oc = buffer; (c->c).lzw.bitsused = bu; return back; } /** Add one byte to an LZW compressing cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param chr Character to add. @return 1 on success, 0 on error. */ static int add_byte_to_lzw DK_P4(dk_of_t *,o, dk_of_cell_t *,c, size_t,n, unsigned char,chr) { int back = 0; lzw_entry lzwe, *lzwptr; $? "+ add_byte_to_lzw" if(((c->c).lzw.table) && ((c->c).lzw.ti)) { if(((c->c).lzw.fl) & LZW_FLAG_HAVE_STRING) { lzwe.s = (c->c).lzw.s; lzwe.c = chr; lzwptr = dksto_it_find_like((c->c).lzw.ti, (void *)(&lzwe), 0); if(lzwptr) { $? ". combination found" (c->c).lzw.s = lzwptr->r; (c->c).lzw.fl |= LZW_FLAG_HAVE_STRING; back = 1; } else { $? ". combination not yet found" lzwptr = dk_new(lzw_entry,1); if(lzwptr) { lzwptr->s = (c->c).lzw.s; lzwptr->c = chr; (c->c).lzw.lte = (c->c).lzw.lte + 1; lzwptr->r = (c->c).lzw.lte; if(dksto_add((c->c).lzw.table, (void *)lzwptr)) { if(lzw_output_string(o, c, n, (c->c).lzw.s)) { (c->c).lzw.s = (dk_uword)chr; if((c->c).lzw.lte >= 4095) { if(lzw_output_string(o, c, n, (dk_uword)256)) { clear_lzw_table(c); back = 1; } else { back = 0; (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } } else { if(((c->c).lzw.lte) == 2047) { (c->c).lzw.ob = 12; back = 1; } else { if((c->c).lzw.lte == 1023) { (c->c).lzw.ob = 11; back = 1; } else { if((c->c).lzw.lte == 511) { (c->c).lzw.ob = 10; back = 1; } else { back = 1; } } } } } else { back = 0; } } else { dk_delete(lzwptr); back = 0; $? "! memory" (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } } else { back = 0; $? "! memory" (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } } } else { (c->c).lzw.s = (dk_uword)chr; (c->c).lzw.fl |= LZW_FLAG_HAVE_STRING; back = 1; } } $? "- add_byte_to_lzw %d", back return back; } /** Write data into an LZW compressing cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_lzw_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; char chr, *ptr; size_t s; int err; $? "+ add_to_lzw_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) ptr = b; err = 0; s = 0; while((s < l) && (err == 0)) { chr = *(ptr++); if(add_byte_to_lzw(o, c, n, (unsigned char)chr)) { back++; } else { err = 1; $? "! error in byte %d", (int)s } s++; } if(err) { (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } $? "- add_to_lzw_cell %lu", (unsigned long)back return back; } #endif /* if DK_HAVE_LZW */ /** Write data into an ASCII-85 encoding cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_a85_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; unsigned long ul; char *ptr; size_t i; $? "+ add_to_a85_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) ptr = b; for(i = 0; i < l; i++) { ul = (unsigned long)((unsigned)((unsigned char)(*(ptr++)))); (c->c).a85.a85val = ul + 256UL * (c->c).a85.a85val; (c->c).a85.used += 1; if(((c->c).a85.used) >= 4) { if(write_a85_buffer(o,c,n)) { back++; } } else { back++; } } $? "- add_to_a85_cell %lu", TR_UL(back) return back; } /** Write data into an ASCII-Hex encoding cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_ah_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; int ok = 0; unsigned u; char *ptr; size_t i; char buffer[3]; $? "+ add_to_ah_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) ptr = b; buffer[2] = '\0'; for(i = 0; i < l; i++) { ok = 0; u = (unsigned)((unsigned char)(*ptr)); buffer[0] = hex_digits[((u >> 4) & 15)]; buffer[1] = hex_digits[(u & 15)]; if(add_from_cell(o,n,buffer,2) == 2) { ok = 1; } (c->c).ah.linepos += 2; if((c->c).ah.maxlinepos > 0) { if((c->c).ah.linepos >= (c->c).ah.maxlinepos) { if((o->flags) & 1) { if(add_from_cell(o,n,eol1,2) != 2) { ok = 0; } } else { if(add_from_cell(o,n,eol2,1) != 1) { ok = 0; } } (c->c).ah.linepos = 0; } } ptr++; if(ok) { back++; } } $? "- add_to_ah_cell %lu", TR_UL(back) return back; } /** Copy byte "to the left". As \a d and \a s are overlapping we will not use the memcpy() or bcopy() functions. @param d Destination pointer. @param s Source pointer. @param l Number of bytes to copy. */ static void copy_forward DK_P3(char *,d, char *,s, size_t,l) { char *dptr, *sptr; size_t lgt; lgt = l; sptr = s; dptr = d; while(lgt--) { *(dptr++) = *(sptr++); } } /** Remove leading bytes from cell buffer. @param c Cell. @param l Number of leading bytes to remove. */ static void preserve_buffer_contents DK_P2(dk_of_cell_t *,c, size_t,l) { size_t newused; $? "+ preserve_buffer_contents" if((c->c).rl.used > l) { $? ". need to preserve %lu < %lu", (unsigned long)l, (unsigned long)((c->c).rl.used) newused = (c->c).rl.used - l; copy_forward((c->c).rl.buffer, &(((c->c).rl.buffer)[l]), newused); (c->c).rl.used = newused; } else { $? ". flush completely" (c->c).rl.used = 0; (c->c).rl.lc = '\0'; (c->c).rl.st = 0; } $? "- preserve_buffer_contents" } /** Write data into a filter cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param l Buffer length. @return 1 on success, 0 on error. */ static int write_psrl_data DK_P4(dk_of_t *,o, dk_of_cell_t *,c, size_t,n, size_t,l) { int back = 0; char ch; size_t wr; $? "+ write_psrl_data l=%lu", (unsigned long)l if((c->c).rl.buffer) { if(l > 0) { $? ". write data" ch = (char)((unsigned char)((l - 1) & 255)); if(add_from_cell(o,n,&ch,1) == 1) { $? ". size written successfully" if((wr = add_from_cell(o,n,(c->c).rl.buffer,l)) == l) { $? ". buffer written successfully" preserve_buffer_contents(c, l); back = 1; } else { $? "! error while writing buffer %lu %lu", (unsigned long)wr, (unsigned long)l } } else { $? "! error while writing size" } } else { $? ". no need to write data" back = 1; } } $? "- write_psrl_data %d", back return back; } /** Write one run. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param l Size of the run. @return 1 on success, 0 on error. */ static int write_psrl_run DK_P4(dk_of_t *,o, dk_of_cell_t *,c, size_t,n, size_t,l) { int back = 0; size_t b; char buffer[3]; $? "+ write_psrl_run" if(((c->c).rl.buffer) && (l > 0)) { b = 257 - l; buffer[0] = (char)((unsigned char)(b & 255)); buffer[1] = (c->c).rl.lc; if(add_from_cell(o,n,buffer,2) == 2) { preserve_buffer_contents(c, l); back = 1; } } $? "- write_psrl_run %d", back return back; } /** Add one character to PS run-length compressing cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param ch Character to add. @return 1 on success, 0 on error. */ static int add_psrl_char DK_P4(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char,ch) { int back = 0; $? "+ add_psrl_char" if((c->c).rl.used) { if(ch == (c->c).rl.lc) { $? ". character matches last character" switch((c->c).rl.st) { case 2: { $? ". continue existing run" back = 1; ((c->c).rl.buffer)[(c->c).rl.used] = ch; (c->c).rl.used += 1; if((c->c).rl.used >= 127) { $? ". flush buffer" back = write_psrl_run(o,c,n,(c->c).rl.used); (c->c).rl.used = 0; (c->c).rl.st = 0; (c->c).rl.lc = ch; } } break; case 1: { $? ". start of new run" back = write_psrl_data(o,c,n,((c->c).rl.used - 2)); ((c->c).rl.buffer)[2] = ch; (c->c).rl.lc = ch; (c->c).rl.st = 2; (c->c).rl.used = 3; } break; default: { $? ". possible start of new run" back = 1; ((c->c).rl.buffer)[(c->c).rl.used] = ch; (c->c).rl.used += 1; (c->c).rl.lc = ch; (c->c).rl.st = 1; if((c->c).rl.used >= 127) { back = write_psrl_data(o,c,n,((c->c).rl.used - 2)); (c->c).rl.st = 1; (c->c).rl.lc = ch; (c->c).rl.used = 2; } } break; } } else { $? ". no matching" switch((c->c).rl.st) { case 2: { $? ". flush last run" back = write_psrl_run(o,c,n,(c->c).rl.used); ((c->c).rl.buffer)[0] = ch; (c->c).rl.lc = ch; (c->c).rl.st = 0; (c->c).rl.used = 1; } break; default: { $? ". simly add" back = 1; ((c->c).rl.buffer)[(c->c).rl.used] = ch; (c->c).rl.used += 1; (c->c).rl.lc = ch; (c->c).rl.st = 0; if((c->c).rl.used >= 127) { back = write_psrl_data(o,c,n,(c->c).rl.used); } } break; } } } else { $? ". first character" ((c->c).rl.buffer)[0] = ch; (c->c).rl.lc = ch; (c->c).rl.used = 1; (c->c).rl.st = 0; back = 1; } $? "- add_psrl_char %d", back return back; } /** Write data into a PS run-length compressing cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_psrl_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; char *ptr; size_t lgt; $? "+ add_to_psrl_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) if((c->c).rl.buffer) { ptr = b; lgt = l; while(lgt--) { if(add_psrl_char(o,c,n,*(ptr++))) { back++; } } } $? "- add_to_psrl_cell %lu", TR_UL(back) return back; } /** Write data into a buffering cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_buf_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; char *ptr; size_t i; $? "+ add_to_buf_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) if(((c->c).b.buffer) && ((c->c).b.lgt)) { ptr = b; for(i = 0; i < l; i++) { ((c->c).b.buffer)[(c->c).b.used] = *(ptr++); (c->c).b.used += 1; if(((c->c).b.used) >= ((c->c).b.lgt)) { $? ". buffer to write is:" $!trace-code if(dktrace_file()) { $!trace-code fwrite((c->c).b.buffer,1,(c->c).b.used,dktrace_file()); $!trace-code fputc('\n', dktrace_file()); $!trace-code } $? ". end of buffer" if(add_from_cell(o,n,(c->c).b.buffer,(c->c).b.used)==((c->c).b.used)) { back++; } (c->c).b.used = 0; } else { back++; } } } else { $? "! setup problem buffer or length wrong" } $? "- add_to_buf_cell %lu", TR_UL(back) return back; } /** Write data into a filter cell. @param o Output filter. @param c Filter cell. @param n Index of \a c in filter chain. @param b Data buffer pointer. @param l Size of \a b. @return Number of bytes written. */ static size_t add_to_cell DK_P5(dk_of_t *,o,dk_of_cell_t *,c,size_t,n,char *,b,size_t,l) { size_t back = 0; $? "+ add_to_cell %s %s %lu %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n), TR_PTR(b), TR_UL(l) switch(c->what) { #if DK_HAVE_ZLIB_H case DK_OF_TYPE_FLATE: { back = add_to_flate_cell(o,c,n,b,l); } break; #endif case DK_OF_TYPE_ASCII85: { back = add_to_a85_cell(o,c,n,b,l); } break; case DK_OF_TYPE_ASCIIHEX: { back = add_to_ah_cell(o,c,n,b,l); } break; case DK_OF_TYPE_PSRL: { back = add_to_psrl_cell(o,c,n,b,l); } break; case DK_OF_TYPE_BUFFERED: { back = add_to_buf_cell(o,c,n,b,l); } break; #if DK_HAVE_LZW case DK_OF_TYPE_LZW: { back = add_to_lzw_cell(o,c,n,b,l); } break; #endif /* further cell types here */ default: { $? "! setup problem, unknown cell type" } break; } $? "- add_to_cell (%lu) %lu", TR_UL(n), TR_UL(back) return back; } #if DK_HAVE_ZLIB_H /** Initialize a flate compressing cell. @param c Cell to prepare. @return 1 on success, 0 on error. */ static int cell_flate_init DK_P1(dk_of_cell_t *,c) { int back = 0; $? "+ cell_flate_init %s", TR_PTR(c) (c->c).flate.zs = dk_new(z_stream,1); (c->c).flate.ibuffer = dk_new(Bytef,1024); (c->c).flate.obuffer = dk_new(Bytef,1057); if(((c->c).flate.zs) && ((c->c).flate.ibuffer) && ((c->c).flate.obuffer)) { (c->c).flate.i_length = (uLong)1024UL; (c->c).flate.o_length = (uLong)1057UL; (c->c).flate.used = (uLong)0UL; (c->c).flate.stillok = 0; c->what = DK_OF_TYPE_FLATE; back = 1; } else { $? "! not enough memory" if((c->c).flate.zs) { dk_delete((c->c).flate.zs); } if((c->c).flate.ibuffer) { dk_delete((c->c).flate.ibuffer); } if((c->c).flate.obuffer) { dk_delete((c->c).flate.obuffer); } (c->c).flate.zs = NULL; (c->c).flate.ibuffer = NULL; (c->c).flate.obuffer = NULL; } $? "- cell_flate_init %d", back return back; } #endif /** Initialize an ASCII-85 encoding cell. @param c Cell to prepare. @return 1 on success, 0 on error. */ static int cell_a85_init DK_P1(dk_of_cell_t *,c) { int back = 1; $? "+ cell_a85_init %s", TR_PTR(c) (c->c).a85.a85val = 0UL; (c->c).a85.linepos = 0; (c->c).a85.maxlinepos = 75; (c->c).a85.used = 0; (c->c).a85.fl = 1; c->what = DK_OF_TYPE_ASCII85; $? "- cell_a85_init %d", back return back; } #if DK_HAVE_LZW /** Compare two LZW table entries. @param l Left entry. @param r Right entry. @param cr Comparison criteria (ignored). @return Comparison result. */ static int compare_lzw_entry DK_P3(void *,l, void *,r, int,cr) { int back = 0; lzw_entry *pl, *pr; pl = (lzw_entry *)l; pr = (lzw_entry *)r; if(l) { if(r) { if(pl->s > pr->s) { back = 1; } else { if(pl->s < pr->s) { back = -1; } else { if(pl->c > pr->c) { back = 1; } else { if(pl->c < pr->c) { back = -1; } } } } } else { back = 1; } } else { if(r) { back = -1; } } return back; } /** Initialize an LZW compressing cell. @param c Cell to prepare. @return 1 on success, 0 on error. */ static int cell_lzw_init DK_P1(dk_of_cell_t *,c) { int back = 0; $? "+ cell_lzw_init %s", TR_PTR(c) c->what = DK_OF_TYPE_LZW; (c->c).lzw.fl = 0; (c->c).lzw.s = 0; (c->c).lzw.ic = 0x00; (c->c).lzw.oc = 0x00; (c->c).lzw.bitsused = 0; (c->c).lzw.table = dksto_open(0); (c->c).lzw.lte = 257; if((c->c).lzw.table) { dksto_set_comp((c->c).lzw.table, compare_lzw_entry, 0); (c->c).lzw.ti = dksto_it_open((c->c).lzw.table); if((c->c).lzw.ti) { back = 1; } } $? "- cell_lzw_init %d", back return back; } #endif /* if DK_HAVE_LZW */ /** Initialize an ASCII-Hex encoding cell. @param c Cell to prepare. @return 1 on success, 0 on error. */ static int cell_ah_init DK_P1(dk_of_cell_t *,c) { int back = 1; $? "+ cell_ah_init %s", TR_PTR(c) (c->c).ah.linepos = 0; (c->c).ah.maxlinepos = 78; (c->c).ah.fl = 1; c->what = DK_OF_TYPE_ASCIIHEX; $? "- cell_ah_init %d", back return back; } /** Initialize a PS run-length compressing cell. @param c Cell to prepare. @return 1 on success, 0 on error. */ static int cell_psrl_init DK_P1(dk_of_cell_t *,c) { int back = 0; $? "+ cell_psrl_init %s", TR_PTR(c) c->what = DK_OF_TYPE_PSRL; (c->c).rl.buffer = NULL; (c->c).rl.lc = '\0'; (c->c).rl.used = 0; (c->c).rl.st = 0; (c->c).rl.buffer = dk_new(char,128); if((c->c).rl.buffer) { back = 1; } $? "- cell_psrl_init %d", back return back; } /** Initialize a buffering cell. @param c Cell to prepare. @return 1 on success, 0 on error. */ static int cell_buffered_init DK_P1(dk_of_cell_t *,c) { int back = 0; $? "+ cell_buffered_init %s", TR_PTR(c) (c->c).b.buffer = dk_new(char,512); if((c->c).b.buffer) { (c->c).b.lgt = 512; (c->c).b.used = 0; c->what = DK_OF_TYPE_BUFFERED; back = 1; } $? "- cell_buffered_init %d", back return back; } /** Initialize a filtering cell. @param c Cell to prepare. @param w Cell type. @return 1 on success, 0 on error. */ static int cell_init DK_P2(dk_of_cell_t *,c,int,w) { int back = 0; $? "+ cell_init %s %d", TR_PTR(c), w if((c->what) == DK_OF_TYPE_NONE) { switch(w) { #if DK_HAVE_ZLIB_H case DK_OF_TYPE_FLATE: { back = cell_flate_init(c); } break; #endif case DK_OF_TYPE_ASCII85: { back = cell_a85_init(c); } break; case DK_OF_TYPE_ASCIIHEX: { back = cell_ah_init(c); } break; case DK_OF_TYPE_PSRL: { back = cell_psrl_init(c); } break; case DK_OF_TYPE_BUFFERED: { back = cell_buffered_init(c); } break; #if DK_HAVE_LZW case DK_OF_TYPE_LZW: { back = cell_lzw_init(c); } break; #endif /* further cell types here */ default: { $? "! unknown cell type" } break; } } else { $? "! cell already set up" } $? "- cell_init %d", back return back; } #if DK_HAVE_ZLIB_H /** Prepare flate compressing cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_flate_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_flate_start %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) if(((c->c).flate.zs) && ((c->c).flate.ibuffer) && ((c->c).flate.obuffer)) { if(((c->c).flate.i_length) && ((c->c).flate.o_length)) { (c->c).flate.used = (uLong)0UL; (c->c).flate.stillok = 0; ((c->c).flate.zs)->zfree = (free_func)0; ((c->c).flate.zs)->zalloc = (alloc_func)0; ((c->c).flate.zs)->opaque = (voidpf)0; $? ". running deflateInit" if(deflateInit((c->c).flate.zs, 9) == Z_OK) { $? ". deflateInit ok" back = 1; (c->c).flate.stillok = 1; } else { $? "! deflateInit error" } } else { $? "! setup problem" } } else { $? "! setup problem" } $? "- cell_flate_start %d", back return back; } #endif /** Prepare ASCII-85-encoding cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_a85_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 1; $? "+ cell_a85_start %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) (c->c).a85.a85val = 0UL; (c->c).a85.linepos = 0; (c->c).a85.used = 0; $? "- cell_a85_start %d", back return back; } #if DK_HAVE_LZW /** Prepare LZW compressing cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_lzw_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_lzw_start %s %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n) if((c->c).lzw.table) { if((c->c).lzw.ti) { (c->c).lzw.fl = 0; (c->c).lzw.s = 0; (c->c).lzw.ic = 0x00; (c->c).lzw.oc = 0x00; (c->c).lzw.bitsused = 0; clear_lzw_table(c); (c->c).lzw.ob = 9; (c->c).lzw.lte = 257; if(lzw_output_string(o, c, n, 256)) { back = 1; } } } if(!back) { (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } $? "- cell_lzw_start %d", back return back; } #endif /* if DK_HAVE_LZW */ /** Prepare ASCII-Hex encoding cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_ah_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 1; $? "+ cell_ah_start %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) (c->c).ah.linepos = 0; $? "- cell_ah_start %d", back return back; } /** Prepare PS run-length compressing cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_psrl_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_psrl_start %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) if((c->c).rl.buffer) { back = 1; (c->c).rl.lc = '\0'; (c->c).rl.used = 0; (c->c).rl.st = 0; } $? "- cell_psrl_start %d", back return back; } /** Prepare buffering cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_buf_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_buf_start %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) if(((c->c).b.lgt) && ((c->c).b.buffer)) { (c->c).b.used = 0; back = 1; } else { $? "! setup problem" } $? "- cell_buf_start %d", back return back; } /** Prepare filtering cell at start of filtered chunk. @param o Output filter. @param c Cell to prepare. @param n Index of \a c in filter chain. @return 1 on success, 0 on error. */ static int cell_start DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_start %s %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n) switch(c->what) { #if DK_HAVE_ZLIB_H case DK_OF_TYPE_FLATE: { back = cell_flate_start(o,c,n); } break; #endif case DK_OF_TYPE_ASCII85: { back = cell_a85_start(o,c,n); } break; case DK_OF_TYPE_ASCIIHEX: { back = cell_ah_start(o,c,n); } break; case DK_OF_TYPE_PSRL: { back = cell_psrl_start(o,c,n); } break; case DK_OF_TYPE_BUFFERED: { back = cell_buf_start(o,c,n); } break; #if DK_HAVE_LZW case DK_OF_TYPE_LZW: { back = cell_lzw_start(o,c,n); } break; #endif default: { $? "! unknown cell type" } break; } $? "- cell_start %d", back return back; } #if DK_HAVE_ZLIB_H /** Final write operation to flate compressing cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int write_flate_final DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; int cc, err; size_t sz; $? "+ write_flate_final %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) cc = 1; ((c->c).flate.zs)->next_in = (c->c).flate.ibuffer; ((c->c).flate.zs)->avail_in = (c->c).flate.used; back = 1; $? ". before loop" while(cc) { $? ". loop start" cc = 0; ((c->c).flate.zs)->next_out = (c->c).flate.obuffer; ((c->c).flate.zs)->avail_out = (c->c).flate.o_length; err = deflate((c->c).flate.zs, Z_FINISH); $? ". (c->c).flate.o_length = %lu", (c->c).flate.o_length $? ". ((c->c).flate.zs)->avail_out = %lu", ((c->c).flate.zs)->avail_out switch(err) { case Z_STREAM_END: { $? ". done now" sz = (size_t)(((c->c).flate.o_length) - (((c->c).flate.zs)->avail_out)); $? ". sz = %lu", (unsigned long)sz if(sz) { if(add_from_cell(o,n,(char *)((c->c).flate.obuffer),sz) != sz) { back = 0; } } } break; case Z_OK: { $? ". must continue" cc = 1; sz = (size_t)(((c->c).flate.o_length) - (((c->c).flate.zs)->avail_out)); if(sz) { if(add_from_cell(o,n,(char *)((c->c).flate.obuffer),sz) != sz) { back = 0; } } } break; default: { $? "! error" back = 0; } break; } $? ". loop end" } if(deflateEnd((c->c).flate.zs) != Z_OK) { back = 0; } (c->c).flate.used = (uLong)0UL; (c->c).flate.stillok = 0; $? ". after loop" $? "- write_flate_final %d", back return back; } /** Flush deflate compressing cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_flate_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_flate_end %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) if(((c->c).flate.zs) && ((c->c).flate.ibuffer) && ((c->c).flate.obuffer)) { if(((c->c).flate.o_length) && ((c->c).flate.i_length)) { if((c->c).flate.stillok) { back = write_flate_final(o,c,n); } else { $? "! we already had an error" } } else { $? "! setup problem" } } else { $? "! setup problem" } $? "- cell_flate_end %d", back return back; } #endif /** Flush ASCII-85 encoding cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_a85_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 1; size_t i; $? "+ cell_a85_end %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) if((c->c).a85.used) { back = 0; for(i = (c->c).a85.used; i < 4; i++) { (c->c).a85.a85val = 256UL * (c->c).a85.a85val; } if(write_a85_buffer(o,c,n)) { back = 1; } } if(((c->c).a85.maxlinepos) > 0) { if(((c->c).a85.linepos) >= ((c->c).a85.maxlinepos + 3)) { if((o->flags) & 1) { if(add_from_cell(o,n,eol1,2) != 2) { back = 0; } } else { if(add_from_cell(o,n,eol2,1) != 1) { back = 0; } } (c->c).a85.linepos = 0; } } if(((c->c).a85.fl) & 1) { if(add_from_cell(o,n,a85end,2) != 2) { back = 0; } } if((o->flags) & 1) { if(add_from_cell(o,n,eol1,2) != 2) { back = 0; } } else { if(add_from_cell(o,n,eol2,1) != 1) { back = 0; } } (c->c).a85.a85val = 0UL; (c->c).a85.used = 0; (c->c).a85.linepos = 0; $? "- cell_a85_end %d", back return back; } /** Flush buffering cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_buf_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; size_t sz; $? "+ cell_buf_end %s %s %lu", TR_PTR(o), TR_PTR(c),TR_UL(n) if(((c->c).b.lgt) && ((c->c).b.buffer)) { if((c->c).b.used) { sz = (c->c).b.used; if(add_from_cell(o,n,(c->c).b.buffer,sz) == sz) { back = 1; } } else { back = 1; $? ". no more data" } } else { $? "! setup problem" } (c->c).b.used = 0; $? "- cell_buf_end %d", back return back; } #if DK_HAVE_LZW /** Flush LZW compressing cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_lzw_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_lzw_end" /* flush pending output, send EOD */ if(((c->c).lzw.fl) & LZW_FLAG_HAVE_STRING) { $? ". have string" if(!((c->c).lzw.fl & LZW_FLAG_ERROR_OCCURED)) { if(lzw_output_string(o, c, n, (c->c).lzw.s)) { back = 1; } else { back = 0; (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } } else { back = 0; } } else { back = 1; } if(!((c->c).lzw.fl & LZW_FLAG_ERROR_OCCURED)) { if(!lzw_output_string(o, c, n, 257)) { back = 0; (c->c).lzw.fl |= LZW_FLAG_ERROR_OCCURED; } } if(!((c->c).lzw.fl & LZW_FLAG_ERROR_OCCURED)) { while((c->c).lzw.bitsused > 0) { $? ". have bits" if(!lzw_output_bit(o, c, n, 0)) { back = 0; } } } clear_lzw_table(c); $? "- cell_lzw_end %d", back return back; } #endif /* if DK_HAVE_LZW */ /** Flush ASCII-Hex filtering cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_ah_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 1; $? "+ cell_ah_end" if(((c->c).ah.maxlinepos) > 0) { if(((c->c).ah.linepos) >= (c->c).ah.maxlinepos) { if((o->flags) & 1) { if(add_from_cell(o,n,eol1,2) != 2) { back = 0; } } else { if(add_from_cell(o,n,eol2,1) != 1) { back = 0; } } (c->c).ah.linepos = 0; } } if(((c->c).ah.fl) & 1) { if(add_from_cell(o,n,ahend,strlen(ahend)) != 2) { back = 0; } } if((o->flags) & 1) { if(add_from_cell(o,n,eol1,2) != 2) { back = 0; } } else { if(add_from_cell(o,n,eol2,1) != 1) { back = 0; } } $? "- cell_ah_end %d", back return back; } /** Flush PS run-length filtering cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_psrl_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; char buffer[2]; $? "+ cell_psrl_end" if((c->c).rl.buffer) { if((c->c).rl.used) { switch((c->c).rl.st) { case 2: { back = write_psrl_run(o,c,n,(c->c).rl.used); } break; default: { back = write_psrl_data(o,c,n,(c->c).rl.used); } break; } } else { back = 1; /* no bytes in buffer */ } if(back) { buffer[0] = (char)0x80; buffer[1] = (char)0x00; back = add_from_cell(o,n,buffer,1); } } $? "- cell_psrl_end %d", back return back; } /** Flush filtering cell at end of chunk. @param o output filter. @param c Filtering cell. @param n Index of \a in filter chain. @return 1 on success, 0 on error. */ static int cell_end DK_P3(dk_of_t *,o,dk_of_cell_t *,c,size_t,n) { int back = 0; $? "+ cell_end %s %s %lu", TR_PTR(o), TR_PTR(c), TR_UL(n) switch(c->what) { #if DK_HAVE_ZLIB_H case DK_OF_TYPE_FLATE: { back = cell_flate_end(o,c,n); } break; #endif case DK_OF_TYPE_ASCII85: { back = cell_a85_end(o,c,n); } break; case DK_OF_TYPE_BUFFERED: { back = cell_buf_end(o,c,n); } break; case DK_OF_TYPE_ASCIIHEX: { back = cell_ah_end(o,c,n); } break; case DK_OF_TYPE_PSRL: { back = cell_psrl_end(o,c,n); } break; #if DK_HAVE_LZW case DK_OF_TYPE_LZW: { back = cell_lzw_end(o,c,n); } break; #endif /* further cell types here */ default: { $? "! unknown cell type" } break; } $? "- cell_end %d", back return back; } /** Start a filtered chunk. @param o Output filter. @return 1 on success, 0 on error. */ static int start_chunk DK_P1(dk_of_t *,o) { int back = 0; size_t n; $? "+ start_chunk %s", TR_PTR(o) if((o->have_data) == 0) { if((o->cells) && (o->n_of_cells)) { back = 1; for(n = 0; n < (size_t)(o->n_of_cells); n++) { if(!cell_start(o,&((o->cells)[n]),n)) { back = 0; } } if(back) { o->have_data = 1; } } else { $? "! setup problem" } } else { $? "! chunk already started" } $? "- start_chunk %d", back return back; } /** End chunk of filtered data. @param o Output filter. @return 1 on success, 0 on error. */ static int end_chunk DK_P1(dk_of_t *,o) { int back = 0; size_t n; $? "+ end_chunk %s", TR_PTR(o) if((o->have_data) == 1) { if((o->cells) && (o->n_of_cells)) { back = 1; n = o->n_of_cells; while(n--) { if(!cell_end(o,&((o->cells)[n]),n)) { back = 0; } } o->have_data = (back ? 0 : -1); } else { $? "! setup problem" } } else { $? "! no chunk started" } $? "- end_chunk %d", back return back; } #if DK_HAVE_ZLIB_H /** Close a deflate compressing filtering cell. @param c Filtering cell to close. */ static void delete_flate_cell DK_P1(dk_of_cell_t *,c) { void *ptr; $? "+ delete_flate_cell %s", TR_PTR(c) if((c->c).flate.zs) { ptr = (c->c).flate.zs; dk_delete(ptr); } if((c->c).flate.ibuffer) { ptr = (c->c).flate.ibuffer; dk_delete(ptr); } if((c->c).flate.obuffer) { ptr = (c->c).flate.obuffer; dk_delete(ptr); } $? "- delete_flate_cell" } #endif #if DK_HAVE_LZW /** Close an LZW compressing filtering cell. @param c Filtering cell to close. */ static void delete_lzw_cell DK_P1(dk_of_cell_t *,c) { $? "+ delete_lzw_cell %s", TR_PTR(c) if((c->c).lzw.table) { if((c->c).lzw.ti) { clear_lzw_table(c); dksto_it_close((c->c).lzw.ti); } dksto_close((c->c).lzw.table); } (c->c).lzw.table = NULL; (c->c).lzw.ti = NULL; (c->c).lzw.fl = 0; (c->c).lzw.s = 0; (c->c).lzw.ic = 0x00; (c->c).lzw.oc = 0x00; (c->c).lzw.bitsused = 0; (c->c).lzw.lte = 0; $? "- delete_lzw_cell" } #endif /* if DK_HAVE_LZW */ /** Close an ASCII-85 filtering cell. @param c Filtering cell to close. */ static void delete_a85_cell DK_P1(dk_of_cell_t *,c) { $? "+ delete_a85_cell %s", TR_PTR(c) (c->c).a85.a85val = 0UL; (c->c).a85.linepos = 0; (c->c).a85.used = 0; $? "- delete_a85_cell" } /** Close a buffering filter cell. @param c Filtering cell to close. */ static void delete_buf_cell DK_P1(dk_of_cell_t *,c) { void *ptr; $? "+ delete_buf_cell %s", TR_PTR(c) if((c->c).b.buffer) { ptr = (c->c).b.buffer; dk_delete(ptr); } $? "- delete_buf_cell" } /** Close an ASCII-Hex filtering cell. @param c Filtering cell to close. */ static void delete_ascii_hex_cell DK_P1(dk_of_cell_t *,c) { $? "= delete_ascii_hex_cell" } /** Close a PS run-length filtering cell. @param c Cell to close. */ static void delete_ps_runlength_cell DK_P1(dk_of_cell_t *,c) { char *ptr; $? "+ delete_ps_runlength_cell" ptr = (c->c).rl.buffer; if(ptr) { dk_delete(ptr); } (c->c).rl.buffer = NULL; (c->c).rl.lc = '\0'; (c->c).rl.used = 0; (c->c).rl.st = 0; $? "- delete_ps_runlength_cell" } /** Close one filter cell. @param c Filter cell to close. */ static void delete_cell DK_P1(dk_of_cell_t *,c) { switch(c->what) { #if DK_HAVE_ZLIB_H case DK_OF_TYPE_FLATE: { delete_flate_cell(c); } break; #endif case DK_OF_TYPE_ASCII85: { delete_a85_cell(c); } break; case DK_OF_TYPE_BUFFERED: { delete_buf_cell(c); } break; case DK_OF_TYPE_ASCIIHEX: { delete_ascii_hex_cell(c); } break; case DK_OF_TYPE_PSRL: { delete_ps_runlength_cell(c); } break; #if DK_HAVE_LZW case DK_OF_TYPE_LZW: { delete_lzw_cell(c); } break; #endif /* further cell types here */ default: { $? "! unknown cell type" } break; } DK_MEMRES(c,sizeof(dk_of_cell_t)); } /** Close output filter. @param o Output filter to close. */ static int delete_of DK_P1(dk_of_t *,o) { int back = 1; dk_of_cell_t *c; size_t i; void *ptr; $? "+ delete_of %s", TR_PTR(o) if(o->have_data == 1) { if(!end_chunk(o)) { back = 0; } } c = o->cells; if(c && (o->n_of_cells)) { for(i = 0; i < (size_t)(o->n_of_cells); i++) { delete_cell(c++); } ptr = (void *)(o->cells); dk_delete(ptr); } o->target = NULL; o->cells = NULL; o->n_of_cells = 0; o->have_data = 0; dk_delete(o); $? "- delete_of %d", back return back; } void dkof_stream_fct DK_P1(dk_stream_api_t *, a) { dk_stream_t *s; dk_of_t *o; dk_of_cell_t *c; if(a) { a->return_value = 0; a->error_code = DK_ERR_FUNCTION_UNSUPPORTED; s = (dk_stream_t *)(a->strm); if(s) { o = (dk_of_t *)(s->data); if(o) { c = o->cells; if(c) { switch(a->cmd) { case DK_STREAM_CMD_TEST: { switch( (a->params).cmd ) { case DK_STREAM_CMD_TEST: case DK_STREAM_CMD_FINISH: case DK_STREAM_CMD_WRBUF: { a->return_value= 1; } break; } } break; case DK_STREAM_CMD_FINISH: { a->return_value = delete_of(o); s->data = NULL; s->fct = NULL; } break; case DK_STREAM_CMD_WRBUF: { void *b; size_t sz, res, n; if(o->n_of_cells) { sz = (a->params).length; b = (a->params).buffer; n = o->n_of_cells - 1; if(b && sz) { res = add_to_cell(o, &(c[n]), n, (char *)b, sz); if(res) { a->return_value = 1; (a->results).used = res; } else { $? "! I/O error" a->error_code = DK_ERR_IO; } } else { $? "! no data to write" } } else { $? "! setup problem" } } break; } } else { $? "! setup problem" } } else { $? "! setup problem" } } else { $? "! problem" } } else { $? "! problem" } } dk_stream_t * dkof_open DK_P2(dk_stream_t *,t,size_t,nof) { dk_stream_t *back = NULL; dk_of_t *o = NULL; dk_of_cell_t *c = NULL, *cptr = NULL; size_t n; $? "+ dkof_open %s %lu", TR_PTR(t), TR_UL(nof) if(t && nof) { $? ". args ok" o = dk_new(dk_of_t,1); c = dk_new(dk_of_cell_t,nof); if(o && c) { back = dkstream_new((void *)o, (dk_stream_fct_t *)dkof_stream_fct); if(back) { $? ". memory allocations ok, going to create links" o->flags = 0; o->target = t; o->cells = c; o->n_of_cells = nof; o->have_data = 0; cptr = c; n = nof; while(nof--) { DK_MEMRES(cptr,sizeof(dk_of_cell_t)); cptr->what = DK_OF_TYPE_NONE; cptr++; } } else { $? "! not enough memory" } } else { $? "! not enough memory" } if(!back) { if(o) dk_delete(o); if(c) dk_delete(c); } } else { $? "! invalid args" } $? "- dkof_open %s", TR_PTR(back) return back; } void dkof_close DK_P1(dk_stream_t *,s) { $? "+ dkof_close %s", TR_PTR(s) if(s) { dkstream_delete(s); } $? "- dkof_close" } int dkof_set DK_P3(dk_stream_t *,s,size_t,n,int,w) { int back = 0; dk_of_t *o; dk_of_cell_t *c; $? "+ dkof_set %s %lu %d", TR_PTR(s), TR_UL(n), w if(s) { o = (dk_of_t *)(s->data); if(o) { c = o->cells; if(c) { if(n < (size_t)(o->n_of_cells)) { back = cell_init(&((o->cells)[n]), w); } else { $? "! cell number out of range" } } else { $? "! no cells in filter" } } else { $? "! setup problem" } } else { $? "! invalid stream pointer" } $? "- dkof_set %d", back return back; } int dkof_start_chunk DK_P1(dk_stream_t *,s) { int back = 0; dk_of_t *o; $? "+ dkof_start_chunk %s", TR_PTR(s) if(s) { o = (dk_of_t *)(s->data); if(o) { back = start_chunk(o); } else { $? "! setup problem" } } else { $? "! invalid argument" } $? "- dkof_start_chunk %d", back return back; } int dkof_end_chunk DK_P1(dk_stream_t *,s) { int back = 0; dk_of_t *o; $? "+ dkof_end_chunk %s", TR_PTR(s) if(s) { o = (dk_of_t *)(s->data); if(o) { back = end_chunk(o); } else { $? "! setup problem" } } else { $? "! invalid argument" } $? "- dkof_end_chunk %d", back return back; } void dkof_set_crnl DK_P2(dk_stream_t *,s,int,v) { dk_of_t *o; $? "= dkof_set_crnl %s %d", TR_PTR(s), v if(s) { o = (dk_of_t *)(s->data); if(o) { if(v) { o->flags |= 1; } else { o->flags &= (~1); } } else { $? "! setup problem" } } } void dkof_set_finalizing DK_P2(dk_stream_t *,s,int,v) { dk_of_t *o; size_t n; if(s) { o = (dk_of_t *)(s->data); if(o) { if((o->cells) && (o->n_of_cells)) { for(n = 0; n < (size_t)(o->n_of_cells); n++) { switch(((o->cells)[n]).what) { case DK_OF_TYPE_ASCII85: { if(v) { ((o->cells)[n]).c.a85.fl |= 1; } else { ((o->cells)[n]).c.a85.fl &= (~1); } } break; case DK_OF_TYPE_ASCIIHEX: { if(v) { ((o->cells)[n]).c.ah.fl |= 1; } else { ((o->cells)[n]).c.ah.fl &= (~1); } } break; } } } } } } dk_bitshift_t * dkof_bs_open DK_P1(dk_stream_t *,t) { dk_bitshift_t *back = NULL; if(t) { back = dk_new(dk_bitshift_t,1); if(back) { back->t = t; back->c = 0x00; back->b = 0; } } return back; } void dkof_bs_close DK_P1(dk_bitshift_t *,p) { if(p) { p->t = NULL; p->c = 0x00; p->b = 0; dk_delete(p); } } int dkof_bs_put DK_P3(dk_bitshift_t *,bsp, unsigned short,c, unsigned short,nbits) { int back = 0; unsigned short br; /* bits remaining for next loops */ unsigned short itl; /* bits in this loop */ $? "+ dkof_bs_put" if(bsp) { back = 1; br = nbits; do { itl = 8 - bsp->b; itl = ((itl > br) ? br : itl); bsp->c = SHIFTBITS((bsp->c),itl) | GETBITS(c,br,itl); br -= itl; bsp->b += itl; if((bsp->b) >= 8) { bsp->b = 0; if(dkstream_write(bsp->t, (char *)(&(bsp->c)), 1) != 1) { back = 0; } } } while((br > 0) && (back)); br = nbits; } else { } $? "- dkof_bs_put %d", back return back; } int dkof_bs_flush DK_P1(dk_bitshift_t *,bsp) { int back = 0; if(bsp) { back = 1; if(bsp->b) { back = dkof_bs_put(bsp, (unsigned short)0, (unsigned short)(8 - bsp->b)); } } return back; } int dkof_lzw_available DK_P0() { int back = 0; #if DK_HAVE_LZW back = 1; #endif return back; } void dkof_set_max_line_length DK_P2(dk_stream_t *,s, size_t,ll) { dk_of_t *o; size_t i; if(s) { o = (dk_of_t *)(s->data); if(o) { if(o->cells) { for(i = 0; i < (size_t)(o->n_of_cells); i++) { switch(((o->cells)[i]).what) { case DK_OF_TYPE_ASCII85: { if(ll > 5) { ((o->cells)[i]).c.a85.maxlinepos = ll - 5; } else { ((o->cells)[i]).c.a85.maxlinepos = 0; } } break; case DK_OF_TYPE_ASCIIHEX: { if(ll > 2) { ((o->cells)[i]).c.ah.maxlinepos = ll - 2; } else { ((o->cells)[i]).c.ah.maxlinepos = 0; } } break; } } } } } }