help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] [PATCH] Allow "stream nextPutAll: anotherStream"


From: Paolo Bonzini
Subject: [Help-smalltalk] [PATCH] Allow "stream nextPutAll: anotherStream"
Date: Fri, 18 May 2007 13:34:22 +0200
User-agent: Thunderbird 2.0.0.0 (Macintosh/20070326)

Various optimizations inhibit this in FileDescriptor and FileStream. This patch works around them.

Among other things, it allows writing a ZlibStream onto a file just by doing a #nextPutAll:.

Paolo
2007-05-18  Paolo Bonzini  <address@hidden>

        * kernel/ByteStream.st: Support #nextPutAll: of Streams into Streams.
        * kernel/Collection.st: Add #isSequenceable.
        * kernel/FileDescr.st: Add #next:putAll:startingAt:.  Support
        #nextPutAll: of Streams into Streams.  Fix #next:
        * kernel/FileStream.st: Support #nextPutAll: of Streams into Streams.
        * kernel/SeqCollect.st: Add #isSequenceable.
        * kernel/Stream.st: Add #isSequenceable.  Support #nextPutAll: of
        Streams into Streams.



--- orig/kernel/ByteStream.st
+++ mod/kernel/ByteStream.st
@@ -164,6 +164,9 @@ nextPutByte: anInteger
 nextPutAll: aCollection
     "Write all the objects in aCollection to the receiver"
     | collEnd relative lastCopied |
+    aCollection isSequenceable
+       ifFalse: [ ^super nextPutAll: aCollection ].
+
     aCollection isEmpty ifTrue: [ ^self ].
 
     collEnd := ptr + aCollection size - 1.


--- orig/kernel/Collection.st
+++ mod/kernel/Collection.st
@@ -159,6 +159,12 @@ removeAll: aCollection ifAbsent: aBlock
 
 !Collection methodsFor: 'testing collections'!
 
+isSequenceable
+    "Answer whether the receiver can be accessed by a numeric index with
+     #at:/#at:put:."
+    ^false
+!
+
 capacity
     "Answer how many elements the receiver can hold before having to grow."
     ^self basicSize


--- orig/kernel/FileDescr.st
+++ mod/kernel/FileDescr.st
@@ -517,8 +517,21 @@ isEmpty
     ^self size == 0
 !
 
+next: n putAll: aCollection startingAt: position
+    "Put the characters in the supplied range of aCollection in the file"
+    ^self write: aCollection from: position to: position + n - 1!
+
 nextPutAll: aCollection
     "Put all the characters in aCollection in the file"
+    | stream |
+    aCollection isSequenceable ifFalse: [
+       [ stream := aCollection readStream ]
+           on: MessageNotUnderstood
+           do: [ :ex | ex return: aCollection asString readStream ].
+
+       [ stream atEnd ] whileFalse: [ self write: stream nextHunk ].
+       ^self ].
+
     self write: aCollection asString
 !
 
@@ -543,8 +556,8 @@ next: anInteger
     n = 0
        ifTrue: [ atEnd := true ].
     ^n < anInteger
-       ifTrue: [ collection copyFrom: 1 to: n ]
-       ifFalse: [ collection ].
+       ifTrue: [ result copyFrom: 1 to: n ]
+       ifFalse: [ result ].
 ! !
 
 


--- orig/kernel/FileStream.st
+++ mod/kernel/FileStream.st
@@ -365,7 +365,20 @@ nextPutAllFlush: aCollection
 nextPutAll: aCollection
     "Put all the characters in aCollection in the file"
     | n coll written |
-    coll := aCollection asString.
+    "Just do 'coll := aCollection asString', but avoid expensive operations
+     in the common case where aCollection is already a String."
+    coll := aCollection isSequenceable
+       ifTrue: [ aCollection ]
+       ifFalse: [
+           [ aCollection asString ]
+               on: MessageNotUnderstood
+               do: [ :ex |
+                   "If we are in a stream, try to facilitate buffering."
+                   [ aCollection atEnd ] whileFalse: [
+                       coll := aCollection nextHunk.
+                       self next: coll size putAll: coll startingAt: 1 ].
+                   ^self ] ].
+
     n := coll size.
     written := collection size - ptr + 1 min: n.
     self next: written bufferAll: coll startingAt: 1.


--- orig/kernel/SeqCollect.st
+++ mod/kernel/SeqCollect.st
@@ -105,6 +105,12 @@ inspect
 !
 
 
+isSequenceable
+    "Answer whether the receiver can be accessed by a numeric index with
+     #at:/#at:put:."
+    ^true
+!
+
 = aCollection
     "Answer whether the receiver's items match those in aCollection"
 


--- orig/kernel/Stream.st
+++ mod/kernel/Stream.st
@@ -196,7 +196,9 @@ next: n putAll: aCollection startingAt: 
 
 nextPutAll: aCollection
     "Write all the objects in aCollection to the receiver"
-    aCollection do: [ :element | self nextPut: element ].
+    aCollection isSequenceable
+       ifTrue: [ self next: aCollection size putAll: aCollection startingAt: 1 
]
+       ifFalse: [ aCollection do: [ :element | self nextPut: element ] ].
     ^aCollection
 !
 
@@ -215,6 +217,18 @@ atEnd
     self subclassResponsibility
 !
 
+readStream
+    "As a wild guess, return the receiver.  WriteStreams should override
+     this method."
+    ^self
+!
+
+isSequenceable
+    "Answer whether the receiver can be accessed by a numeric index with
+     #at:/#at:put:."
+    ^false
+!
+
 isExternalStream
     "Answer whether the receiver streams on a file or socket.
      By default, answer false."




reply via email to

[Prev in Thread] Current Thread [Next in Thread]