www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - ubyte to string conversion (md5)

reply "Asaf Karagila" <kas1 netvision.net.il> writes:
well,
i'm kinda stuck.. i've done those things before, and for some reason, they 
won't work here..
i'm trying to convert an MD5 digest from std.md5 (ubyte[16]) into a string 
(char[])
i need it for internal usage, so using printDigest is useless for me, unless 
there is a way i can print it into a string..
i tired (fuitily i must say) several ways of converting the bytes into 
chars,
none worked.

does anyone have any code for that, or some tips for me ?

Cheers,
Asaf 
Oct 09 2004
next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Asaf Karagila" <kas1 netvision.net.il> wrote in message
news:ck9s27$1b4a$1 digitaldaemon.com...
 well,
 i'm kinda stuck.. i've done those things before, and for some reason, they
 won't work here..
 i'm trying to convert an MD5 digest from std.md5 (ubyte[16]) into a string
 (char[])
 i need it for internal usage, so using printDigest is useless for me,

 there is a way i can print it into a string..
 i tired (fuitily i must say) several ways of converting the bytes into
 chars,
 none worked.

 does anyone have any code for that, or some tips for me ?

 Cheers,
 Asaf

do you mean something like: import std.string; import std.stdio; ubyte[] x = [10, 20, 30]; int main() { char[] y; foreach(ubyte n;x) y ~= toString(n) ~ " "; writefln(y); return 0; }
Oct 09 2004
parent "Asaf Karagila" <kas1 netvision.net.il> writes:
"Ben Hinkle" <bhinkle mathworks.com> wrote in message 
news:cka2o8$1ep3$1 digitaldaemon.com...
 "Asaf Karagila" <kas1 netvision.net.il> wrote in message
 news:ck9s27$1b4a$1 digitaldaemon.com...
 well,
 i'm kinda stuck.. i've done those things before, and for some reason, 
 they
 won't work here..
 i'm trying to convert an MD5 digest from std.md5 (ubyte[16]) into a 
 string
 (char[])
 i need it for internal usage, so using printDigest is useless for me,

 there is a way i can print it into a string..
 i tired (fuitily i must say) several ways of converting the bytes into
 chars,
 none worked.

 does anyone have any code for that, or some tips for me ?

 Cheers,
 Asaf

do you mean something like: import std.string; import std.stdio; ubyte[] x = [10, 20, 30]; int main() { char[] y; foreach(ubyte n;x) y ~= toString(n) ~ " "; writefln(y); return 0; }

thats a cool routine, but its not exactly what i am looking for, it gives out a decimal output, what i need is actually a 128bit hex number output..
Oct 09 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Sun, 10 Oct 2004 01:26:51 +0200, Asaf Karagila <kas1 netvision.net.il> 
wrote:
 well,
 i'm kinda stuck.. i've done those things before, and for some reason, 
 they
 won't work here..
 i'm trying to convert an MD5 digest from std.md5 (ubyte[16]) into a 
 string
 (char[])
 i need it for internal usage, so using printDigest is useless for me, 
 unless
 there is a way i can print it into a string..
 i tired (fuitily i must say) several ways of converting the bytes into
 chars,
 none worked.

 does anyone have any code for that, or some tips for me ?

Try this... template hexStringT(T) { char[] hexStringT(T d) { char[] result; if (d.length != 0) { typeof(d[0]) u; uint sz = u.sizeof*2; uint ndigits = 0; result = new char[sz*d.length]; for(int i = d.length-1; i >= 0; i--) { u = d[i]; for(; u; u /= 16) { result[result.length-1-ndigits] = hexdigits[u & 15]; ndigits++; } for(; ndigits < (d.length-i)*sz; ndigits++) result[result.length-1-ndigits] = '0'; } } return result; } } char[] toHexString(ubyte[] array) { return hexStringT!(typeof(array))(array); } char[] toHexString(ulong[] array) { return hexStringT!(typeof(array))(array); } char[] toHexString(uint[] array) { return hexStringT!(typeof(array))(array); } The above code is from my library of hashing routines in the Deimos library which you can find here: http://www.dsource.org/projects/deimos/ Deimos is an open source library to which anyone can contribute. You can use the "Browse SVN Repository for Deimos" link to have a look at the other source files, the hashing routines are here: http://svn.dsource.org/svn/projects/deimos/trunk/etc/crypto/hash/ Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Oct 10 2004
parent reply "Asaf Karagila" <kas1 netvision.net.il> writes:
thanks for the code,
its a bit over my level at the moment, and i don't like using code i can't 
understand..
so i'm not sure if i'll use it,
as well, i managed to sort something out.. its almost perfect as well..

foreach(ubyte u;array)
     myString ~= std.string.format("%2X",u);

