digitalmars.D.learn - array and pointers
- Alberto <reda zioale.it> Jan 25 2007
- Matthew Wesley <mwesley acm.org> Jan 25 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Jan 25 2007
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> Jan 25 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Jan 25 2007
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.
Jan 25 2007
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 -----------------------------------------------------
Jan 25 2007
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.
Jan 25 2007
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
Jan 25 2007
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.
Jan 25 2007








Frits van Bommel <fvbommel REMwOVExCAPSs.nl>