#REFACTORING by stefan
Refactor for common code.
Better documentation
class: Stream
comment/format in:
#copyToEndFrom:
#copyToEndInto:
#copyToEndInto:bufferSize:
changed:
#copy:into: (send #bufferSizeForBulkFileCopy instead of #bufferSizeForBulkCopy)
#copy:into:bufferSize:
category of:
#copy:into:
#copy:into:bufferSize:
#copyToEndFrom:
#copyToEndInto:
#copyToEndInto:bufferSize:
class: Stream class
added: #bufferSizeForBulkCopy
--- a/Stream.st Wed Mar 13 17:01:22 2019 +0100
+++ b/Stream.st Wed Mar 13 17:04:15 2019 +0100
@@ -216,6 +216,14 @@
^ ChunkSeparator
! !
+!Stream class methodsFor:'defaults'!
+
+bufferSizeForBulkCopy
+ ^ 128 * 1024
+
+ "Created: / 13-03-2019 / 16:50:04 / Stefan Vogel"
+! !
+
!Stream class methodsFor:'testing'!
isAbstract
@@ -723,181 +731,6 @@
"Created: 13.9.1996 / 18:33:26 / cg"
! !
-!Stream methodsFor:'misc functions'!
-
-copy:numberOfBytes into:outStream
- "read from the receiver, and write numberOfBytes data to another aWriteStream.
- Return the number of bytes which have been transferred."
-
- ^ self copy:numberOfBytes into:outStream bufferSize:(128*1024)
-!
-
-copy:numberOfBytes into:aWriteStream bufferSize:bufferSizeArg
- "read from the receiver, and write numberOfBytes data to another aWriteStream.
- Return the number of bytes which have been transferred."
-
- |bufferSpecies bufferSize bytesLeft buffer countWritten freeBuffer|
-
- countWritten := 0.
- bufferSpecies := self contentsSpecies.
- bytesLeft := numberOfBytes.
- bufferSize := bufferSizeArg min:numberOfBytes.
-
- bufferSpecies == ByteArray ifTrue:[
- "an ExternalBytes buffer is faster when writing to a windows ExternalStream"
- buffer:= ExternalBytes unprotectedNew:bufferSize.
- freeBuffer := true.
- ] ifFalse:[
- buffer := bufferSpecies new:bufferSize.
- freeBuffer := false.
- ].
-
- "read loop: read required bytes"
- [
- |readCount writeCount|
-
- readCount := self nextAvailable:(bytesLeft min:bufferSize) into:buffer startingAt:1.
- readCount ~~ 0 ifTrue:[
- bytesLeft := bytesLeft - readCount.
- writeCount := 0.
- "write loop: write until all is written"
- [
- |count|
-
- count := aWriteStream
- nextPutAll:readCount-writeCount
- from:buffer
- startingAt:writeCount+1.
- writeCount := writeCount + count.
- writeCount < readCount ifTrue:[
- aWriteStream writeWait.
- true.
- ] ifFalse:[
- false
- ].
- ] whileTrue.
- countWritten := countWritten + writeCount.
- ].
- "Note: atEnd will block if reading from an empty pipe or socket.
- avoid atEnd if possible, because it reads a single byte."
- (bytesLeft == 0) or:[readCount == 0 and:[self atEnd]]
- ] whileFalse.
-
- freeBuffer ifTrue:[ buffer free ].
- ^ countWritten.
-
- "
- |s|
- s := WriteStream on:(String new:100).
- '/etc/passwd' asFilename readStream
- copy:100 into:s bufferSize:10.
- s contents
- "
-
- "Modified: / 13-03-2019 / 12:00:46 / Claus Gittinger"
- "Modified: / 13-03-2019 / 12:50:48 / Stefan Vogel"
-!
-
-copyToEndFrom:inStream
- "read from inStream, and write all data up to the end to the receiver.
- Return the number of bytes which have been transferred.
- Same functionality as copyToEnd:, but reversed arg and receiver
- (useful in a cascade message of the writeStream)"
-
- ^ inStream copyToEndInto:self
-!
-
-copyToEndInto:outStream
- "read from the receiver, and write all data up to the end to another stream.
- Return the number of bytes which have been transferred"
-
- ^ self copyToEndInto:outStream bufferSize:(128*1024)
-
-"/ data rate to USB2.0 stick (Win32):
-"/ 120 KB/s 8Kb SingleBuffer
-"/ 741 KB/s 64Kb SingleBuffer
-"/ 1345 KB/s 128Kb SingleBuffer
-"/ 2087 KB/s 256Kb SingleBuffer
-"/ 3573 KB/s 1024Kb SingleBuffer
-
-"/|t retVal|
-"/
-"/t := Time millisecondsToRun:[
-"/ retVal := self copyToEndInto:outStream bufferSize:(64*1024).
-"/].
-"/
-"/Transcript showCR:('%1 KB copied in %2s (%3 KB/s)'
-"/ bindWith:((retVal/1024)asFixedPoint:2)
-"/ with:((t/1000)asFixedPoint:2)
-"/ with:((retVal/1024/(t/1000))asFixedPoint:2)).
-"/^ retVal.
-"/
-!
-
-copyToEndInto:outStream bufferSize:bufferSize
- "read from the receiver, and write all data up to the end to another stream.
- Return the number of bytes which have been transferred"
-
- |bufferSpecies buffer countWritten freeBuffer|
-
- countWritten := 0.
- bufferSpecies := self contentsSpecies.
- bufferSpecies == ByteArray ifTrue:[
- "an ExternalBytes buffer is faster when writing to a windows ExternalStream"
- buffer:= ExternalBytes unprotectedNew:bufferSize.
- freeBuffer := true.
- ] ifFalse:[
- buffer := bufferSpecies new:bufferSize.
- freeBuffer := false.
- ].
-
- "read loop: read until end of stream"
- [
- |readCount|
-
- readCount := self nextAvailable:bufferSize into:buffer startingAt:1.
- readCount > 0 ifTrue:[
- |writeCount|
-
- writeCount := 0.
- "write loop: write until all is written"
- [
- |count|
-
- count := outStream
- nextPutAll:readCount-writeCount
- from:buffer
- startingAt:writeCount+1.
- writeCount := writeCount + count.
- writeCount < readCount ifTrue:[
- outStream writeWait.
- true.
- ] ifFalse:[
- false
- ].
- ] whileTrue.
- countWritten := countWritten + writeCount.
- ].
- "Note: atEnd will block if reading from an empty pipe or socket.
- avoid atEnd if possible, because it reads a single byte."
- readCount ~~ 0 or:[self atEnd not]
- ] whileTrue.
-
- freeBuffer ifTrue:[ buffer free ].
- ^ countWritten
-
- "
- 'hello world' readStream copyToEndInto:'/tmp/mist' asFilename writeStream.
- 'hello world' readStream copyToEndInto:#[] writeStream.
- ('/tmp/mist' asFilename readStream binary; yourself) copyToEndInto:#[] writeStream
- #[1 2 3 4 5 6 7] readStream copyToEndInto:'/tmp/mist' asFilename writeStream.
- #(1 2 3 a 'b' 6.4 true) readStream next; copyToEndInto:#() writeStream inspect.
-
- "
-
- "Modified: / 13-03-2019 / 11:54:17 / Claus Gittinger"
-! !
-
!Stream methodsFor:'non homogenous reading'!
nextAvailableBytes:numBytes into:aCollection startingAt:initialIndex
@@ -3785,6 +3618,159 @@
! !
+!Stream methodsFor:'stream-to-stream copy'!
+
+copy:numberOfElementsOrNil into:outStream
+ "read from the receiver, and write numberOfElements elements to outStream, a WriteStream.
+ Return the number of elements which have been transferred.
+ If numberOfElementsOrNil is nil, copy until the end of myself."
+
+ ^ self copy:numberOfElementsOrNil into:outStream bufferSize:(self class bufferSizeForBulkCopy)
+
+ "Modified (comment): / 13-03-2019 / 17:03:47 / Stefan Vogel"
+!
+
+copy:numberOfElementsOrNil into:aWriteStream bufferSize:bufferSizeArg
+ "read from the receiver, and write numberOfElementsOrNil elements to outStream, a WriteStream.
+ Return the number of elements which have been transferred.
+ If numberOfElementsOrNil is nil, copy until the end of myself."
+
+ |bufferSpecies bufferSize elementsLeft buffer countWritten freeBuffer|
+
+ countWritten := 0.
+ numberOfElementsOrNil isNil ifTrue:[
+ "read to end..."
+ elementsLeft := -1.
+ bufferSize := bufferSizeArg.
+ ] ifFalse:[
+ elementsLeft := numberOfElementsOrNil.
+ bufferSize := bufferSizeArg min:numberOfElementsOrNil.
+ ].
+
+ bufferSpecies := self contentsSpecies.
+ bufferSpecies == ByteArray ifTrue:[
+ "an ExternalBytes buffer is faster when writing to a windows ExternalStream"
+ buffer:= ExternalBytes unprotectedNew:bufferSize.
+ freeBuffer := true.
+ ] ifFalse:[
+ buffer := bufferSpecies new:bufferSize.
+ freeBuffer := false.
+ ].
+
+ "read loop: read required bytes"
+ [
+ |readCount writeCount|
+
+ readCount := self nextAvailable:bufferSize into:buffer startingAt:1.
+ readCount ~~ 0 ifTrue:[
+ elementsLeft := elementsLeft - readCount.
+ writeCount := 0.
+ "write loop: write until all is written"
+ [
+ |count|
+
+ count := aWriteStream
+ nextPutAll:readCount-writeCount
+ from:buffer
+ startingAt:writeCount+1.
+ writeCount := writeCount + count.
+ writeCount < readCount ifTrue:[
+ aWriteStream writeWait.
+ true.
+ ] ifFalse:[
+ false
+ ].
+ ] whileTrue.
+ countWritten := countWritten + writeCount.
+ ].
+ "Note: atEnd will block if reading from an empty pipe or socket.
+ avoid atEnd if possible, because it reads a single byte.
+ If we read until end, bytesLeft is negative and will never become 0!!"
+ (elementsLeft == 0) or:[readCount == 0 and:[self atEnd]]
+ ] whileFalse.
+
+ freeBuffer ifTrue:[ buffer free ].
+ ^ countWritten.
+
+ "
+ |s|
+ s := WriteStream on:(String new:100).
+ '/etc/passwd' asFilename readStream
+ copy:nil into:s bufferSize:10.
+ s contents
+
+ |s|
+ s := WriteStream on:(String new:100).
+ '/etc/passwd' asFilename readStream
+ copy:100 into:s bufferSize:10.
+ s contents
+ "
+
+ "Modified: / 13-03-2019 / 12:00:46 / Claus Gittinger"
+ "Modified (comment): / 13-03-2019 / 17:03:20 / Stefan Vogel"
+!
+
+copyToEndFrom:inStream
+ "read from inStream, and write all elements up to the end to the receiver.
+ Return the number of elements which have been transferred.
+ Same functionality as #copyToEndInto:, but reversed arg and receiver
+ (useful in a cascade message of the writeStream)"
+
+ ^ inStream copy:nil into:self
+
+ "Modified (comment): / 13-03-2019 / 17:02:19 / Stefan Vogel"
+!
+
+copyToEndInto:outStream
+ "read from the receiver, and write all elements up to the end to outStream, a WriteStream.
+ Return the number of elements which have been transferred"
+
+ ^ self copy:nil into:outStream bufferSize:(self class bufferSizeForBulkCopy)
+
+"/ data rate to USB2.0 stick (Win32):
+"/ 120 KB/s 8Kb SingleBuffer
+"/ 741 KB/s 64Kb SingleBuffer
+"/ 1345 KB/s 128Kb SingleBuffer
+"/ 2087 KB/s 256Kb SingleBuffer
+"/ 3573 KB/s 1024Kb SingleBuffer
+
+"/|t retVal|
+"/
+"/t := Time millisecondsToRun:[
+"/ retVal := self copyToEndInto:outStream bufferSize:(64*1024).
+"/].
+"/
+"/Transcript showCR:('%1 KB copied in %2s (%3 KB/s)'
+"/ bindWith:((retVal/1024)asFixedPoint:2)
+"/ with:((t/1000)asFixedPoint:2)
+"/ with:((retVal/1024/(t/1000))asFixedPoint:2)).
+"/^ retVal.
+"/
+
+ "Modified (comment): / 13-03-2019 / 17:03:04 / Stefan Vogel"
+!
+
+copyToEndInto:outStream bufferSize:bufferSize
+ "read from the receiver, and write all elements up to the end to outStream, aWriteStream.
+ Return the number of elements which have been transferred"
+
+ ^ self copy:nil into:outStream bufferSize:bufferSize
+
+ "
+ 'hello world' readStream copyToEndInto:'/tmp/mist' asFilename writeStream.
+ 'hello world' readStream copyToEndInto:'' writeStream.
+ ('/tmp/mist' asFilename readStream binary; yourself) copyToEndInto:#[] writeStream
+ #[1 2 3 4 5 6 7] readStream copyToEndInto:'/tmp/mist' asFilename writeStream binary; yourself.
+
+ |s|
+ s := #() writeStream.
+ #(1 2 3 a 'b' 6.4 true) readStream next; copyToEndInto:s. s inspect.
+ "
+
+ "Modified: / 13-03-2019 / 11:54:17 / Claus Gittinger"
+ "Modified (comment): / 13-03-2019 / 17:02:51 / Stefan Vogel"
+! !
+
!Stream methodsFor:'testing'!
atEnd