On Tue, May 17, 2011 at 7:16 PM, Igor Stasenko <siguctua@gmail.com> wrote:
On 17 May 2011 22:58, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
On Tue, May 17, 2011 at 10:31 PM, Sven Van Caekenberghe <sven@beta9.be> wrote:
On 17 May 2011, at 21:57, Mariano Martinez Peck wrote:
Sven, I want to make it work :)
so....the missing methods I told you that I need are:
#nextStringPut: #nextNumber:put: #nextInt32Put: #nextWordPut:
I guess these are pretty easy. But I think they clutter the interface of ZnBufferedWriteStream, so maybe you should make a subclass.
Yeah, don't worry. I can even duplicate the class hehehe
#contents
Implement #contents I guess it is something like:
ZnBufferedWriteStream >> contents ^ stream contents
Why to you need #contents ?
becasue I am an idiot. No, I don't need it. You are correct. Thanks for asking.
I would say that it goes a bit against the concept of a stream as a sink of data. I haven't looked, but I would guess that saying #contents to a
FileStream
is not efficient.
Those missing methods I need are implemented PositionableStream. I took the implementation from there and put it in ZnBufferedWriteStream. I just added to them a first line " self flushBufferIfFull."
That is probably OK, except when your string becomes larger than the buffer. Have a look at #nextPutAll:
I am not sure if I understood. The following are correct for sure then: #nextNumber:put: #nextInt32Put: #nextWordPut:
And #nextStringPut: is like this:
nextStringPut: s "Append the string, s, to the receiver. Only used by DataStream. Max size of 64*256*256*256."
| length | self flushBufferIfFull. (length := s size) < 192 ifTrue: [self nextPut: length] ifFalse: [self nextPut: (length digitAt: 4)+192. self nextPut: (length digitAt: 3). self nextPut: (length digitAt: 2). self nextPut: (length digitAt: 1)]. self nextPutAll: s asByteArray. ^s
Sorry, but i can't resist commenting on that. Why, if you demand from stream to implement #nextInt32Put: a the same time, you writing code like this
self nextPut: (length digitAt: 4)+192. self nextPut: (length digitAt: 3). self nextPut: (length digitAt: 2). self nextPut: (length digitAt: 1)
? Then just extend your serializer with a notion of 'length' field, which you can use for anything where you need to encode length/size value, but not just for Strings. So, then the above method could be as short as:
nextStringPut: s self putLength: s size. self nexPutAll: s asByteArray.
and here you have a potential caveat because your string could be WideString .. muhahaha.
So, i suggest you to reconsider the way how you serializing strings. Instead what you could do is to extend ByteString and WideString (and perhaps similarily do for ByteSymbol and WideSymbol), the methods which is responsible to turning a receiver in a sequence of bytes, and then simply put it into output stream, whatever it might be.
Then you don't need #nextStringPut: because its a) not polymorphic, because apparently serializing ByteString should be different from serializing WideString b) instead you implementing this in Byte/WideString>>serializeToFuelStream: aStream and you done.
Yes, I am not sure if #nextStringPut: is not polymorphic, but I think that with #serializeToFuelStream: we can avoid converting the WideString to ByteArray just to write the ByteArray to the stream, and instead just write the WideString to the stream. Right?
which will finally send #nextPutAll: that does correct check.
The way I am creating it is like this:
stream := ZnBufferedWriteStream on: ((FileDirectory default forceNewFileNamed: 'mariano') binary).
So...is this correct Sven? My tests are green :)
That seems OK
Ok.
Still need to try benchmarks.
You might also consider playing with making the buffer larger.
yeah, I was trying that. Just by curious, why you put a 2^X number there?
Ahh and for reading we don't need something special because it is already buffered? (I have been told that)
Thanks a lot Sven,
-- Mariano http://marianopeck.wordpress.com
-- Best regards, Igor Stasenko AKA sig.