home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1993, 1994 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.
- */
-
- /* sstring.c */
- /* String and hexstring streams for Ghostscript */
- #include "stdio_.h" /* includes std.h */
- #include "memory_.h"
- #include "strimpl.h"
- #include "sfilter.h"
- #include "scanchar.h"
-
- /* ------ ASCIIHexEncode ------ */
-
- /* Process a buffer */
- private int
- s_AXE_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;
- int rcount = pr->limit - p;
- int wcount = pw->limit - q;
- register int count;
- register const char _ds *hex_digits = "0123456789abcdef";
- int status = 0;
- if ( last )
- wcount--; /* leave room for '>' */
- wcount -= (wcount + 64) / 65; /* leave room for \n */
- wcount >>= 1; /* 2 chars per input byte */
- count = (wcount < rcount ? (status = 1, wcount) : rcount);
- while ( --count >= 0 )
- { *++q = hex_digits[*++p >> 4];
- *++q = hex_digits[*p & 0xf];
- if ( !(count & 31) )
- *++q = '\n';
- }
- if ( last && status == 0 )
- { *++q = '>';
- }
- pr->ptr = p;
- pw->ptr = q;
- return status;
- }
-
- /* Stream template */
- const stream_template s_AXE_template =
- { &st_stream_state, NULL, s_AXE_process, 1, 3
- };
-
- /* ------ ASCIIHexDecode ------ */
-
- private_st_AXD_state();
-
- #define ss ((stream_AXD_state *)st)
-
- /* Initialize the state */
- private int
- s_AXD_init(stream_state *st)
- { return s_AXD_init_inline(ss);
- }
-
- /* Process a buffer */
- private int
- s_AXD_process(stream_state *st, stream_cursor_read *pr,
- stream_cursor_write *pw, bool last)
- { int code = s_hex_process(pr, pw, &ss->odd, false);
- switch ( code )
- {
- case 0:
- if ( ss->odd >= 0 && last )
- { if ( pw->ptr == pw->limit )
- return 1;
- *++(pw->ptr) = ss->odd << 4;
- }
- /* falls through */
- default:
- return code;
- case ERRC:
- ;
- }
- /* Check for EOD. ERRC implies at least one more character */
- /* was read. */
- if ( *pr->ptr != '>' ) /* EOD */
- return ERRC;
- if ( ss->odd >= 0 )
- { if ( pw->ptr == pw->limit )
- return 1;
- *++(pw->ptr) = ss->odd << 4;
- }
- return EOFC;
- }
-
- #undef ss
-
- /* Stream template */
- const stream_template s_AXD_template =
- { &st_AXD_state, s_AXD_init, s_AXD_process, 2, 1
- };
-
- /* ------ PSStringEncode ------ */
-
- /* Process a buffer */
- private int
- s_PSSE_process(stream_state *st, stream_cursor_read *pr,
- stream_cursor_write *pw, bool last)
- { register const byte *p = pr->ptr;
- const byte *rlimit = pr->limit;
- register byte *q = pw->ptr;
- byte *wlimit = pw->limit;
- int status = 0;
- /* This doesn't have to be very efficient. */
- while ( p < rlimit )
- { register int c;
- if ( q == wlimit )
- { status = 1;
- break;
- }
- c = *++p;
- if ( c < 32 || c >= 127 || c == '(' || c == ')' || c == '\\' )
- { if ( q + 1 == wlimit )
- { status = 1;
- break;
- }
- *++q = '\\';
- }
- *++q = c;
- }
- if ( last && status == 0 )
- { if ( q == wlimit )
- status = 1;
- else
- *++q = ')';
- }
- pr->ptr = p;
- pw->ptr = q;
- return status;
- }
-
- /* Stream template */
- const stream_template s_PSSE_template =
- { &st_stream_state, NULL, s_PSSE_process, 1, 4
- };
-
- /* ------ PSStringDecode ------ */
-
- private_st_PSSD_state();
-
- #define ss ((stream_PSSD_state *)st)
-
- /* Initialize the state */
- private int
- s_PSSD_init(stream_state *st)
- { return s_PSSD_init_inline(ss);
- }
-
- /* Process a buffer */
- private int
- s_PSSD_process(stream_state *st, stream_cursor_read *pr,
- stream_cursor_write *pw, bool last)
- { register const byte *p = pr->ptr;
- const byte *rlimit = pr->limit;
- register byte *q = pw->ptr;
- byte *wlimit = pw->limit;
- int status = 0;
- register int c;
- #define check_p(n)\
- if ( p == rlimit ) { p -= n; goto out; }
- #define check_q(n)\
- if ( q == wlimit ) { p -= n; status = 1; goto out; }
- while ( p < rlimit )
- { c = *++p;
- if ( c == '\\' && !ss->from_string )
- { check_p(1);
- switch ( (c = *++p) )
- {
- case 'n':
- c = '\n';
- goto put;
- case 'r':
- c = '\r';
- goto put;
- case 't':
- c = '\t';
- goto put;
- case 'b':
- c = '\b';
- goto put;
- case 'f':
- c = '\f';
- goto put;
- default: /* ignore the \ */
- put: check_q(2);
- *++q = c;
- continue;
- case char_CR: /* ignore, check for following \n */
- check_p(2);
- if ( p[1] == char_EOL )
- p++;
- continue;
- case char_EOL: /* ignore */
- continue;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- { int d;
- check_p(2);
- d = p[1];
- c -= '0';
- if ( d >= '0' && d <= '7' )
- { if ( p + 1 == rlimit )
- { p -= 2;
- goto out;
- }
- check_q(2);
- c = (c << 3) + d - '0';
- d = p[2];
- if ( d >= '0' && d <= '7' )
- { c = (c << 3) + d - '0';
- p += 2;
- }
- else
- p++;
- }
- else
- check_q(2);
- *++q = c;
- continue;
- }
- }
- }
- else
- switch ( c )
- {
- case '(':
- check_q(1);
- ss->depth++;
- break;
- case ')':
- if ( ss->depth == 0 )
- { status = EOFC;
- goto out;
- }
- check_q(1);
- ss->depth--;
- break;
- case char_CR: /* convert to \n */
- check_p(1);
- check_q(1);
- if ( p[1] == char_EOL )
- p++;
- *++q = '\n';
- continue;
- case char_EOL:
- c = '\n';
- default:
- check_q(1);
- break;
- }
- *++q = c;
- }
- #undef check_p
- #undef check_q
- out: pr->ptr = p;
- pw->ptr = q;
- if ( last && status == 0 && p != rlimit )
- status = ERRC;
- return status;
- }
-
- #undef ss
-
- /* Stream template */
- const stream_template s_PSSD_template =
- { &st_PSSD_state, s_PSSD_init, s_PSSD_process, 4, 1
- };
-
- /* ------ Utilities ------ */
-
- /*
- * Convert hex data to binary. Return 1 if we filled the string, 0 if
- * we ran out of input data before filling the string, or ERRC on error.
- * The caller must set *odd_digit to -1 before the first call;
- * after each call, if an odd number of hex digits has been read (total),
- * *odd_digit is the odd digit value, otherwise *odd_digit = -1.
- * If ignore_garbage is true, ignore characters other than hex digits;
- * if ignore_garbage is false, return ERRC on characters other than hex
- * digits or whitespace.
- */
- int
- s_hex_process(stream_cursor_read *pr, stream_cursor_write *pw,
- int *odd_digit, bool ignore_garbage)
- { const byte *p = pr->ptr;
- const byte *rlimit = pr->limit;
- byte *q = pw->ptr;
- byte *wlimit = pw->limit;
- byte val1 = (byte)*odd_digit;
- byte val2;
- uint rcount;
- byte *flimit;
- register const byte _ds *decoder = scan_char_decoder;
- int code = 0;
- if ( q >= wlimit )
- return 1;
- if ( val1 <= 0xf )
- goto d2;
- d1: if ( (rcount = (rlimit - p) >> 1) == 0 )
- goto x1;
- /* Set up a fast end-of-loop check, so we don't have to test */
- /* both p and q against their respective limits. */
- flimit = (rcount < wlimit - q ? q + rcount : wlimit);
- f1: if ( (val1 = decoder[p[1]]) <= 0xf &&
- (val2 = decoder[p[2]]) <= 0xf
- )
- { p += 2;
- *++q = (val1 << 4) + val2;
- if ( q < flimit )
- goto f1;
- if ( q >= wlimit )
- goto px;
- }
- x1: if ( p >= rlimit )
- goto end1;
- if ( (val1 = decoder[*++p]) > 0xf )
- { if ( val1 == ctype_space || ignore_garbage )
- goto x1;
- code = ERRC;
- goto end1;
- }
- d2: if ( p >= rlimit )
- { *odd_digit = val1;
- goto ended;
- }
- if ( (val2 = decoder[*++p]) > 0xf )
- { if ( val2 == ctype_space || ignore_garbage )
- goto d2;
- *odd_digit = val1;
- code = ERRC;
- goto ended;
- }
- *++q = (val1 << 4) + val2;
- if ( q < wlimit ) goto d1;
- px: code = 1;
- end1: *odd_digit = -1;
- ended: pr->ptr = p;
- pw->ptr = q;
- return code;
- }
-