ExtStream.st
changeset 665 429936f8e6e7
parent 612 e640bef6170e
child 668 73165201a9da
--- a/ExtStream.st	Sun Dec 03 15:37:50 1995 +0100
+++ b/ExtStream.st	Sun Dec 03 17:25:38 1995 +0100
@@ -177,7 +177,7 @@
 !
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Attic/ExtStream.st,v 1.70 1995-11-23 01:48:32 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Attic/ExtStream.st,v 1.71 1995-12-03 16:25:38 cg Exp $'
 ! !
 
 !ExternalStream class methodsFor:'initialization'!
@@ -2287,37 +2287,29 @@
      doesnt really matter, since C-primitives are an ST/X feature anyway.
      Reimplemented here for more speed."
 
-    |retVal outOfMemory|
+    |retVal outOfMemory buffer|
 
     filePointer isNil ifTrue:[^ self errorNotOpen].
     binary ifTrue:[^ self errorBinary].
     (mode == #writeonly) ifTrue:[^ self errorWriteOnly].
 
 %{  /* STACK: 8000 */
+    /*
+     * the main trick (and a bit of complication) here
+     * is to read the first 4k into a stack-buffer.
+     * Since most chunks fit into that, 
+     * this avoids creating lots of garbage for thos small chunks.
+     */
     FILE *f;
     int done = 0;
     REGISTER int c;
     int peekC;
-    static char *buffer = (char *)0;
-    static fastFlag = 0;
-    char fastBuffer[1024];
-    char *newBuffer;
+    char *bufferPtr = (char *)0;
+    char fastBuffer[4096];
     REGISTER int index;
-    int currSize;
+    int currSize, fastFlag;
     int inComment, inString, inPrimitive = 0;
-    OBJ __MKSTRING_L();
-
-    if (!fastFlag && buffer) {
-	/*
-	 * we have to be very careful with the buffer, 
-	 * since in case of an interrupt while reading,
-	 * the method below is left and noone frees the
-	 * memory. To cleanup, we keep the ptr in a static and
-	 * free it when we come here the next time.
-	 */
-	free(buffer);
-	buffer = (char *)0;
-    }
+    OBJ __MKSTRING_L(), __MKSTRING_ST_L(), __MKEMPTYSTRING();
 
     _INST(lastErrorNumber) = nil;
     f = __FILEVal(_INST(filePointer));
@@ -2366,7 +2358,7 @@
     /*
      * read chunk into a buffer
      */
-    buffer = fastBuffer; fastFlag = 1;
+    bufferPtr = fastBuffer; fastFlag = 1;
     currSize = sizeof(fastBuffer);
 
     index = 0;
@@ -2375,21 +2367,29 @@
 	 * do we have to resize the buffer ? 
 	 */
 	if ((index+2) >= currSize) {
-	    newBuffer = (char *)malloc(currSize * 2);
-	    if (! newBuffer) {
+    	    OBJ newBuffer;
+	    char *nbp;
+
+	    newBuffer = __MKEMPTYSTRING(currSize * 2 COMMA_CON);
+	    if (newBuffer == nil) {
 		/*
 		 * mhmh - chunk seems to be very big ....
 		 */
 		outOfMemory = true;
 		goto err;
 	    }
-	    bcopy(buffer, newBuffer, index);
-	    if (fastFlag) {
-		fastFlag = 0;
-	    } else {
-		free(buffer);
+	    nbp = __stringVal(newBuffer);
+	    if (!fastFlag) {
+		/*
+		 * old buffer may have moved - refetch pointer
+		 */
+		bufferPtr = __stringVal(buffer);
 	    }
+	    bcopy(bufferPtr, nbp, index);
+	    bufferPtr = nbp;
+	    bufferPtr[index] = '\0';
 	    buffer = newBuffer;
+	    fastFlag = 0;
 	    currSize = currSize * 2;
 	}
 
@@ -2405,6 +2405,7 @@
 		peekC = getc(f);
 	    } while (peekC < 0 && (errno == EINTR));
 	    __END_INTERRUPTABLE__
+
 	    ungetc(peekC, f);
 	    if (peekC == '{') {
 		inPrimitive++;
@@ -2436,19 +2437,21 @@
 	    }
 	    break;
 	}
-	buffer[index++] = c;
+	bufferPtr[index++] = c;
     }
 
-    buffer[index] = '\0';
     /*
      * make it a string
+     * be careful here - allocating a new string may make the
+     * existing buffer move around. Need to check if copying from
+     * fast (C) buffer or from real (ST) buffer.
      */
-    retVal = __MKSTRING_L(buffer, index COMMA_CON);
-err:
-    if (!fastFlag && buffer) {
-	free(buffer);
-	buffer = (char *)0;
+    if (fastFlag) {
+        retVal = __MKSTRING_L(bufferPtr, index COMMA_CON);
+    } else {
+	retVal = __MKSTRING_ST_L(buffer, index COMMA_CON);
     }
+err: ;
 %}.
     retVal isNil ifTrue:[
 	"/