digitalmars.D.learn - array and pointers
- Alberto (74/74) Jan 25 2007 hi, I have just started to play with D, and I have some little problem.
- Matthew Wesley (45/135) Jan 25 2007 The problem you are having is that arrays in D are not like arrays in
- Frits van Bommel (9/15) Jan 25 2007 Nitpick: the members are the other way around :p. (in DMD)
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (7/11) Jan 25 2007 If you're going to nitpick, then it's implemented as a ulong
- Frits van Bommel (13/26) Jan 25 2007 Well, AFAIK the only real difference between ulongs and 8-byte structs
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: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.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 :-)
Jan 25 2007