[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] [PATCH] Block-level stream input protocol
From: |
Paolo Bonzini |
Subject: |
[Help-smalltalk] [PATCH] Block-level stream input protocol |
Date: |
Wed, 06 Aug 2008 09:36:55 +0200 |
User-agent: |
Thunderbird 2.0.0.16 (Macintosh/20080707) |
This patch adds another important set of methods, that allows to
eliminate useless creation of collections when stream-to-stream
operation is not possible. These are #nextAvailable:into:startingAt:
and #next:into:startingAt:.
This patch also cleans up the file code, because
#nextAvailable:into:startingAt: can replace the old method #read:from:to:.
Paolo
diff --git a/ChangeLog b/ChangeLog
index 786a934..d896ec0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2008-08-05 Paolo Bonzini <address@hidden>
+ * kernel/FileDescr.st: Remove #read:... methods, except
+ #read:from:to: which becomes #nextAvailable:into:startingAt:.
+ Remove #write:... methods except #write:from:to: which becomes
+ #next:putAll:startingAt:. Remove #next:, #nextAvailable:,
+ #nextHunk, #nextHunkPutAllOn: to use the superclass version,
+ change #next:into: to #next:into:startingAt:.
+ * kernel/FileStream.st: Change calls to #read:form:to:
+ and #write:from:to: to super sends. Change #nextAvailable:
+ to #nextAvailable:into:startingAt:, #next:into: to
+ #next:into:startingAt:.
+ * kernel/PosStream.st: Add #nextAvailable:into:startingAt:.
+ * kernel/Stream.st: Add #next:into:startingAt: and
+ #nextAvailable:into:startingAt:, use them in #next:,
+ #nextAvailable:, #nextHunk.
+
+2008-08-05 Paolo Bonzini <address@hidden>
+
* kernel/Stream.st: Do not use Streams in the default implementation
of #nextAvailable:.
diff --git a/kernel/FileDescr.st b/kernel/FileDescr.st
index 340b6e6..043f204 100644
--- a/kernel/FileDescr.st
+++ b/kernel/FileDescr.st
@@ -342,7 +342,7 @@ do arbitrary processing on the files.'>
result := 1]
ifTrue:
[data := self species new: 1.
- result := self read: data from: 1 to: 1.
+ result := self nextAvailable: 1 into: data startingAt: 1.
data := data at: 1].
^result > 0
ifTrue: [data]
@@ -368,7 +368,7 @@ do arbitrary processing on the files.'>
| result data |
peek isNil ifFalse: [^peek].
data := self species new: 1.
- result := self read: data from: 1 to: 1.
+ result := self nextAvailable: 1 into: data startingAt: 1.
^result > 0
ifTrue: [peek := data at: 1]
ifFalse: [self pastEnd]
@@ -387,7 +387,7 @@ do arbitrary processing on the files.'>
"Store aCharacter on the file"
<category: 'basic'>
- self write: aCharacter numBytes: 1
+ self next: 1 putAll: (String with: aCharacter) startingAt: 1
]
nextPutByte: anInteger [
@@ -675,59 +675,17 @@ do arbitrary processing on the files.'>
bufSize = 0 ifTrue: [ ^self ].
buf := String new: bufSize.
[
- n := self read: buf from: 1 to: bufSize.
+ n := self nextAvailable: bufSize into: buf startingAt: 1.
aStream next: n putAll: buf startingAt: 1.
n = 1024
] whileTrue
]
- next: n putAll: aCollection startingAt: position [
- "Put the characters in the supplied range of aCollection in the file"
-
- <category: 'overriding inherited methods'>
- ^self
- write: aCollection
- from: position
- to: position + n - 1
- ]
-
nextByteArray: anInteger [
"Return the next 'anInteger' bytes from the stream, as a ByteArray."
<category: 'overriding inherited methods'>
- ^self next: anInteger into: (ByteArray new: anInteger)
- ]
-
- next: anInteger [
- "Return the next 'anInteger' characters from the stream, as a String."
-
- <category: 'overriding inherited methods'>
- ^self next: anInteger into: (self species new: anInteger)
- ]
-
- next: anInteger into: result [
- "Return the next 'anInteger' characters from the stream, as a String."
-
- <category: 'overriding inherited methods'>
- | read |
- read := 0.
- [ read = anInteger ] whileFalse: [
- self atEnd ifTrue: [
- ^SystemExceptions.NotEnoughElements signalOn: anInteger -
read].
- read := read + (self read: result from: read + 1 to: anInteger).
- ].
- ^result
- ]
-
- nextAvailable: anInteger [
- "Return up to anInteger objects in the receiver, stopping if
- the end of the stream is reached"
-
- <category: 'accessing-reading'>
- | result n |
- result := self species new: anInteger.
- n := self read: result.
- ^n < anInteger ifTrue: [result copyFrom: 1 to: n] ifFalse: [result]
+ ^self next: anInteger into: (ByteArray new: anInteger) startingAt: 1
]
atEnd [
@@ -815,28 +773,6 @@ do arbitrary processing on the files.'>
^true
]
- nextHunkPutAllOn: aStream [
- "Copy the next buffers worth of stuff from the receiver to aStream."
-
- <category: 'low-level access'>
- | count coll |
- count := self read: (coll := self species new: 1024).
- count = 0 ifTrue: [^self pastEnd].
- aStream next: count putAll: coll startingAt: 1
- ]
-
- nextHunk [
- "Answer the next buffers worth of stuff in the Stream represented
- by the receiver. Do at most one actual input operation."
-
- <category: 'low-level access'>
- | count answer |
- count := self read: (answer := self species new: 1024).
- count < answer size ifTrue: [answer := answer copyFrom: 1 to: count].
- count = 0 ifTrue: [^self pastEnd].
- ^answer
- ]
-
pastEnd [
"The end of the stream has been reached. Signal a Notification."
@@ -845,115 +781,44 @@ do arbitrary processing on the files.'>
super pastEnd
]
- read: byteArray [
- "Ignoring any buffering, try to fill byteArray with the
- contents of the file"
-
- <category: 'low-level access'>
- | count available |
- self ensureReadable.
- available := peek isNil ifTrue: [0] ifFalse: [1].
- peek isNil
- ifFalse:
- [byteArray byteAt: 1 put: peek value.
- peek := nil].
- self isOpen ifFalse: [^available].
- count := self
- fileOp: 3
- with: byteArray
- with: available + 1
- with: byteArray size
- ifFail: [self checkError].
- count := count + available.
- count = 0 ifTrue: [atEnd := true].
- ^count
- ]
-
- read: byteArray numBytes: anInteger [
- "Ignoring any buffering, try to fill anInteger bytes of byteArray
+ nextAvailable: n into: aCollection startingAt: position [
+ "Ignoring any buffering, try to fill the given range of aCollection
with the contents of the file"
<category: 'low-level access'>
| count available |
+ n = 0 ifTrue: [ ^self ].
self ensureReadable.
available := peek isNil ifTrue: [0] ifFalse: [1].
peek isNil
ifFalse:
- [byteArray byteAt: 1 put: peek value.
+ [aCollection byteAt: position put: peek value.
peek := nil].
self isOpen ifFalse: [^available].
count := self
fileOp: 3
- with: byteArray
- with: 1 + available
- with: (anInteger min: byteArray size)
- ifFail: [self checkError].
- count := count + available.
- count = 0 ifTrue: [atEnd := true].
- ^count
- ]
-
- read: byteArray from: position to: end [
- "Ignoring any buffering, try to fill the given range of byteArray
- with the contents of the file"
-
- <category: 'low-level access'>
- | count available |
- self ensureReadable.
- available := peek isNil ifTrue: [0] ifFalse: [1].
- peek isNil
- ifFalse:
- [byteArray byteAt: position put: peek value.
- peek := nil].
- self isOpen ifFalse: [^available].
- count := self
- fileOp: 3
- with: byteArray
+ with: aCollection
with: position + available
- with: (end min: byteArray size)
+ with: (position + n - 1 min: aCollection size)
ifFail: [self checkError].
count := count + available.
count = 0 ifTrue: [atEnd := true].
^count
]
- write: byteArray [
- "Ignoring any buffering, try to write the contents of byteArray in the
- file"
-
- <category: 'low-level access'>
- ^self
- write: byteArray
- from: 1
- to: byteArray size
- ]
-
- write: byteArray numBytes: anInteger [
- "Ignoring any buffering, try to write to the file the first anInteger
- bytes of byteArray"
-
- <category: 'low-level access'>
- ^self
- write: byteArray
- from: 1
- to: anInteger
- ]
-
- write: byteArray from: position to: end [
- "Ignoring any buffering, try to write to the file the given range
- of byteArray, starting at the position-th element and ending
- at the end-th."
+ next: n putAll: aCollection startingAt: position [
+ "Put the characters in the supplied range of aCollection in the file"
<category: 'low-level access'>
| cur last soFar result |
cur := position.
- last := end min: byteArray size.
+ last := position + n - 1 min: aCollection size.
[cur <= last] whileTrue:
[self ensureWriteable.
self isOpen ifFalse: [^cur - position].
result := self
fileOp: 2
- with: byteArray
+ with: aCollection
with: cur
with: last
ifFail: [self checkError].
diff --git a/kernel/FileStream.st b/kernel/FileStream.st
index 1156e16..827cf5e 100644
--- a/kernel/FileStream.st
+++ b/kernel/FileStream.st
@@ -382,10 +382,10 @@ file object, such as /dev/rmt0 on UNIX or MTA0: on VMS).'>
bufferAll: aCollection
startingAt: pos + written]
ifFalse:
- [self
- write: aCollection asString
- from: pos + written
- to: pos + n - 1]
+ [super
+ next: n - written
+ putAll: aCollection asString
+ startingAt: pos + written]
]
upTo: aCharacter [
@@ -477,21 +477,71 @@ file object, such as /dev/rmt0 on UNIX or MTA0: on VMS).'>
^resultStream contents
]
- nextAvailable: anInteger [
- "Private - Read up to anInteger bytes from the stream and store them
- into answer. Return `answer' itself, or raise an exception if we
- could not read the full amount of data."
+ next: anInteger into: answer startingAt: pos [
+ "Read up to anInteger bytes from the stream and store them
+ into answer. Return the number of bytes that were read, raising
+ an exception if we could not read the full amount of data."
+
+ <category: 'buffering'>
+ | read last |
+ writePtr notNil ifTrue: [self flush].
+ read := 0.
+
+ "Exhaust the remaining contents of the buffer if they cannot satisfy
+ the whole request."
+ ptr + anInteger - 1 > endPtr
+ ifTrue:
+ [answer
+ replaceFrom: pos
+ to: endPtr - ptr + pos
+ with: collection
+ startingAt: ptr.
+ read := endPtr - ptr + 1.
+ ptr := endPtr + 1].
+
+ "If we did not read everything, but what's left is less than the size of
+ the buffer, try once more filling it..."
+ anInteger - read < collection size
+ ifTrue:
+ [ptr > endPtr ifTrue: [self fill].
+ last := read + endPtr - ptr + pos min: answer size.
+ answer
+ replaceFrom: read + pos
+ to: last
+ with: collection
+ startingAt: ptr.
+ ptr := ptr + (last - read - pos + 1).
+ read := last - pos + 1].
+
+ "Anything more? We read it from the file. We can come here only if the
+ buffer cannot be filled completely, or if we want to read really a
+ lot of data."
+ [ read = anInteger ] whileFalse: [
+ self atEnd ifTrue: [
+ ^SystemExceptions.NotEnoughElements signalOn: anInteger -
read].
+ read := read + (super
+ nextAvailable: anInteger - read
+ into: answer
+ startingAt: 1)
+ ].
+ ^answer
+ ]
+
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Read up to anInteger bytes from the stream and store them
+ into aCollection. Return the number of bytes read."
<category: 'buffering'>
- | answer last |
+ | last n |
writePtr notNil ifTrue: [self flush].
ptr > endPtr ifTrue: [self fill].
"Fetch data from the buffer, without doing more than one I/O operation."
last := endPtr min: ptr + anInteger - 1.
- answer := collection copyFrom: ptr to: last.
- ptr := ptr + answer size.
- ^answer
+ n := last - ptr + 1.
+ aCollection replaceFrom: pos to: pos + n - 1 with: collection
startingAt: ptr.
+ ptr := ptr + n.
+ ^n
]
nextPutAllOn: aStream [
@@ -568,10 +618,10 @@ file object, such as /dev/rmt0 on UNIX or MTA0: on VMS).'>
ifTrue:
[(self isPipe or: [writePtr - 1 = endPtr])
ifFalse: [super skip: writePtr - 1 - endPtr].
- self
- write: collection
- from: writePtr
- to: writeEnd]]
+ super
+ next: writeEnd - writePtr + 1
+ putAll: collection
+ startingAt: writePtr]]
ifFalse:
[writePtr notNil
ifTrue:
@@ -659,63 +709,16 @@ file object, such as /dev/rmt0 on UNIX or MTA0: on VMS).'>
writeEnd := ptr - 1
]
- next: anInteger into: answer [
- "Private - Read up to anInteger bytes from the stream and store them
- into answer. Return `answer' itself, or raise an exception if we
- could not read the full amount of data."
-
- <category: 'buffering'>
- | read last |
- writePtr notNil ifTrue: [self flush].
- read := 0.
-
- "Exhaust the remaining contents of the buffer if they cannot satisfy
- the whole request."
- ptr + anInteger - 1 > endPtr
- ifTrue:
- [answer
- replaceFrom: 1
- to: endPtr - ptr + 1
- with: collection
- startingAt: ptr.
- read := endPtr - ptr + 1.
- ptr := endPtr + 1].
-
- "If we did not read everything, but what's left is less than the size of
- the buffer, try once more filling it..."
- anInteger - read < collection size
- ifTrue:
- [ptr > endPtr ifTrue: [self fill].
- last := read + endPtr - ptr + 1 min: answer size.
- answer
- replaceFrom: read + 1
- to: last
- with: collection
- startingAt: ptr.
- ptr := ptr + last - read.
- read := last].
-
- "Anything more? We read it from the file. We can come here only if the
- buffer cannot be filled completely, or if we want to read really a
- lot of data."
- [ read = anInteger ] whileFalse: [
- self atEnd ifTrue: [
- ^SystemExceptions.NotEnoughElements signalOn: anInteger -
read].
- read := read + (self read: answer from: read + 1 to: anInteger)
- ].
- ^answer
- ]
-
fill [
"Private - Fill the input buffer"
<category: 'buffering'>
(access bitAnd: 1) = 0 ifTrue: [^self shouldNotImplement].
ptr > endPtr ifTrue: [self flush].
- endPtr := endPtr + (self
- read: collection
- from: endPtr + 1
- to: collection size)
+ endPtr := endPtr + (super
+ nextAvailable: collection size - endPtr
+ into: collection
+ startingAt: endPtr + 1)
]
]
diff --git a/kernel/PosStream.st b/kernel/PosStream.st
index 1f9d78b..1788d69 100644
--- a/kernel/PosStream.st
+++ b/kernel/PosStream.st
@@ -88,6 +88,23 @@ or ReadWriteStream instead of me to create and use streams.'>
aStream next: endPtr putAll: collection startingAt: 1.
]
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Place up to anInteger objects from the receiver into
+ aCollection, starting from position pos and stopping if
+ no more data is available."
+
+ <category: 'accessing-reading'>
+ | n |
+ n := anInteger min: endPtr - ptr + 1.
+ aCollection
+ replaceFrom: pos
+ to: pos + n - 1
+ with: collection
+ startingAt: ptr.
+ ptr := ptr + n.
+ ^n
+ ]
+
peek [
"Returns the next element of the stream without moving the pointer.
Returns nil when at end of stream."
diff --git a/kernel/Stream.st b/kernel/Stream.st
index 081cd2b..802aa35 100644
--- a/kernel/Stream.st
+++ b/kernel/Stream.st
@@ -59,16 +59,31 @@ provide for writing collections sequentially.'>
"Return the next anInteger objects in the receiver"
<category: 'accessing-reading'>
- | data i item |
- data := self species new: anInteger.
-
- [i := 0.
- [i < anInteger] whileTrue:
- [item := self next.
- data at: (i := i + 1) put: item]]
- on: SystemExceptions.EndOfStream
- do: [:ex | SystemExceptions.NotEnoughElements signalOn: anInteger -
i].
- ^data
+ | answer |
+ self
+ next: anInteger
+ into: (answer := self species new: anInteger)
+ startingAt: 1.
+ ^answer
+ ]
+
+ next: anInteger into: answer startingAt: pos [
+ "Read up to anInteger bytes from the stream and store them
+ into answer. Return the number of bytes that were read, raising
+ an exception if we could not read the full amount of data."
+
+ <category: 'buffering'>
+ | read |
+ read := 0.
+ [ read = anInteger ] whileFalse: [
+ self atEnd ifTrue: [
+ ^SystemExceptions.NotEnoughElements signalOn: anInteger -
read].
+ read := read + (self
+ nextAvailable: anInteger - read
+ into: answer
+ startingAt: 1)
+ ].
+ ^answer
]
nextAvailable: anInteger [
@@ -79,14 +94,32 @@ provide for writing collections sequentially.'>
operation."
<category: 'accessing-reading'>
- | answer |
- answer := self species new: anInteger.
- 1 to: anInteger do:
- [:i | self atEnd ifTrue: [^answer copyFrom: 1 to: i - 1].
- answer at: i put: self next].
+ | n answer |
+ n := self
+ nextAvailable: anInteger
+ into: (answer := self species new: anInteger)
+ startingAt: 1.
+ n < anInteger ifTrue: [ answer := answer copyFrom: 1 to: n ].
^answer
]
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Place the next anInteger objects from the receiver into aCollection,
+ starting at position pos. Return the number of items stored.
+ Besides stopping if the end of the stream is reached, this may
+ return less than this number of bytes for various reasons.
+ For example, on files and sockets this operation could be
+ non-blocking, or could do at most one I/O operation."
+
+ <category: 'accessing-reading'>
+ | i |
+ i := -1.
+ [(i := i + 1) = anInteger] whileFalse: [
+ self atEnd ifTrue: [^i].
+ aCollection at: i + pos put: self next].
+ ^anInteger
+ ]
+
nextMatchFor: anObject [
"Answer whether the next object is equal to anObject. Even if it does
not, anObject is lost"
@@ -527,14 +560,7 @@ provide for writing collections sequentially.'>
Smalltalk (including zlib streams)."
<category: 'positioning'>
- | s |
- s := self species new: 1024.
- 1 to: 1024
- do:
- [:i |
- self atEnd ifTrue: [^s copyFrom: 1 to: i - 1].
- s at: i put: self next].
- ^s
+ ^self nextAvailable: 1024
]
prefixTableFor: aCollection [
diff --git a/packages/iconv/ChangeLog b/packages/iconv/ChangeLog
index 9bc08be..5e59995 100644
--- a/packages/iconv/ChangeLog
+++ b/packages/iconv/ChangeLog
@@ -1,5 +1,9 @@
2008-08-05 Paolo Bonzini <address@hidden>
+ * Sets.st: Use #nextInputAvailable:into:startingAt: instead.
+
+2008-08-05 Paolo Bonzini <address@hidden>
+
* Sets.st: Add #nextInputAvailable: and use it to refill the buffer.
2008-01-17 Paolo Bonzini <address@hidden>
diff --git a/packages/iconv/Sets.st b/packages/iconv/Sets.st
index 35c1cfe..6045b27 100644
--- a/packages/iconv/Sets.st
+++ b/packages/iconv/Sets.st
@@ -379,13 +379,13 @@ encodings.'>
^origin next
]
- nextInputAvailable: n [
- "Return up to N characters from the origin. This method is for
+ nextInputAvailable: n into: aCollection startingAt: pos [
+ "Place up to N characters from the origin in aCollection. This method
is for
private use by encoders, calling it outside may corrupt the
internal state of the encoder."
<category: 'stream operations'>
- ^origin nextAvailable: n
+ ^origin nextAvailable: n into: aCollection startingAt: pos
]
species [
@@ -966,6 +966,22 @@ Iconv is skipped altogether and only Smalltalk converters
are used.'>
^answer
]
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Answer the next buffer's worth of data from the receiver."
+
+ <category: 'stream operation'>
+ | n |
+ (self atEndOfBuffer and: [self convertMore])
+ ifTrue: [^self pastEnd].
+ n := anInteger min: recodedEnd - recodedPos + 1.
+ aCollection
+ replaceFrom: pos to: pos + n - 1
+ with: recodedBuffer
+ startingAt: recodedPos.
+ recodedPos := recodedPos + n.
+ ^n
+ ]
+
nextHunkPutAllOn: aStream [
"Copy the next buffer's worth of data from the receiver onto
aStream."
@@ -985,12 +1001,7 @@ Iconv is skipped altogether and only Smalltalk converters
are used.'>
"Answer the next buffer's worth of data from the receiver."
<category: 'stream operation'>
- | answer |
- (self atEndOfBuffer and: [self convertMore])
- ifTrue: [^self pastEnd].
- answer := recodedBuffer copyFrom: recodedPos to: recodedEnd.
- recodedPos := recodedEnd + 1.
- ^answer
+ ^self nextAvailable: recodedEnd - recodedPos + 1
]
release [
@@ -1043,13 +1054,10 @@ Iconv is skipped altogether and only Smalltalk
converters are used.'>
readEnd := readEnd - readPos + 1.
readPos := 1].
- data := self nextInputAvailable: self bufferSize - readEnd.
- readBuffer
- replaceFrom: readEnd + 1 to: readEnd + data size
- with: data
- startingAt: 1.
-
- readEnd := readEnd + data size.
+ readEnd := readEnd + (self
+ nextInputAvailable: self bufferSize - readEnd
+ into: readBuffer
+ startingAt: readEnd + 1).
]
initializeFrom: fromEncoding to: toEncoding origin: aStringOrStream [
diff --git a/packages/sockets/Buffers.st b/packages/sockets/Buffers.st
index b822b96..fc2e498 100644
--- a/packages/sockets/Buffers.st
+++ b/packages/sockets/Buffers.st
@@ -124,7 +124,7 @@ evaluates an user defined block to try to get some more
data.'>
"Copy a buffer's worth of data from the receiver to aStream, doing
at most one call to the fill block."
- <category: 'buffer handling'>
+ <category: 'accessing-reading'>
self atEnd ifTrue: [^super pastEnd].
aStream next: endPtr - ptr + 1 putAll: self collection startingAt: ptr.
endPtr := ptr - 1. "Empty the buffer"
@@ -134,20 +134,27 @@ evaluates an user defined block to try to get some more
data.'>
"Answer a buffer's worth of data, doing at most one call
to the fill block."
- <category: 'buffer handling'>
- | contents |
- self atEnd ifTrue: [^super pastEnd].
- contents := self collection copyFrom: ptr to: endPtr.
- endPtr := ptr - 1. "Empty the buffer"
- ^contents
+ <category: 'accessing-reading'>
+ ^self nextAvailable: endPtr - ptr + 1
]
availableBytes [
"Answer how many bytes are available in the buffer."
+ <category: 'buffer handling'>
+ self isEmpty ifTrue: [ self fill ].
^endPtr + 1 - ptr
]
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Place the next anInteger objects from the receiver into aCollection,
+ starting at position pos. Return the number of items stored."
+
+ <category: 'accessing-reading'>
+ self isEmpty ifTrue: [ self fill ].
+ ^super nextAvailable: anInteger into: aCollection startingAt: pos
+ ]
+
fill [
"Fill the buffer with more data if it is empty, and answer
true if the fill block was able to read more data."
diff --git a/packages/sockets/ChangeLog b/packages/sockets/ChangeLog
index f7450dc..f10dbb5 100644
--- a/packages/sockets/ChangeLog
+++ b/packages/sockets/ChangeLog
@@ -1,5 +1,12 @@
2008-08-05 Paolo Bonzini <address@hidden>
+ * Buffers.st: Add #nextAvailable:into:startingAt:.
+ * Sockets.st: Change #nextAvailable: into
+ #nextAvailable:into:startingAt:. Change the fill
+ blocks to not use #read:from:to: and #write:from:to:.
+
+2008-08-05 Paolo Bonzini <address@hidden>
+
* Buffers.st: Add #nextHunk and #nextHunkPutAllOn:.
* Sockets.st: Remove the lookahead instance variable. Delegate
more stuff to the readBuffer, including #nextHunk. Implement
diff --git a/packages/sockets/Sockets.st b/packages/sockets/Sockets.st
index b2c11f2..11de715 100644
--- a/packages/sockets/Sockets.st
+++ b/packages/sockets/Sockets.st
@@ -1164,7 +1164,6 @@ This class adds a read buffer to the basic model of
AbstractSocket.'>
<category: 'stream protocol'>
self canRead ifFalse: [ ^0 ].
- self readBuffer isEmpty ifTrue: [ self readBuffer fill ].
^self readBuffer availableBytes
]
@@ -1208,30 +1207,24 @@ This class adds a read buffer to the basic model of
AbstractSocket.'>
^self readBuffer next
]
- nextAvailable: anInteger [
- "Return up to anInteger objects in the receiver, stopping if
- the end of the stream is reached"
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Place up to anInteger objects from the receiver into
+ aCollection, starting from position pos and stopping if
+ no more data is available."
<category: 'accessing-reading'>
- | buffer available stream |
+ | available read |
readBuffer isNil ifTrue: [ ^self pastEnd ].
-
self ensureReadable.
- available := self availableBytes.
- available >= anInteger ifTrue: [ ^self next: anInteger ].
-
- "Try filling the first buffer."
- buffer := self next: available.
- available := self availableBytes min: anInteger - available.
- available = 0 ifTrue: [ ^buffer ].
- "Streams have extra costs because of copying, use them only if
- needed."
- stream := WriteStream with: buffer.
- [ (available := self availableBytes min: anInteger - stream size) > 0 ]
- whileTrue: [ stream nextPutAll: (self readBuffer next: available) ].
+ read := 0.
+ [ (available := self availableBytes) > 0 ] whileTrue: [
+ read := read + (self readBuffer
+ nextAvailable: available
+ into: aCollection
+ startingAt: pos + read) ].
- ^stream contents
+ ^read
]
nextHunkPutAllOn: aStream [
@@ -1256,16 +1249,6 @@ This class adds a read buffer to the basic model of
AbstractSocket.'>
^self readBuffer nextHunk
]
- next: count [
- "Read `count' bytes from the socket. This might yield control to other
- Smalltalk Processes."
-
- <category: 'stream protocol'>
- | result |
- readBuffer isNil ifTrue: [ ^self pastEnd ].
- ^self readBuffer next: count
- ]
-
peek [
"Read a byte from the socket, without advancing the buffer; answer
nil if no more data is available. This might yield control to other
@@ -1329,7 +1312,7 @@ This class adds a read buffer to the basic model of
AbstractSocket.'>
[:data :size |
self implementation ensureReadable.
self implementation isOpen
- ifTrue: [self implementation read: data numBytes: size]
+ ifTrue: [self implementation nextAvailable: size into: data
startingAt: 1]
ifFalse:
[self deleteBuffers.
0]]
@@ -1470,7 +1453,7 @@ This class adds read and write buffers to the basic model
of AbstractSocket.'>
| alive |
self implementation ensureWriteable.
alive := self implementation isOpen
- and: [(self implementation write: data numBytes:
size) > -1].
+ and: [(self implementation next: size putAll: data
startingAt: 1) > -1].
alive ifFalse: [self deleteBuffers]]
]
diff --git a/packages/sport/ChangeLog b/packages/sport/ChangeLog
index 3599bbb..ba15e8d 100644
--- a/packages/sport/ChangeLog
+++ b/packages/sport/ChangeLog
@@ -1,3 +1,8 @@
+2008-08-05 Paolo Bonzini <address@hidden>
+
+ * sport.st: At last use native Socket methods for #read: and
+ #readInto:startingAt:for:.
+
2008-08-04 Paolo Bonzini <address@hidden>
* sport.st: Use StreamSocket>>#nextAvailable:.
diff --git a/packages/sport/sport.st b/packages/sport/sport.st
index 6ed8633..957f5f3 100644
--- a/packages/sport/sport.st
+++ b/packages/sport/sport.st
@@ -1205,10 +1205,11 @@ Object subclass: SpSocket [
If the targetNumberOfBytes are not available, I return what I can
get."
<category: 'services-io'>
- "FIXME: this needs #nextAvailable:into: to avoid a copy in #asByteArray"
- ^(self underlyingSocket
- ensureReadable;
- nextAvailable: targetNumberOfBytes) asByteArray
+ | answer n |
+ answer := ByteArray new: targetNumberOfBytes.
+ n := self underlyingSocket nextAvailable: targetNumberOfBytes into:
answer startingAt: 1.
+ n < targetNumberOfBytes ifTrue: [ answer := answer copyFrom: 1 to: n ].
+ ^answer
]
readInto: aByteArray startingAt: startIndex for: aNumberOfBytes [
@@ -1217,13 +1218,7 @@ Object subclass: SpSocket [
number of bytes to be read. We get what its there no matter how
much their is!!"
<category: 'services-io'>
- | buffer |
- buffer := self underlyingSocket
- ensureReadable;
- nextAvailable: aNumberOfBytes.
- aByteArray replaceFrom: startIndex to: startIndex + buffer size - 1
- with: buffer startingAt: 1.
- ^buffer size
+ ^self underlyingSocket nextAvailable: aNumberOfBytes into: aByteArray
startingAt: startIndex
]
readyForRead [
diff --git a/packages/zlib/ChangeLog b/packages/zlib/ChangeLog
index a9c3914..9e8bfb5 100644
--- a/packages/zlib/ChangeLog
+++ b/packages/zlib/ChangeLog
@@ -1,5 +1,9 @@
2008-08-05 Paolo Bonzini <address@hidden>
+ * ZLibReadStream.st: Add #nextAvailable:into:startingAt:.
+
+2008-08-05 Paolo Bonzini <address@hidden>
+
* ZLibReadStream.st: Add #nextHunkPutAllOn:.
* zlibtests.st: Test it.
diff --git a/packages/zlib/ZLibReadStream.st b/packages/zlib/ZLibReadStream.st
index 17fbea5..8684ab5 100644
--- a/packages/zlib/ZLibReadStream.st
+++ b/packages/zlib/ZLibReadStream.st
@@ -89,11 +89,24 @@ used for communication with zlib.'>
operation."
<category: 'streaming'>
- | result |
- self atEnd ifTrue: [^self pastEnd].
- result := outBytes copyFrom: ptr + 1 to: endPtr.
- ptr := endPtr.
- ^result
+ ^self nextAvailable: endPtr - ptr
+ ]
+
+ nextAvailable: anInteger into: aCollection startingAt: pos [
+ "Place up to anInteger objects from the receiver into
+ aCollection, starting from position pos and stopping if
+ no more data is available."
+
+ <category: 'accessing-reading'>
+ | n |
+ n := anInteger min: endPtr - ptr.
+ aCollection
+ replaceFrom: pos
+ to: pos + n - 1
+ with: outBytes
+ startingAt: ptr + 1.
+ ptr := ptr + n.
+ ^n
]
peek [
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-smalltalk] [PATCH] Block-level stream input protocol,
Paolo Bonzini <=