summaryrefslogtreecommitdiff
path: root/gs/src/srld.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/src/srld.c')
-rw-r--r--gs/src/srld.c123
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
+};