www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using array slices with C-style fread() from file

reply uncorroded <uncorroded temp.org> writes:
Hi all,

I am writing a program to read device /dev/urandom file to get 
some random bytes. I am trying to bypass D's GC as I know the 
length of the buffer needed. I tried using std.stdio.File and 
rawRead but File cannot be used with  nogc. So I used 
core.stdc.stdio and used traditional C style. My code is here - 
https://dpaste.dzfl.pl/36e1df4cb99b (Also at end of post). I am 
using fread instead of read because /dev/urandom can be accessed 
by other programs (From this post - 
http://insanecoding.blogspot.in/2014/05/a-good-idea-with-bad-u
age-devurandom.html ). As you can see from code, I ended up doing pointer
arithmetic. Is there a way of making this work with D slices? Can they be used
as C-style pointers?

My D function used for getting random bytes:

 nogc ubyte[n] rand_bytes(uint n)() {
     import core.stdc.stdio;
     FILE *fp;
     fp = fopen("/dev/urandom", "r");
     ubyte[n] buf;
     ubyte *bp = &buf[0];
     uint bread = 0;
     while (bread < n) {
         auto toread = n - bread;
         auto read = fread(bp, ubyte.sizeof, toread, fp);
         bread += read;
         bp += read;
     }
     fclose(fp);
     return buf;
}
Jun 21
next sibling parent reply tetyys <tetyys tetyys.com> writes:
On Wednesday, 21 June 2017 at 18:49:01 UTC, uncorroded wrote:
 Is there a way of making this work with D slices? Can they be 
 used as C-style pointers?
What about this: nogc ubyte[n] rand_bytes(uint n)() { import core.stdc.stdio; FILE *fp; fp = fopen("/dev/urandom", "r"); ubyte[n] buf; uint bread = 0; while (bread < n) { auto toread = n - bread; auto read = fread(buf[bread .. $].ptr, ubyte.sizeof, toread, fp); bread += read; } fclose(fp); return buf; } ?
Jun 21
next sibling parent tetyys <tetyys tetyys.com> writes:
On Wednesday, 21 June 2017 at 18:58:58 UTC, tetyys wrote:
 On Wednesday, 21 June 2017 at 18:49:01 UTC, uncorroded wrote:
 Is there a way of making this work with D slices? Can they be 
 used as C-style pointers?
What about this
Or simpler, while (left) left -= fread(buf[n-left .. $].ptr, ubyte.sizeof, left, fp);
Jun 21
prev sibling parent reply uncorroded <uncorroded temp.org> writes:
On Wednesday, 21 June 2017 at 18:58:58 UTC, tetyys wrote:
 On Wednesday, 21 June 2017 at 18:49:01 UTC, uncorroded wrote:
 Is there a way of making this work with D slices? Can they be 
 used as C-style pointers?
What about this: nogc ubyte[n] rand_bytes(uint n)() { import core.stdc.stdio; FILE *fp; fp = fopen("/dev/urandom", "r"); ubyte[n] buf; uint bread = 0; while (bread < n) { auto toread = n - bread; auto read = fread(buf[bread .. $].ptr, ubyte.sizeof, toread, fp); bread += read; } fclose(fp); return buf; } ?
Thanks a lot! That works. Did not know about the .ptr for a slice. Is there any way of making the function with safe as well? I get the errors "cannot call system function 'core.stdc.stdio.fread,fopen,fclose'.
Jun 21
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/21/2017 12:06 PM, uncorroded wrote:

 Is
 there any way of making the function with  safe as well? I get the
 errors "cannot call  system function 
'core.stdc.stdio.fread,fopen,fclose'. trusted is exactly for that. It can be called from safe code: trusted nogc ubyte[n] rand_bytes(uint n)() { // ... } safe auto foo() { return rand_bytes!3(); } Ali
Jun 21
parent reply uncorroded <uncorroded temp.org> writes:
On Wednesday, 21 June 2017 at 19:11:44 UTC, Ali Çehreli wrote:
 On 06/21/2017 12:06 PM, uncorroded wrote:

 Is
 there any way of making the function with  safe as well? I
get the
 errors "cannot call  system function
'core.stdc.stdio.fread,fopen,fclose'. trusted is exactly for that. It can be called from safe code: trusted nogc ubyte[n] rand_bytes(uint n)() { // ... } safe auto foo() { return rand_bytes!3(); } Ali
Thanks! So trusted is me guaranteeing to the compiler that this function is safe? Is there any way of auditing this code through valgrind, etc. Also, thanks a lot for your book on D. It has been an invaluable resource in getting me started.
Jun 21
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 06/21/2017 12:20 PM, uncorroded wrote:

 So  trusted is me guaranteeing to the compiler that this
 function is safe?
Yes and you shouldn't lie. :)
 Is there any way of auditing this code through
 valgrind, etc.
That's a good idea, which you can do yourself but I don't think you can be sure beyond the tests that you've ran. There can always be corner cases where the library you use may not be memory-safe. You have to trust... :)
 invaluable resource in getting me started.
Thank you! Makes me very happy to hear that. :) Ali
Jun 21
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
- Fixed-length arrays are value types. You may not want to return them 
if n is very large.

- Every array has the .ptr property that gives the pointer to the first 
element.

- What can be helpful to you here is the fact that you can treat any 
memory as a slice:

import core.stdc.stdlib;

struct S {
     double d;
}

void main() {
     ubyte * p = cast(ubyte*)malloc(10);
     ubyte[] slice = p[0..10];    // 10 is number of elements

     // Another example with a struct object:
     auto objectCount = 7;
     S * objects = cast(S*)malloc(objectCount * S.sizeof);
     auto S_slice = objects[0..objectCount];
}

Of course, you must be careful with slice lifetimes in this case; you 
shouldn't use the slices after freeing the memory.

Ali
Jun 21