August 08, 2005 Re: iff module (EndianStream) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | Ben Hinkle wrote: > OK. Now that I think about it repeatedly wrapping a stream with another stream and going back and forth might wind up with some odd state in the original stream wrt unget buffers and end-of-line flags. What would you suggest then? Especially what would be the nicest way of using EndianStream in a library function that takes a Stream argument and where no assumptions can be made about the passed Stream object: 1) Always create an EndianStream wrapper. 2) Check whether the given stream is EndianStream. If yes, use that stream. If not, create an EndianStream wrapper. 3) Take an EndianStream argument instead of a Stream thus forcing the client to create an EndianStream wrapper. 4) Ignore endianness completely. The client will create an EndianStream wrapper if needed. > I should add some documentation that if you wrap and unwrap a stream that is already in use the binary operations are the only truly safe operations. Agreed. -- Niko Korhonen SW Developer |
August 08, 2005 Re: iff module (EndianStream) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Niko Korhonen | "Niko Korhonen" <niktheblak@hotmail.com> wrote in message news:dd86q0$30sl$1@digitaldaemon.com... > Ben Hinkle wrote: >> OK. Now that I think about it repeatedly wrapping a stream with another stream and going back and forth might wind up with some odd state in the original stream wrt unget buffers and end-of-line flags. > > What would you suggest then? Especially what would be the nicest way of using EndianStream in a library function that takes a Stream argument and where no assumptions can be made about the passed Stream object: > > 1) Always create an EndianStream wrapper. > > 2) Check whether the given stream is EndianStream. If yes, use that stream. If not, create an EndianStream wrapper. > > 3) Take an EndianStream argument instead of a Stream thus forcing the client to create an EndianStream wrapper. > > 4) Ignore endianness completely. The client will create an EndianStream wrapper if needed. Since in your initial post you mentioned your code only does binary i/o then you can safely wrap. I'd do 2a) which is 2) but throwing if the EndianStream is the wrong endianness. That way the user can make their own EndianStream if they don't want the performance hit of making lots of little wrappers and yet if they make the wrong EndianStream they'll find out about it quickly. If you want you can write a little helper method "getCompatibleStream" or something: class Foo { // returns a stream possibly wrapping the source stream s that // is compatible with class Foo. Returns null if s can't be made compatible. // Using the same compatible stream instance to write multiple Foo // instances is more efficient than getting a compatible stream for // each Foo instance. Stream getCompatibleStream(Stream s) { assert( s ); EndianStream es = cast(EndianStream)s; if (!es) es = new EndianStream(s,Endian.LittleEndian); is (es.endian != Endian.LittleEndian) es = null; return es; } void write(Stream s) { s = getCompatibleStream(s); assert( s ); ... carry on, nothing to see here ... } >> I should add some documentation that if you wrap and unwrap a stream that >> is >> already in use the binary operations are the only truly safe operations. > > Agreed. > > -- > Niko Korhonen > SW Developer |
August 09, 2005 Re: iff module (EndianStream) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | How about using a stream and a wrapper simultaneously, something like this:
void write(Stream s)
{
EndianStream es = new EndianStream(s, Endian.LittleEndian);
es.write(/* uint argument */);
s.writeString(/* string argument*/ );
es.write(/* long argument */);
s.write(/* ubyte argument */);
}
Do you see any problems with that?
--
Niko Korhonen
SW Developer
|
August 09, 2005 Re: iff module (EndianStream) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Niko Korhonen | "Niko Korhonen" <niktheblak@hotmail.com> wrote in message news:dd9ldm$1hr8$1@digitaldaemon.com... > How about using a stream and a wrapper simultaneously, something like this: > > void write(Stream s) > { > EndianStream es = new EndianStream(s, Endian.LittleEndian); > es.write(/* uint argument */); > s.writeString(/* string argument*/ ); > es.write(/* long argument */); > s.write(/* ubyte argument */); > } > > Do you see any problems with that? > > -- > Niko Korhonen > SW Developer Stream.writeString is fine since it writes the length as binary followed by the string contents. The problem methods are the ones that call getc/getcw like readLine and readf. Now that I think about it, though, mixing get/unget with binary reading isn't a good idea even with one stream let alone wrapper (I should have thought of that earlier - sorry!). The unget buffer is not checked by the binary read methods so anything you unget sits unnoticed until you getc again and it magically pops back up. I believe this matches how C streams work but I haven't ever actually tried mixing getc/ungetc with fread. |
Copyright © 1999-2021 by the D Language Foundation