#DOCUMENTATION by stefan
class: FileStream
comment/format in: #copy:into:bufferSize:
category of:
#copy:into:bufferSize:
#isDirectory
#isEmpty
#truncateTo:
--- a/FileStream.st Tue Apr 28 14:38:55 2020 +0200
+++ b/FileStream.st Tue Apr 28 14:41:07 2020 +0200
@@ -934,174 +934,10 @@
!FileStream methodsFor:'misc functions'!
-copy:numberOfBytesOrNil into:outStream bufferSize:bufferSize
- "read from the receiver, and write numberOfBytes data to another aWriteStream.
- Return the number of bytes which have been transferred.
- If nuberOfBytesOrNil is nil, copy until the end of myself.
- Redefined to use operating system features to do a fast copy."
-
- |nToWrite nWritten fromFd toFd|
-
- nToWrite := numberOfBytesOrNil.
- outStream isExternalStream ifTrue:[
- "/ try optimized system call
- fromFd := self fileHandle.
- fromFd isNil ifTrue:[
- self errorNotOpen.
- ^ 0.
- ].
- toFd := outStream fileHandle.
- toFd isNil ifTrue:[
- outStream errorNotOpen.
- ^ 0.
- ].
-
- nToWrite isNil ifTrue:[
- "/ write to end
- nToWrite := self fileSize - self position.
- ].
-
- "sendfile() in Linux does not support any combination of file/pipe/socket fds.
- #copyFromFd:toFd:startIndex:count: is currently not available in windows.
- Both will return 0 and fall through to super."
-
- nWritten := OperatingSystem
- copyFromFd:fromFd
- toFd:toFd
- startIndex:nil "/ nil -> start at the current position
- count:nToWrite.
- nWritten > 0 ifTrue:[
- "/ sendfile() changes the position in fromFd and toFd.
- "/ sending #position fixes the position instVar as a side effect.
- self position.
- outStream isPositionable ifTrue:[
- outStream position.
- ].
-
- nWritten == nToWrite ifTrue:[
- "we are finished, all has been written"
- ^ nToWrite
- ].
- "some data has not been written.
- Maybe an error occured. We will get the error whe we #copy the rest below"
- nToWrite := nToWrite - nWritten.
- ^ nWritten + (super copy:nToWrite into:outStream bufferSize:bufferSize).
- ].
- ].
-
- "fall back..."
- ^ super copy:nToWrite into:outStream bufferSize:bufferSize.
-
- "
- |in out|
-
- in := 'Make.proto' asFilename readStream.
- in copyToEndInto:Stdout.
- in close.
- "
-
- "
- |in out|
-
- in := 'Make.proto' asFilename readStream.
- out := '/tmp/test' asFilename newReadWriteStream.
- in copyToEndInto:out.
- self assert:(in fileSize = out fileSize).
- self assert:(in position = in fileSize).
- self assert:(in atEnd).
- self assert:(in position = out position).
- in reset. out reset.
- self assert:(in contents = out contents).
- in close. out close.
-
- '/tmp/test' asFilename contents.
- "
-
- "Created: / 13-03-2019 / 16:27:04 / Stefan Vogel"
- "Modified (format): / 25-05-2019 / 16:47:53 / Claus Gittinger"
- "Modified (format): / 28-04-2020 / 11:45:46 / Stefan Vogel"
-!
-
syncFileSystem
"sync the filesystem containing this FileStream"
OperatingSystem syncFileSystem:handle.
-!
-
-truncateTo:newSize
- "truncate the underlying OS file to newSize.
- Warning: this may not be implemented on all platforms."
-
-%{
-#ifdef HAS_FTRUNCATE
- OBJ fp = __INST(handle);
- FILE *f;
- off_t truncateSize;
-
- if ((fp != nil) && (__INST(mode) != @symbol(readonly))) {
- if (__isSmallInteger(newSize)) {
- truncateSize = __intVal(newSize);
- if (truncateSize < 0) {
- goto getOutOfHere;
- }
- } else {
- truncateSize = __signedLongIntVal(newSize);
- if (truncateSize < 0) {
- goto getOutOfHere;
- }
- if (truncateSize == 0) {
- if (sizeof(truncateSize) == 8) {
- if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
- goto getOutOfHere;
- }
- } else {
- goto getOutOfHere;
- }
- }
- }
-
- f = __FILEVal(fp);
-
- if (__INST(buffered) == true) {
- fflush(f);
- fseek(f, 0L, SEEK_END); /* needed in stdio */
- }
- ftruncate(fileno(f), truncateSize);
-
- // oops - must also position
- if (__INST(buffered) == true) {
- fseek(f, truncateSize, SEEK_SET);
- } else {
- lseek(fileno(f), truncateSize, SEEK_SET);
- }
- __INST(position) = newSize; __STORE(self, newSize);
-
- RETURN (self);
- }
-getOutOfHere: ;
-#endif
-%}.
- handle isNil ifTrue:[self errorNotOpen. ^ self].
- (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
- newSize < 0 ifTrue:[
- self error:'wrong arg'.
- ].
- self errorUnsupportedOperation
-
- "
- |f s|
-
- f := 'testTTTT' asFilename.
- s := f writeStream.
- s next:1000 put:$a.
- s truncateTo:100.
- s close.
-
- Transcript showCR:(f fileSize).
- f remove.
- "
-
- "Modified: / 02-08-2017 / 09:44:32 / cg"
! !
!FileStream methodsFor:'positioning'!
@@ -1391,6 +1227,82 @@
pos0Based := self position.
].
"/ ('FileStream [info]: slow position - please convert ''' , pathName printString , ''' to streamLF format') infoPrintCR.
+!
+
+truncateTo:newSize
+ "truncate the underlying OS file to newSize.
+ Warning: this may not be implemented on all platforms."
+
+%{
+#ifdef HAS_FTRUNCATE
+ OBJ fp = __INST(handle);
+ FILE *f;
+ off_t truncateSize;
+
+ if ((fp != nil) && (__INST(mode) != @symbol(readonly))) {
+ if (__isSmallInteger(newSize)) {
+ truncateSize = __intVal(newSize);
+ if (truncateSize < 0) {
+ goto getOutOfHere;
+ }
+ } else {
+ truncateSize = __signedLongIntVal(newSize);
+ if (truncateSize < 0) {
+ goto getOutOfHere;
+ }
+ if (truncateSize == 0) {
+ if (sizeof(truncateSize) == 8) {
+ if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) {
+ goto getOutOfHere;
+ }
+ } else {
+ goto getOutOfHere;
+ }
+ }
+ }
+
+ f = __FILEVal(fp);
+
+ if (__INST(buffered) == true) {
+ fflush(f);
+ fseek(f, 0L, SEEK_END); /* needed in stdio */
+ }
+ ftruncate(fileno(f), truncateSize);
+
+ // oops - must also position
+ if (__INST(buffered) == true) {
+ fseek(f, truncateSize, SEEK_SET);
+ } else {
+ lseek(fileno(f), truncateSize, SEEK_SET);
+ }
+ __INST(position) = newSize; __STORE(self, newSize);
+
+ RETURN (self);
+ }
+getOutOfHere: ;
+#endif
+%}.
+ handle isNil ifTrue:[self errorNotOpen. ^ self].
+ (mode == #readonly) ifTrue:[self errorReadOnly. ^ self].
+ newSize < 0 ifTrue:[
+ self error:'wrong arg'.
+ ].
+ self errorUnsupportedOperation
+
+ "
+ |f s|
+
+ f := 'testTTTT' asFilename.
+ s := f writeStream.
+ s next:1000 put:$a.
+ s truncateTo:100.
+ s close.
+
+ Transcript showCR:(f fileSize).
+ f remove.
+ "
+
+ "Modified: / 02-08-2017 / 09:44:32 / cg"
! !
!FileStream methodsFor:'printing & storing'!
@@ -2169,16 +2081,6 @@
"Modified: / 22-11-2018 / 14:53:12 / Stefan Vogel"
!
-isDirectory
- ^ OperatingSystem isDirectory:pathName
-!
-
-isEmpty
- "common stream protocol: are there no bytes in the file?"
-
- ^ self fileSize == 0.
-!
-
remainingSize
"return the number of remaining elements to read in the streamed collection."
@@ -2204,8 +2106,108 @@
self primitiveFailed
! !
+!FileStream methodsFor:'stream-to-stream copy'!
+
+copy:numberOfBytesOrNil into:outStream bufferSize:bufferSize
+ "read from the receiver, and write numberOfBytes data to another aWriteStream.
+ Return the number of bytes which have been transferred.
+ If nuberOfBytesOrNil is nil, copy until the end of myself.
+ Redefined to use operating system features to do a fast copy."
+
+ |nToWrite nWritten fromFd toFd|
+
+ nToWrite := numberOfBytesOrNil.
+ outStream isExternalStream ifTrue:[
+ "/ try optimized system call
+ fromFd := self fileHandle.
+ fromFd isNil ifTrue:[
+ self errorNotOpen.
+ ^ 0.
+ ].
+ toFd := outStream fileHandle.
+ toFd isNil ifTrue:[
+ outStream errorNotOpen.
+ ^ 0.
+ ].
+
+ nToWrite isNil ifTrue:[
+ "/ write to end
+ nToWrite := self fileSize - self position.
+ ].
+
+ "sendfile() in Linux does not support any combination of file/pipe/socket fds.
+ #copyFromFd:toFd:startIndex:count: is currently not available in windows.
+ Both will return 0 and fall through to super."
+
+ nWritten := OperatingSystem
+ copyFromFd:fromFd
+ toFd:toFd
+ startIndex:nil "/ nil -> start at the current position of fromFd
+ count:nToWrite.
+ nWritten > 0 ifTrue:[
+ "/ sendfile() changes the position in fromFd and toFd.
+ "/ sending #position fixes the position instVar as a side effect.
+ self position.
+ outStream isPositionable ifTrue:[
+ outStream position.
+ ].
+
+ nWritten == nToWrite ifTrue:[
+ "we are finished, all has been written"
+ ^ nToWrite
+ ].
+ "some data has not been written.
+ Maybe an error occured. We will get the error whe we #copy the rest below"
+ nToWrite := nToWrite - nWritten.
+ ^ nWritten + (super copy:nToWrite into:outStream bufferSize:bufferSize).
+ ].
+ ].
+
+ "fall back..."
+ ^ super copy:nToWrite into:outStream bufferSize:bufferSize.
+
+ "
+ |in out|
+
+ in := 'Make.proto' asFilename readStream.
+ in copyToEndInto:Stdout.
+ in close.
+ "
+
+ "
+ |in out|
+
+ in := 'Make.proto' asFilename readStream.
+ out := '/tmp/test' asFilename newReadWriteStream.
+ in copyToEndInto:out.
+ self assert:(in fileSize = out fileSize).
+ self assert:(in position = in fileSize).
+ self assert:(in atEnd).
+ self assert:(in position = out position).
+ in reset. out reset.
+ self assert:(in contents = out contents).
+ in close. out close.
+
+ '/tmp/test' asFilename contents.
+ "
+
+ "Created: / 13-03-2019 / 16:27:04 / Stefan Vogel"
+ "Modified (format): / 25-05-2019 / 16:47:53 / Claus Gittinger"
+ "Modified (comment): / 28-04-2020 / 11:59:00 / Stefan Vogel"
+! !
+
!FileStream methodsFor:'testing'!
+isDirectory
+ ^ OperatingSystem isDirectory:pathName
+!
+
+isEmpty
+ "common stream protocol: are there no bytes in the file?"
+
+ ^ self fileSize == 0.
+!
+
isFileStream
"return true, if the receiver is some kind of fileStream.
redefined from Object"