[gs-cvs] rev 8810 - in trunk/gs: lib src

alexcher at ghostscript.com alexcher at ghostscript.com
Sun Jun 29 17:05:41 PDT 2008


Author: alexcher
Date: 2008-06-29 17:05:40 -0700 (Sun, 29 Jun 2008)
New Revision: 8810

Modified:
   trunk/gs/lib/gs_frsd.ps
   trunk/gs/src/gxshade.c
   trunk/gs/src/int.mak
   trunk/gs/src/zfrsd.c
Log:
Add one more way to store data of the reusable stream: an array of strings.
Read the input stream into an array of strings during reusable stream
construction and use the array directly as a data storage.
Bug 689476, customer 190.

DIFFERENCES:
None


Modified: trunk/gs/lib/gs_frsd.ps
===================================================================
--- trunk/gs/lib/gs_frsd.ps	2008-06-28 15:42:59 UTC (rev 8809)
+++ trunk/gs/lib/gs_frsd.ps	2008-06-30 00:05:40 UTC (rev 8810)
@@ -31,25 +31,25 @@
 		% from the RSD dictionary; all the others should have
 		% CloseSource = true.
 		% Stack: source dict filters parms
-  2 index /CloseSource .knownget not { false } if 5 -1 roll
+  2 index /CloseSource .knownget not { //false } if 5 -1 roll
 		% Stack: dict filters parms CloseSource source
   0 1 5 index length 1 sub {
     4 index 1 index get
 		% Stack: dict filters parms CloseSource source index filtname
-    4 index null eq {
+    4 index //null eq {
       0 dict
     } {
-      4 index 2 index get dup null eq { pop } if
+      4 index 2 index get dup //null eq { pop } if
     } ifelse
     3 -1 roll pop exch filter
-    exch pop true exch		% set CloseSource for further filters
+    exch pop //true exch		% set CloseSource for further filters
   } for
 		% If AsyncRead is true, try to create the filter directly.
 		% Stack: dict filters parms CloseSource source
-  4 index /AsyncRead .knownget not { false } if {
+  4 index /AsyncRead .knownget not { //false } if {
     1 index { .reusablestream } .internalstopped
   } {
-    null true
+    //null //true
   } ifelse {
     pop
 		% No luck.  Read the entire contents of the stream now.
@@ -59,22 +59,16 @@
     } if
 		% We must allocate the string in the same VM space as its
 		% source, since the reusable stream must be allocated there.
+
     .currentglobal 1 index gcheck .setglobal exch
-		% Stack: dict filters parms CloseSource oldglobal file
-    10 dict exch {
-		% Stack: dict filters parms CloseSource oldglobal contdict file
-      dup 64000 string readstring
-      3 index dup length 4 -1 roll put not { exit } if
-    } loop pop
-		% Concatenate the contents into one big string.
-		% Stack: dict filters parms CloseSource oldglobal contdict
-    0 1 index { length exch pop add } forall
-    dup 65400 gt { .bytestring } { string } ifelse
-    3 -1 roll .setglobal exch {
-		% Stack: dict filters parms CloseSource string index substring
-      exch 64000 mul exch 2 index 3 1 roll putinterval
-    } forall
-		% Now create the stream on the string.
+    currentpacking //false setpacking exch
+       		% Stack: dict filters parms CloseSource oldglobal oldpacking file
+    [ exch { dup 40000 string readstring not { exit } if exch } loop
+      exch pop
+    ]
+              		% Stack: dict filters parms CloseSource oldglobal oldpacking [()...]
+    3 1 roll setpacking setglobal
+              		% Stack: dict filters parms CloseSource [()...]
     1 index .reusablestream
   } if
 		% We created the stream successfully: clean up.

Modified: trunk/gs/src/gxshade.c
===================================================================
--- trunk/gs/src/gxshade.c	2008-06-28 15:42:59 UTC (rev 8809)
+++ trunk/gs/src/gxshade.c	2008-06-30 00:05:40 UTC (rev 8810)
@@ -55,7 +55,7 @@
     cs->pctm = &pis->ctm;
     if (data_source_is_stream(params->DataSource)) {
 	/*
-	 * Reset the data stream iff it is reusable -- either a reusable
+	 * Rewind the data stream iff it is reusable -- either a reusable
 	 * file or a reusable string.
 	 */
 	stream *s = cs->s = params->DataSource.data.strm;
@@ -63,7 +63,7 @@
 	if ((s->file != 0 && s->file_limit != max_long) ||
 	    (s->file == 0 && s->strm == 0)
 	    )
-	    sreset(s);
+	    sseek(s, 0);
     } else {
 	s_init(&cs->ds, NULL);
         sread_string(&cs->ds, params->DataSource.data.str.data,

Modified: trunk/gs/src/int.mak
===================================================================
--- trunk/gs/src/int.mak	2008-06-28 15:42:59 UTC (rev 8809)
+++ trunk/gs/src/int.mak	2008-06-30 00:05:40 UTC (rev 8810)
@@ -1060,7 +1060,7 @@
 $(PSOBJ)zfrsd.$(OBJ) : $(PSSRC)zfrsd.c $(OP) $(memory__h)\
  $(gsfname_h) $(gxiodev_h)\
  $(sfilter_h) $(stream_h) $(strimpl_h)\
- $(files_h) $(idict_h) $(idparam_h) $(iname_h) $(store_h)
+ $(files_h) $(idict_h) $(idparam_h) $(iname_h) $(istruct_h) $(store_h)
 	$(PSCC) $(PSO_)zfrsd.$(OBJ) $(C_) $(PSSRC)zfrsd.c
 
 # ======================== PostScript Level 2 ======================== #

Modified: trunk/gs/src/zfrsd.c
===================================================================
--- trunk/gs/src/zfrsd.c	2008-06-28 15:42:59 UTC (rev 8809)
+++ trunk/gs/src/zfrsd.c	2008-06-30 00:05:40 UTC (rev 8810)
@@ -25,6 +25,7 @@
 #include "idict.h"
 #include "idparam.h"
 #include "iname.h"
+#include "istruct.h"
 #include "store.h"
 
 /* ---------------- Reusable streams ---------------- */
@@ -108,6 +109,7 @@
 /*
  * The file|string operand must be a "reusable source", either:
  *      - A string or bytestring;
+ *      - An array of strings;
  *      - A readable, positionable file stream;
  *      - A readable string stream;
  *      - A SubFileDecode filter with an empty EODString and a reusable
@@ -120,6 +122,10 @@
 		     bool is_bytestring);
 static int make_rfs(i_ctx_t *i_ctx_p, os_ptr op, stream *fs,
 		     long offset, long length);
+
+static int make_aos(i_ctx_t *i_ctx_p, os_ptr op,
+                    int blk_sz, int blk_sz_last, unsigned int file_sz);
+
 static int
 zreusablestream(i_ctx_t *i_ctx_p)
 {
@@ -146,6 +152,32 @@
 	code = make_rss(i_ctx_p, source_op,
 			(const byte *)source_op->value.pstruct, size,
 			r_space(source_op), 0L, size, true);
+    } else if (r_has_type(source_op, t_array)) {  /* no packedarrays */
+	int i, blk_cnt, blk_sz;
+        ref *blk_ref;
+        ulong filelen = 0;
+
+        check_read(*source_op);
+        blk_cnt = r_size(source_op);
+	blk_ref = source_op->value.refs;
+        if (blk_cnt > 0) {
+            blk_sz = r_size(blk_ref);
+            for (i = 0; i < blk_cnt; i++) {
+                int len;
+
+                check_read_type(blk_ref[i], t_string);
+                len = r_size(&blk_ref[i]);
+                if (len > blk_sz || len < blk_sz && i < blk_cnt - 1)
+                   return_error(e_rangecheck); /* last block can be smaller */
+                filelen += len;
+            }
+        }
+        if (filelen == 0) {
+           code = make_rss(i_ctx_p, source_op, (unsigned char *)"", 0,
+	       r_space(source_op), 0, 0, false);
+        } else {
+           code = make_aos(i_ctx_p, source_op, blk_sz, r_size(&blk_ref[blk_cnt - 1]), filelen);
+        }
     } else {
 	long offset = 0;
 	stream *source;
@@ -255,7 +287,181 @@
     make_stream_file(op, s, "r");
     return 0;
 }
+/* ----------- Reusable array-of-strings stream ------------- */
 
+static int  s_aos_available(stream *, long *);
+static int  s_aos_seek(stream *, long);
+static void s_aos_reset(stream *s);
+static int  s_aos_flush(stream *s);
+static int  s_aos_close(stream *);
+static int  s_aos_process(stream_state *, stream_cursor_read *,
+	                stream_cursor_write *, bool);
+
+/* Stream state */
+typedef struct aos_state_s {
+    stream_state_common;
+    ref   blocks;
+    stream *s;	
+    int   blk_sz;
+    int   blk_sz_last;
+    uint  file_sz; 
+} aos_state_t;
+
+/* GC procedures */
+static 
+CLEAR_MARKS_PROC(aos_clear_marks)
+{   aos_state_t *const pptr = vptr;
+
+    r_clear_attrs(&pptr->blocks, l_mark);
+}
+static 
+ENUM_PTRS_WITH(aos_enum_ptrs, aos_state_t *pptr) return 0;
+ENUM_PTR(0, gs_context_state_t, pgs);
+case 1:
+ENUM_RETURN_REF(&pptr->blocks);
+ENUM_PTRS_END
+static RELOC_PTRS_WITH(aos_reloc_ptrs, aos_state_t *pptr);
+RELOC_PTR(aos_state_t, s);
+RELOC_REF_VAR(pptr->blocks);
+r_clear_attrs(&pptr->blocks, l_mark);
+RELOC_PTRS_END
+
+gs_private_st_complex_only(st_aos_state, aos_state_t,
+    "aos_state", aos_clear_marks, aos_enum_ptrs, aos_reloc_ptrs, 0);
+
+/* Stream template */
+static const stream_template s_aos_template = {	
+     &st_aos_state, 0, s_aos_process, 1, 1, 0, 0 };
+
+/* Stream procs */
+static const stream_procs s_aos_procs = { 
+     s_aos_available, s_aos_seek, s_aos_reset,
+     s_aos_flush, s_aos_close, s_aos_process,
+     NULL		/* no s_aos_switch */
+};
+
+static int
+make_aos(i_ctx_t *i_ctx_p, os_ptr op, int blk_sz, int blk_sz_last, uint file_sz)
+{
+    stream *s;
+    aos_state_t *ss;
+    byte *buf;
+    const int aos_buf_size = 1024; /* arbitrary */
+    uint save_space = icurrent_space;
+    ialloc_set_space(idmemory, r_space(op));
+    
+    s = s_alloc(imemory, "aos_stream");
+    ss = (aos_state_t *)s_alloc_state(imemory, &st_aos_state, "st_aos_state");
+    buf = gs_alloc_bytes(imemory, aos_buf_size, "aos_stream_buf");
+    if (s == 0 || ss == 0 || buf == 0) {
+        gs_free_object(imemory, buf, "aos_stream_buf");
+        gs_free_object(imemory, ss, "st_aos_state");
+        gs_free_object(imemory, s, "aos_stream");
+        ialloc_set_space(idmemory, save_space);
+        return_error(e_VMerror);
+    }
+    ialloc_set_space(idmemory, save_space);
+    ss->template = &s_aos_template;
+    ss->blocks = *op;
+    ss->s = s;
+    ss->blk_sz = blk_sz;
+    ss->blk_sz_last = blk_sz_last;
+    ss->file_sz = file_sz;
+    s_std_init(s, buf, aos_buf_size, &s_aos_procs, s_mode_read + s_mode_seek);
+    s->state = (stream_state *)ss;
+    s->file_offset = 0;
+    s->file_limit = max_long;
+    s->close_at_eod = false;
+    make_stream_file(op, s, "r");
+    return 0;
+}
+
+/* Return the number of available bytes */
+static int
+s_aos_available(stream *s, long *pl)
+{
+    *pl = ((aos_state_t *)s->state)->file_sz - stell(s);
+    return 0;
+}
+
+/* Seek in a string being read.  Return 0 if OK, ERRC if not. */
+static int
+s_aos_seek(register stream * s, long pos)
+{
+    uint end = s->srlimit - s->cbuf + 1;
+    long offset = pos - s->position;
+
+    if (offset >= 0 && offset <= end) {  /* Staying within the same buffer */
+	s->srptr = s->cbuf + offset - 1;
+	return 0;
+    }
+    if (pos < 0 || pos > s->file_limit)
+	return ERRC;
+    s->srptr = s->srlimit = s->cbuf - 1;
+    s->end_status = 0;
+    s->position = pos;
+    return 0;
+}
+
+static void
+s_aos_reset(stream *s)
+{
+    /* PLRM definition of reset operator is strange. */
+    /* Rewind the file and discard the buffer. */
+    s->position = 0; 
+    s->srptr = s->srlimit = s->cbuf - 1;
+    s->end_status = 0;
+}
+
+static int
+s_aos_flush(stream *s)
+{
+    s->position = ((aos_state_t *)s->state)->file_sz;
+    s->srptr = s->srlimit = s->cbuf - 1;
+    return 0;
+}
+
+static int
+s_aos_close(stream * s)
+{
+    gs_free_object(s->memory, s->cbuf, "s_aos_close(buffer)");
+    s->cbuf = 0;
+    /* Increment the IDs to prevent further access. */
+    s->read_id = s->write_id = (s->read_id | s->write_id) + 1;
+    return 0;
+}
+
+static int
+s_aos_process(stream_state * st, stream_cursor_read * ignore_pr,
+		      stream_cursor_write * pw, bool last)
+{
+    int blk_i, blk_off, blk_cnt, status = 1;
+    uint count;
+    aos_state_t *ss = (aos_state_t *)st;
+    uint max_count = pw->limit - pw->ptr;
+    uint pos = stell(ss->s);
+    unsigned const char *data;
+    ref *blk_ref;
+
+    if (pos >= ss->file_sz)
+	return EOFC;
+    blk_i   = pos / ss->blk_sz;
+    blk_off = pos % ss->blk_sz;
+    blk_cnt = r_size(&ss->blocks);
+    count = blk_i < blk_cnt - 1 ? ss->blk_sz : ss->blk_sz_last;
+    blk_ref = ss->blocks.value.refs;
+    data = blk_ref[blk_i].value.bytes;
+
+    if (max_count > count - blk_off) {
+        max_count = count - blk_off;
+        if (blk_i == blk_cnt - 1)
+	     status = EOFC;	
+    }
+    memcpy(pw->ptr+1, data + blk_off, max_count);
+    pw->ptr += max_count;
+    return status;
+}
+
 /* ---------------- Initialization procedure ---------------- */
 
 const op_def zfrsd_op_defs[] =



More information about the gs-cvs mailing list