Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
May 28, 2008 Endianness and Tango | ||||
---|---|---|---|---|
| ||||
Attachments: | Hello, this is a noob question, but I'm learning Tango/D, and I'm a bit lost with all the possibilities I'm offered to read/write a file. The format of the file is a bit fuzzy, since it has, say, a BigEndian part followed by a LittleEndian part, so I must switch protocols in the middle of the reading and writing. What should be the best approach ? For now, I do : read( char[] filename ) { auto file = new FileConduit( filename ) ; version( LittleEndian ) auto inp = new EndianInput!( short )( file ); version( BigEndian ) auto inp = file ; read some stuf... ; version( LittleEndian ) auto inp2 = file ; version( BigEndian ) auto inp2 = new EndianInput!( float )( file ); read some stuff... ; } and same for writing (with FileConduit.WriteCreate, and EndianOutput!( short )) the reading seems to work fine, but the writing does not work (looks like when I do the second outpf = file ; it starts writing again from the beginning of the file rather than where I left it before. Plus the code looks ugly, to me, and I don't like having to specify the EndianInput!(short) thing, I'd prefer to tell at the point where I read something, what is the value I will be reading. Someone has a clue ? I attached my FImage.d library file } |
May 28, 2008 Re: Endianness and Tango | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | "Mael" wrote
> Hello,
>
> this is a noob question, but I'm learning Tango/D, and I'm a bit lost with
> all the possibilities I'm offered to read/write a file. The format of the
> file is a bit fuzzy, since it has, say, a BigEndian part followed by a
> LittleEndian part, so I must switch protocols in the middle of the reading
> and writing. What should be the
> best approach ?
>
> For now, I do :
>
> read( char[] filename )
> {
> auto file = new FileConduit( filename ) ;
> version( LittleEndian ) auto inp = new EndianInput!( short )( file );
> version( BigEndian ) auto inp = file ;
> read some stuf... ;
>
> version( LittleEndian ) auto inp2 = file ;
> version( BigEndian ) auto inp2 = new EndianInput!( float )( file );
> read some stuff... ;
> }
>
> and same for writing (with FileConduit.WriteCreate, and EndianOutput!( short ))
>
> the reading seems to work fine, but the writing does not work (looks like when I do the second outpf = file ; it starts writing again from the beginning of the file rather than where I left it before. Plus the code looks ugly, to me, and I don't like having to specify the EndianInput!(short) thing, I'd prefer to tell at the point where I read something, what is the value I will be reading. Someone has a clue ?
You should probably use the Protocol classes as they allow reading/writing different types from/to a stream without re-opening.
i.e.:
// the second argument says don't expect a length argument for arrays.
version( LittleEndian ) auto proto = new EndianProtocol( file, false ) ;
version( BigEndian ) auto proto = new NativeProtocol( file, false);
auto inp = new Reader(proto);
short[4] res;
auto _res = res[];
inp.get( _res );
if( res[0] != 0x4952 )
throw new Exception( "Invalid RIM file" );
int length_comment = res[1] ;
this.width = res[2] ;
this.height = res[3] ;
assert( width >= 0 && height >= 0 );
int length_header = base_length_header + length_comment ;
file.seek( length_header );
inp.buffer.clear(); // flush all content out of the buffer
this.data = new float[width*height] ;
inp.read( data );
Note: didn't compile this or test it :)
-Steve
|
May 29, 2008 Re: Endianness and Tango | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Okay thanks, can you just explain your _res trick ? Why does calling the get method with res doesn't work and says "cast(short[])res is not an lvalue" ? |
May 29, 2008 Re: Endianness and Tango | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mael | "Mael" wrote
> Okay thanks,
>
> can you just explain your _res trick ? Why does calling the get method with res doesn't work and says "cast(short[])res is not an lvalue" ?
>
_res is an array slice, res is a static array. Under the hood of the compiler, these are viewed as totally separate types. In fact, two static arrays of different size are viewed as different types. However, one can implicitly cast a static array to an array slice, which is what the function is expecting. However, whenever you cast, you are creating a temporary variable, which cannot be an lvalue (a value that can be assigned to). A ref parameter must take an lvalue because it must be able to write to it. Because Reader uses ref as a parameter for its array, you must pass it a true lvalue, which is what _res is.
It would be impossible for Reader to accept ref parameters to all sizes of static arrays, since they are all considered different types, and I don't even know that you can ref a static array, so you must do this trick. Very kludgy, but it works :)
Hopefully at some point in the future, D will be able to remedy this.
-Steve
|
May 30, 2008 Re: Endianness and Tango | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Okay, sure, static arrays aren't represented with a length + ptr, I don't know why I assumed this. |
Copyright © 1999-2021 by the D Language Foundation