diff options
Diffstat (limited to 'gs/src/srld.c')
-rw-r--r-- | gs/src/srld.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/gs/src/srld.c b/gs/src/srld.c new file mode 100644 index 000000000..814d152ee --- /dev/null +++ b/gs/src/srld.c @@ -0,0 +1,123 @@ +/* Copyright (C) 1995, 1996, 1997 Aladdin Enterprises. All rights reserved. + + This file is part of Aladdin Ghostscript. + + Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author + or distributor accepts any responsibility for the consequences of using it, + or for whether it serves any particular purpose or works at all, unless he + or she says so in writing. Refer to the Aladdin Ghostscript Free Public + License (the "License") for full details. + + Every copy of Aladdin Ghostscript must include a copy of the License, + normally in a plain ASCII text file named PUBLIC. The License grants you + the right to copy, modify and redistribute Aladdin Ghostscript, but only + under certain conditions described in the License. Among other things, the + License requires that the copyright notice and this notice be preserved on + all copies. +*/ + +/* srld.c */ +/* RunLengthDecode filter */ +#include "stdio_.h" /* includes std.h */ +#include "memory_.h" +#include "strimpl.h" +#include "srlx.h" + +/* ------ RunLengthDecode ------ */ + +private_st_RLD_state(); + +#define ss ((stream_RLD_state *)st) + +/* Set defaults */ +private void +s_RLD_set_defaults(stream_state *st) +{ s_RLD_set_defaults_inline(ss); +} + +/* Initialize */ +private int +s_RLD_init(stream_state *st) +{ return s_RLD_init_inline(ss); +} + +/* Refill the buffer */ +private int +s_RLD_process(stream_state *st, stream_cursor_read *pr, + stream_cursor_write *pw, bool last) +{ register const byte *p = pr->ptr; + register byte *q = pw->ptr; + const byte *rlimit = pr->limit; + byte *wlimit = pw->limit; + int left; + int status = 0; + +top: if ( (left = ss->copy_left) > 0 ) + { /* We suspended because the output buffer was full; */ + /* try again now. */ + uint avail = wlimit - q; + int copy_status = 1; + + if ( left > avail ) + left = avail; + if ( ss->copy_data >= 0 ) + memset(q + 1, ss->copy_data, left); + else + { avail = rlimit - p; + if ( left >= avail ) + { copy_status = 0; + left = avail; + } + memcpy(q + 1, p + 1, left); + p += left; + } + q += left; + if ( (ss->copy_left -= left) > 0 ) + { status = copy_status; + goto x; + } + } + while ( p < rlimit ) + { int b = *++p; + if ( b < 128 ) + { if ( ++b > rlimit - p || b > wlimit - q ) + { ss->copy_left = b; + ss->copy_data = -1; + goto top; + } + memcpy(q + 1, p + 1, b); + p += b; + q += b; + } + else if ( b == 128 ) /* end of data */ + { if ( ss->EndOfData ) + { status = EOFC; + break; + } + } + else if ( p == rlimit ) + { p--; + break; + } + else if ( (b = 257 - b) > wlimit - q ) + { ss->copy_left = b; + ss->copy_data = *++p; + goto top; + } + else + { memset(q + 1, *++p, b); + q += b; + } + } +x: pr->ptr = p; + pw->ptr = q; + return status; +} + +#undef ss + +/* Stream template */ +const stream_template s_RLD_template = +{ &st_RLD_state, s_RLD_init, s_RLD_process, 1, 1, NULL, + s_RLD_set_defaults +}; |