it gives me out a pretty good result, only its sticking a 'b' on the end, i 
don't know why..
anyone got a clue about that ?

Cheers,
Asaf 
Oct 10 2004
next sibling parent reply Sjoerd van Leent <svanleent wanadoo.nl> writes:
Asaf Karagila wrote:
 thanks for the code,
 its a bit over my level at the moment, and i don't like using code i can't 
 understand..
 so i'm not sure if i'll use it,
 as well, i managed to sort something out.. its almost perfect as well..
 
 foreach(ubyte u;array)
      myString ~= std.string.format("%2X",u);
 
 it gives me out a pretty good result, only its sticking a 'b' on the end, i 
 don't know why..
 anyone got a clue about that ?
 
 Cheers,
 Asaf 
 
 

I don't quite see what the problem is. If I run the following code: import std.stdio; import std.string; int main (char[][] args) { char[] s; const static ubyte[] array = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ]; foreach(ubyte u; array) { s ~= format("%2X", u); } writefln(s); // writes: 0 1 2 3 4 5 6 7 8 9 A B C D E F return 0; } It does print the values as it is supposed to do Regards, Sjoerd
Oct 11 2004
parent reply "Asaf Karagila" <kas1 netvision.net.il> writes:
"Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
news:ckdp2m$15id$1 digitaldaemon.com...
 Asaf Karagila wrote:
 thanks for the code,
 its a bit over my level at the moment, and i don't like using code i 
 can't understand..
 so i'm not sure if i'll use it,
 as well, i managed to sort something out.. its almost perfect as well..

 foreach(ubyte u;array)
      myString ~= std.string.format("%2X",u);

 it gives me out a pretty good result, only its sticking a 'b' on the end, 
 i don't know why..
 anyone got a clue about that ?

 Cheers,
 Asaf

I don't quite see what the problem is. If I run the following code: import std.stdio; import std.string; int main (char[][] args) { char[] s; const static ubyte[] array = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ]; foreach(ubyte u; array) { s ~= format("%2X", u); } writefln(s); // writes: 0 1 2 3 4 5 6 7 8 9 A B C D E F return 0; } It does print the values as it is supposed to do Regards, Sjoerd

yeah, it doesn't look flawed either, so maybe the buffer allocated for the char[] i have is already used ? if so, is there a way to initialize the array to be clear, and to clean the memory its using ? Cheers, Asaf
Oct 11 2004
parent reply Sjoerd van Leent <svanleent wanadoo.nl> writes:
Asaf Karagila wrote:
 "Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
 news:ckdp2m$15id$1 digitaldaemon.com...
 
Asaf Karagila wrote:

thanks for the code,
its a bit over my level at the moment, and i don't like using code i 
can't understand..
so i'm not sure if i'll use it,
as well, i managed to sort something out.. its almost perfect as well..

foreach(ubyte u;array)
     myString ~= std.string.format("%2X",u);

it gives me out a pretty good result, only its sticking a 'b' on the end, 
i don't know why..
anyone got a clue about that ?

Cheers,
Asaf

I don't quite see what the problem is. If I run the following code: import std.stdio; import std.string; int main (char[][] args) { char[] s; const static ubyte[] array = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ]; foreach(ubyte u; array) { s ~= format("%2X", u); } writefln(s); // writes: 0 1 2 3 4 5 6 7 8 9 A B C D E F return 0; } It does print the values as it is supposed to do Regards, Sjoerd

yeah, it doesn't look flawed either, so maybe the buffer allocated for the char[] i have is already used ? if so, is there a way to initialize the array to be clear, and to clean the memory its using ? Cheers, Asaf

Initialize the array to an empty array. This could be done using an empty array or using the init property of the current array: char[] s; s = s.init; this should work as expected. Regards, Sjoerd
Oct 11 2004
parent reply "Asaf Karagila" <kas1 netvision.net.il> writes:
"Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
news:ckebb5$1mkb$1 digitaldaemon.com...
 Asaf Karagila wrote:
 "Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
 news:ckdp2m$15id$1 digitaldaemon.com...

Asaf Karagila wrote:

thanks for the code,
its a bit over my level at the moment, and i don't like using code i 
can't understand..
so i'm not sure if i'll use it,
as well, i managed to sort something out.. its almost perfect as well..

foreach(ubyte u;array)
     myString ~= std.string.format("%2X",u);

it gives me out a pretty good result, only its sticking a 'b' on the 
end, i don't know why..
anyone got a clue about that ?

Cheers,
Asaf

I don't quite see what the problem is. If I run the following code: import std.stdio; import std.string; int main (char[][] args) { char[] s; const static ubyte[] array = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ]; foreach(ubyte u; array) { s ~= format("%2X", u); } writefln(s); // writes: 0 1 2 3 4 5 6 7 8 9 A B C D E F return 0; } It does print the values as it is supposed to do Regards, Sjoerd

