digitalmars.D.learn - Passing a ubyte[] to a function taking a 'ref ubyte[16]'
- Johannes Pfau (40/40) Jun 23 2012 I'm working on the new design for std.hash and I hit an interesting
- simendsjo (14/22) Jun 23 2012 I don't have a clue, but the following seems to work as well :)
- simendsjo (2/24) Jun 23 2012 Oops.. Just saw it should have been the other way around. Never mind me
- Jonathan M Davis (7/53) Jun 23 2012 I confess that I'm baffled as to why you'd even be using interfaces for ...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (12/23) Jun 23 2012 I had the following function template in a message that did not appear
- Johannes Pfau (4/38) Jun 24 2012 Yes that's better. Could this be added to phobos, probably
- Johannes Pfau (9/32) Jun 24 2012 As discussed in the main newsgroup I use both. Interfaces and classes
- Regan Heath (9/33) Jun 25 2012 Correction; I supplied some code which became the Tango digest modules, ...
I'm working on the new design for std.hash and I hit an interesting problem: The OOP interface has to take buffers as slices with unknown length, as the length differs between hashes and I have to put a common function declaration in a interface. So I have this: ------------ interface Digest { ubyte[] finish(ubyte[] buf); } ------------ Now the template API can and should use the correct type, so there finish is defined like this: ------------ struct MD5 { void finish(ref ubyte[16] data); } ------------ And the interface implementation for MD5 has to call the MD5 structs finish function: ------------ class MD5Digest : Digest { private MD5 _digest; ubyte[] finish(ubyte[] buf) { enforce(buf.length >= 16); _digest.finish(buf); //How to do this? } } ------------ So how to pass a ubyte[] to a function expecting a ref ubyte[16] without allocating/using any extra memory (Not even stack)? This seems to work, but it's very ugly: ------------ _digest.finish(*cast(ubyte[16]*)buf.ptr); ------------ I thought this might create a temporary, but it passes all unittests, so it seems to work?
Jun 23 2012
On Sat, 23 Jun 2012 20:23:26 +0200, Johannes Pfau <nospam example.com> wrote:So how to pass a ubyte[] to a function expecting a ref ubyte[16] without allocating/using any extra memory (Not even stack)? This seems to work, but it's very ugly: ------------ _digest.finish(*cast(ubyte[16]*)buf.ptr); ------------ I thought this might create a temporary, but it passes all unittests, so it seems to work?I don't have a clue, but the following seems to work as well :) void sarr(ref ubyte[1] a) { darr(a.ptr[0..a.length]); } void darr(ubyte[] a) { a[0] = 2; } void main() { ubyte[1] a = [1]; sarr(a); assert(a[0] == 2); }
Jun 23 2012
On Sat, 23 Jun 2012 20:33:09 +0200, simendsjo <simendsjo gmail.com> wrote:On Sat, 23 Jun 2012 20:23:26 +0200, Johannes Pfau <nospam example.com> wrote:Oops.. Just saw it should have been the other way around. Never mind meSo how to pass a ubyte[] to a function expecting a ref ubyte[16] without allocating/using any extra memory (Not even stack)? This seems to work, but it's very ugly: ------------ _digest.finish(*cast(ubyte[16]*)buf.ptr); ------------ I thought this might create a temporary, but it passes all unittests, so it seems to work?I don't have a clue, but the following seems to work as well :) void sarr(ref ubyte[1] a) { darr(a.ptr[0..a.length]); } void darr(ubyte[] a) { a[0] = 2; } void main() { ubyte[1] a = [1]; sarr(a); assert(a[0] == 2); }
Jun 23 2012
On Saturday, June 23, 2012 20:23:26 Johannes Pfau wrote:I'm working on the new design for std.hash and I hit an interesting problem: The OOP interface has to take buffers as slices with unknown length, as the length differs between hashes and I have to put a common function declaration in a interface. So I have this: ------------ interface Digest { ubyte[] finish(ubyte[] buf); } ------------I confess that I'm baffled as to why you'd even be using interfaces for this, given that Phobos always uses structs and templates for this sort of thing.Now the template API can and should use the correct type, so there finish is defined like this: ------------ struct MD5 { void finish(ref ubyte[16] data); } ------------ And the interface implementation for MD5 has to call the MD5 structs finish function: ------------ class MD5Digest : Digest { private MD5 _digest; ubyte[] finish(ubyte[] buf) { enforce(buf.length >= 16); _digest.finish(buf); //How to do this? } } ------------ So how to pass a ubyte[] to a function expecting a ref ubyte[16] without allocating/using any extra memory (Not even stack)? This seems to work, but it's very ugly: ------------ _digest.finish(*cast(ubyte[16]*)buf.ptr); ------------ I thought this might create a temporary, but it passes all unittests, so it seems to work?I believe that that will work, but it's definitely ugly. However, if you do that, you _need_ to put an assertion about the length of buf in there, otherwise, you could be using memory from past the end of buf. - Jonathan M Davis
Jun 23 2012
On 06/23/2012 04:51 PM, Jonathan M Davis wrote:you doThis seems to work, but it's very ugly: ------------ _digest.finish(*cast(ubyte[16]*)buf.ptr); ------------ I thought this might create a temporary, but it passes all unittests, so it seems to work?I believe that that will work, but it's definitely ugly. However, ifthat, you _need_ to put an assertion about the length of buf in there, otherwise, you could be using memory from past the end of buf. - Jonathan M DavisI had the following function template in a message that did not appear on the newsgroup: ref T[N] asArray(size_t N, T)(ref T[] source) { enforce(source.length >= N); return *cast(T[N]*)source.ptr; } // ... foo(asArray!16(b)); Ali
Jun 23 2012
Am Sat, 23 Jun 2012 23:39:00 -0700 schrieb Ali =C3=87ehreli <acehreli yahoo.com>:On 06/23/2012 04:51 PM, Jonathan M Davis wrote: =20 >> This seems to work, but it's very ugly: >> ------------ >> _digest.finish(*cast(ubyte[16]*)buf.ptr); >> ------------ >> >> I thought this might create a temporary, but it passes all >> unittests, so it seems to work? > > I believe that that will work, but it's definitely ugly. However, > if=20 you do > that, you _need_ to put an assertion about the length of buf in > there, otherwise, you could be using memory from past the end of > buf. > > - Jonathan M Davis =20 I had the following function template in a message that did not appear on the newsgroup: =20 ref T[N] asArray(size_t N, T)(ref T[] source) { enforce(source.length >=3D N); return *cast(T[N]*)source.ptr; } =20 // ... =20 foo(asArray!16(b)); =20 Ali =20Yes that's better. Could this be added to phobos, probably std.typecons?
Jun 24 2012
Am Sat, 23 Jun 2012 16:51:14 -0700 schrieb Jonathan M Davis <jmdavisProg gmx.com>:On Saturday, June 23, 2012 20:23:26 Johannes Pfau wrote:As discussed in the main newsgroup I use both. Interfaces and classes are useful if you want to change the crypto backend (D/OpenSSL/Windows Crypto API) at runtime and without breaking the ABI. Regan Heath who designed the Tango digest module, also said that digets are often used with the factory pattern, which doesn't work with structs / templates.I'm working on the new design for std.hash and I hit an interesting problem: The OOP interface has to take buffers as slices with unknown length, as the length differs between hashes and I have to put a common function declaration in a interface. So I have this: ------------ interface Digest { ubyte[] finish(ubyte[] buf); } ------------I confess that I'm baffled as to why you'd even be using interfaces for this, given that Phobos always uses structs and templates for this sort of thing.I believe that that will work, but it's definitely ugly. However, if you do that, you _need_ to put an assertion about the length of buf in there, otherwise, you could be using memory from past the end of buf.Sure, it's already in the MD5Digest example posted above: enforce(buf.length >= 16);
Jun 24 2012
On Sun, 24 Jun 2012 08:27:00 +0100, Johannes Pfau <nospam example.com> wrote:Am Sat, 23 Jun 2012 16:51:14 -0700 schrieb Jonathan M Davis <jmdavisProg gmx.com>:Correction; I supplied some code which became the Tango digest modules, someone else defined the final API and made all my code 'fit'. I think factory pattern is a commonly desired usage pattern for hashing, crypto, compression, etc. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/On Saturday, June 23, 2012 20:23:26 Johannes Pfau wrote:As discussed in the main newsgroup I use both. Interfaces and classes are useful if you want to change the crypto backend (D/OpenSSL/Windows Crypto API) at runtime and without breaking the ABI. Regan Heath who designed the Tango digest module, also said that digets are often used with the factory pattern, which doesn't work with structs / templates.I'm working on the new design for std.hash and I hit an interesting problem: The OOP interface has to take buffers as slices with unknown length, as the length differs between hashes and I have to put a common function declaration in a interface. So I have this: ------------ interface Digest { ubyte[] finish(ubyte[] buf); } ------------I confess that I'm baffled as to why you'd even be using interfaces for this, given that Phobos always uses structs and templates for this sort of thing.
Jun 25 2012