Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
January 25, 2007 array and pointers | ||||
---|---|---|---|---|
| ||||
hi, I have just started to play with D, and I have some little problem. In C I did something like: #define uchar unsigned char void aes_ecb_decrypt(aes_context *ctx, uchar *input, uchar *output, uint len ) { int n; uchar *pin, *pout; // test to validate parameters.. n = len; pin = input; pout = output; while( n > 0 ) { decrypt_block(ctx, pin, pout ); pin += 16; pout += 16; n -= 16; } } in D: void decrypt_block(ubyte[] input, ubyte[] output) ; ubyte[] ecb_decrypt(in ubyte[] input) in { assert(input.length > 0); } out(output) { assert(output.length == input.length); } body { int i,n, idx; ubyte[] pin; ubyte[] pout; ubyte[] output; n = input.length; output.length = n; idx=0; while( n > 0 ) { if (idx+BLOCK_SIZE >= input.length) { //we must decrypt less then BLOCK_SIZE decrypt_block(input[idx..$], output[idx..$]); } else { decrypt_block( input[idx..idx+BLOCK_SIZE], output[idx..idx+BLOCK_SIZE]); } idx += BLOCK_SIZE; n -= BLOCK_SIZE; } return output; } but I don't think that is the right way.. There is a simpler way using pointers like in C? I have tried to use something like: int n; ubyte *pin; ubyte *pout; ubyte[] output; n = input.length; output.length = n; pin = input.ptr; pout = output.ptr; while( n > 0 ) { decrypt_block(cast(ubyte[])pin, cast(ubyte[])pout); pin += 16; pout += 16; n -= 16; } but I get: test_aes.d(158): Error: e2ir: cannot cast from ubyte* to ubyte[] test_aes.d(158): Error: e2ir: cannot cast from ubyte* to ubyte[] yes I can modify decrypt_block, but this is not the point, I want just understand how can I solve it, in a D way. |
January 25, 2007 Re: array and pointers | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alberto | On Thu, 25 Jan 2007 12:36:53 +0100 Alberto <reda@zioale.it> wrote: > hi, I have just started to play with D, and I have some little problem. > > In C I did something like: > > #define uchar unsigned char > > void aes_ecb_decrypt(aes_context *ctx, uchar *input, uchar *output, > uint len ) { > int n; > uchar *pin, *pout; > > // test to validate parameters.. > > n = len; > pin = input; > pout = output; > > while( n > 0 ) { > decrypt_block(ctx, pin, pout ); > pin += 16; > pout += 16; > n -= 16; > } > } > > in D: > > void decrypt_block(ubyte[] input, ubyte[] output) ; > > ubyte[] ecb_decrypt(in ubyte[] input) > in { > assert(input.length > 0); > } > out(output) { > assert(output.length == input.length); > } > body { > int i,n, idx; > ubyte[] pin; > ubyte[] pout; > ubyte[] output; > > n = input.length; > output.length = n; > idx=0; > > while( n > 0 ) { > if (idx+BLOCK_SIZE >= input.length) { > //we must decrypt less then BLOCK_SIZE > decrypt_block(input[idx..$], > output[idx..$]); } else { > decrypt_block( input[idx..idx+BLOCK_SIZE], > output[idx..idx+BLOCK_SIZE]); } > idx += BLOCK_SIZE; > n -= BLOCK_SIZE; > } > return output; > } > > but I don't think that is the right way.. > There is a simpler way using pointers like in C? > I have tried to use something like: > > > int n; > ubyte *pin; > ubyte *pout; > ubyte[] output; > > n = input.length; > output.length = n; > pin = input.ptr; > pout = output.ptr; > > while( n > 0 ) { > decrypt_block(cast(ubyte[])pin, cast(ubyte[])pout); > pin += 16; > pout += 16; > n -= 16; > } > > but I get: > test_aes.d(158): Error: e2ir: cannot cast from ubyte* to ubyte[] > test_aes.d(158): Error: e2ir: cannot cast from ubyte* to ubyte[] > > yes I can modify decrypt_block, but this is not the point, I want just understand how can I solve it, in a D way. > > The problem you are having is that arrays in D are not like arrays in C. Think of D arrays as: struct DArray { type *ptr; size_t length; } This means there is no way to cast from a pointer to a D array, because D MUST know the length of that array. Here is my solution to the same ECB problem: void[] encrypt_ECB(void[] data, void[]to) in { assert(data.length > 0); assert(to is null || to.length >= data.length + pad_length(data)); } out(ciphertext) { assert(ciphertext.length >= data.length); assert(ciphertext.length <= data.length +b_size); assert(ciphertext.length % b_size == 0); body { ubyte pad = pad_length(data); size_t total = data.length + pad; if(to is null) to = new ubyte[total]; // copy and pad data to[0 .. data.length] = data; to[data.length .. total] = pad; assert(to.length % b_size == 0); for(size_t i=0; i < data.length; i += b_size) { encipher(output[i .. i+b_size]); } return to; } This is a member function of my BlockCipherAlg abstract class. Sub-classes of BlockCipherAlg implement encipher(void[]), allowing me to write one ECB, CBC, PCBC and other chaining method implementations for all block algorithms. If you're interested, I have a nearly complete version of my crypto library framework. -- ----------------------------------------------------- PGP public key ID: pub 2048R/2C19B7E6 2006-02-19 [expires: 2007-02-19] uid Matthew Wesley <mwesley@acm.org> Find it at http://pgp.mit.edu ----------------------------------------------------- |
January 25, 2007 Re: array and pointers | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wesley | Matthew Wesley wrote:
> Think of D arrays as:
>
> struct DArray {
> type *ptr;
> size_t length;
> }
Nitpick: the members are the other way around :p. (in DMD)
Not that it usually matters, but this may come up when writing inline assembly or calling extern(C) functions.
This is not in the spec though, so it's implementation-dependent.
However, it's not likely to change in DMD until Walter finally gets sick of printf[1]...
[1]: The current layout allows him to write 'printf("%.*s", string);' to print D strings.
|
January 25, 2007 Re: array and pointers | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | Frits van Bommel wrote:
> Nitpick: the members are the other way around :p. (in DMD)
> Not that it usually matters, but this may come up when writing inline assembly or calling extern(C) functions.
> This is not in the spec though, so it's implementation-dependent.
If you're going to nitpick, then it's implemented as a ulong
(32-bit length | 32-bit ptr) in DMD and as a struct in GDC...
This makes a difference for return values. Or when debugging.
And it definitely will later, when D supports 64-bit as well.
But most of the time, you can just use .length and .ptr :-)
--anders
|
January 25, 2007 Re: array and pointers | ||||
---|---|---|---|---|
| ||||
Posted in reply to Anders F Björklund | Anders F Björklund wrote:
> Frits van Bommel wrote:
>
>> Nitpick: the members are the other way around :p. (in DMD)
>> Not that it usually matters, but this may come up when writing inline assembly or calling extern(C) functions.
>> This is not in the spec though, so it's implementation-dependent.
>
> If you're going to nitpick, then it's implemented as a ulong
> (32-bit length | 32-bit ptr) in DMD and as a struct in GDC...
> This makes a difference for return values. Or when debugging.
> And it definitely will later, when D supports 64-bit as well.
>
> But most of the time, you can just use .length and .ptr :-)
Well, AFAIK the only real difference between ulongs and 8-byte structs is how they're returned from extern(C) functions (and perhaps extern(Windows/Pascal) as well).
The only reason I even *know* that is that several functions (e.g. _d_arrayappendT (previously _d_arrayappend) in Phobos) have their calling conventions all screwed up ;).
They get parameters passed like a C function, but return an array like a D function would.
This doesn't actually matter to the typical user, since they're only called internally by compiler-generated code that expects exactly that.
So for every-day use, I'd say the struct is way easier to understand and correct enough :p.
|
Copyright © 1999-2021 by the D Language Foundation