yeah, it doesn't look flawed either, so maybe the buffer allocated for the char[] i have is already used ? if so, is there a way to initialize the array to be clear, and to clean the memory its using ? Cheers, Asaf

Initialize the array to an empty array. This could be done using an empty array or using the init property of the current array: char[] s; s = s.init; this should work as expected. Regards, Sjoerd

char[] MD5; MD5.init; foreach(ubyte u;di) MD5 ~= std.string.format("%2X",u); printf(MD5); the output is : "9ADD3AF83DD9DAAA75BDF5CE4E476CBCb" i don't know where does this 'b' is coming from, and i would like to remove it.. weird. Cheers, Asaf
Oct 11 2004
next sibling parent Burton Radons <burton-radons smocky.com> writes:
Asaf Karagila wrote:
 "Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
 news:ckebb5$1mkb$1 digitaldaemon.com...
 
Asaf Karagila wrote:

"Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
news:ckdp2m$15id$1 digitaldaemon.com...


Asaf Karagila wrote:


thanks for the code,
its a bit over my level at the moment, and i don't like using code i 
can't understand..
so i'm not sure if i'll use it,
as well, i managed to sort something out.. its almost perfect as well..

foreach(ubyte u;array)
    myString ~= std.string.format("%2X",u);

it gives me out a pretty good result, only its sticking a 'b' on the 
end, i don't know why..
anyone got a clue about that ?

Cheers,
Asaf

I don't quite see what the problem is. If I run the following code: import std.stdio; import std.string; int main (char[][] args) { char[] s; const static ubyte[] array = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ]; foreach(ubyte u; array) { s ~= format("%2X", u); } writefln(s); // writes: 0 1 2 3 4 5 6 7 8 9 A B C D E F return 0; } It does print the values as it is supposed to do Regards, Sjoerd

yeah, it doesn't look flawed either, so maybe the buffer allocated for the char[] i have is already used ? if so, is there a way to initialize the array to be clear, and to clean the memory its using ? Cheers, Asaf

Initialize the array to an empty array. This could be done using an empty array or using the init property of the current array: char[] s; s = s.init; this should work as expected. Regards, Sjoerd

char[] MD5; MD5.init; foreach(ubyte u;di) MD5 ~= std.string.format("%2X",u); printf(MD5); the output is : "9ADD3AF83DD9DAAA75BDF5CE4E476CBCb" i don't know where does this 'b' is coming from, and i would like to remove it.. weird.

http://www.digitalmars.com/d/faq.html#printf
Oct 11 2004
prev sibling next sibling parent "Asaf Karagila" <kas1 netvision.net.il> writes:
"Asaf Karagila" <kas1 netvision.net.il> wrote in message 
news:ckecsq$1o26$1 digitaldaemon.com...
    char[] MD5;
    MD5.init;
    foreach(ubyte u;di)
        MD5 ~= std.string.format("%2X",u);
    printf(MD5);

 the output is :
 "9ADD3AF83DD9DAAA75BDF5CE4E476CBCb"
 i don't know where does this 'b' is coming from, and i would like to 
 remove it..
 weird.

 Cheers,
 Asaf

well, as i suspected, the problem resides within the MD5 string space, nothing helped, its probably a bug in the implementation, when i made an addition to the code char[32] md5string; for (int i=0;i<MD5.length;i++) md5string[i]=MD5[i]; the 'b' on the end of the MD5 string was gone.. i guess that solves my problem. but i think its ought a deeper check, i'll do my best to debug it in low level.. if i'll have something concrete, i'll post it back. Cheers, Asaf
Oct 11 2004
prev sibling parent reply Sjoerd van Leent <svanleent wanadoo.nl> writes:
Asaf Karagila wrote:
 "Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
 news:ckebb5$1mkb$1 digitaldaemon.com...
 
Asaf Karagila wrote:

"Sjoerd van Leent" <svanleent wanadoo.nl> wrote in message 
news:ckdp2m$15id$1 digitaldaemon.com...


Asaf Karagila wrote:


thanks for the code,
its a bit over my level at the moment, and i don't like using code i 
can't understand..
so i'm not sure if i'll use it,
as well, i managed to sort something out.. its almost perfect as well..

foreach(ubyte u;array)
    myString ~= std.string.format("%2X",u);

it gives me out a pretty good result, only its sticking a 'b' on the 
end, i don't know why..
anyone got a clue about that ?

Cheers,
Asaf

