--- 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:[
"/