I don't quite see what the problem is. If I run the following code: import std.stdio; import std.string; int main (char[][] args) { char[] s; const static ubyte[] array = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ]; foreach(ubyte u; array) { s ~= format("%2X", u); } writefln(s); // writes: 0 1 2 3 4 5 6 7 8 9 A B C D E F return 0; } It does print the values as it is supposed to do Regards, Sjoerd

yeah, it doesn't look flawed either, so maybe the buffer allocated for the char[] i have is already used ? if so, is there a way to initialize the array to be clear, and to clean the memory its using ? Cheers, Asaf

Initialize the array to an empty array. This could be done using an empty array or using the init property of the current array: char[] s; s = s.init; this should work as expected. Regards, Sjoerd

char[] MD5; MD5.init; foreach(ubyte u;di) MD5 ~= std.string.format("%2X",u); printf(MD5); the output is : "9ADD3AF83DD9DAAA75BDF5CE4E476CBCb" i don't know where does this 'b' is coming from, and i would like to remove it.. weird. Cheers, Asaf

Ah there is the problem, if you look close to my code, you'll notice that I use writefln instead of printf. Printf only knows standard C string conventions, which isn't used by D. You should use the writef and writefln of the sts.stdio module instead. Regards, Sjoerd
Oct 11 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Mon, 11 Oct 2004 19:46:26 +0200, Sjoerd van Leent 
<svanleent wanadoo.nl> wrote:
 the output is :
 "9ADD3AF83DD9DAAA75BDF5CE4E476CBCb"
 i don't know where does this 'b' is coming from, and i would like to 
 remove it..
 weird.

 Cheers,
 Asaf

Ah there is the problem, if you look close to my code, you'll notice that I use writefln instead of printf. Printf only knows standard C string conventions, which isn't used by D. You should use the writef and writefln of the sts.stdio module instead.

Sjoerd is right :) You can still use printf if you like, see the link Burton gave: http://www.digitalmars.com/d/faq.html#printf eg. printf("%.*s",MD5); Basically, a D char[] is a struct sorta like so struct char { int length; void* data; } so the above is a little bit of an evil hack, causing printf to grab the length from the D char and print only the right amount of data. a D char[]'s data does not contain the C trailing NULL character which signals the end of the string. D will auto-magically cast a D char to a C char, but, it does not add a trailing NULL. To add a trailing NULL try: printf(toStringZ(MD5)); As the signature for printf is: int printf(char *format, ...); D is converting the D char[] to a char *, but not adding a null. As printf keeps going till it finds a NULL, it's simply luck that it stops where it does. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Oct 11 2004
prev sibling parent Regan Heath <regan netwin.co.nz> writes:
On Mon, 11 Oct 2004 07:30:41 +0200, Asaf Karagila <kas1 netvision.net.il> 
wrote:
 thanks for the code,
 its a bit over my level at the moment, and i don't like using code i 
 can't
 understand..

Then allow me to elucidate... It's not too complex if you break it down into parts. It's a generic version of this: const char[16] hexdigits = "0123456789ABCDEF"; char[] hexStringT(ubyte[] d) { char[] result; /* No point converting an empty array now is there? */ if (d.length != 0) { ubyte u; uint sz = u.sizeof*2; /* number of chars required to represent one 'u' */ uint ndigits = 0; /* pre-allocate space required. */ result = new char[sz*d.length]; /* start at end of resulting string, loop back to start. */ for(int i = d.length-1; i >= 0; i--) { /*this loop takes the remainder of u/16, uses it as an index into the hexdigits array, then does u/16, repeating till u == 0 */ u = d[i]; for(; u; u /= 16) { /* you can use u & 15 or u % 16 below both give you the remainder of u/16 */ result[result.length-1-ndigits] = hexdigits[u & 15]; ndigits++; } /* Pad each value with 0's */ for(; ndigits < (d.length-i)*sz; ndigits++) result[result.length-1-ndigits] = '0'; } } return result; } which is very similar to the functions in std.string, i.e. char[] toString(uint u) { char[uint.sizeof * 3] buffer; int ndigits; char c; char[] result; ndigits = 0; if (u < 10) // Avoid storage allocation for simple stuff result = digits[u .. u + 1]; else { while (u) { c = (u % 10) + '0'; u /= 10; ndigits++; buffer[buffer.length - ndigits] = c; } result = new char[ndigits]; result[] = buffer[buffer.length - ndigits .. buffer.length]; } return result; }
 so i'm not sure if i'll use it,
 as well, i managed to sort something out.. its almost perfect as well..

 foreach(ubyte u;array)
      myString ~= std.string.format("%2X",u);

yeah, that works, I believe my methods is more efficient because: - yours is appending, which causes string reallocations. - yours is calling a complex function 'format' for each ubyte. that said, the difference is probably negligible unless you're using it a lot. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Oct 11 2004