How to place char* of stringZ to ubyte[]?

bearophile bearophileHUGS at lycos.com
Mon Oct 29 11:50:57 PDT 2012


denizzzka:

> I am trying to send to remote host utf8 text with zero byte at 
> end (required by protocol)

What if your UTF8 string coming from D already contains several 
zeros?

toStringz(s) returns a pointer, so you can't cast a pointer (that 
doesn't know the length the buffer it points to) to an array. You 
have to tell it the length in some way. One way is to slice the 
pointer, another solution is to append a '\0' and then cast it to 
an immutable array. Two solutions:


import std.stdio, std.string;
void main() {
    string s = "hello";
    auto valueBin1 = cast(immutable ubyte[])(s ~ '\0');
    writeln(valueBin1);
    auto valueBin2 = cast(immutable ubyte[])(s.toStringz()[0 .. 
s.length + 1]);
    writeln(valueBin2);
}

If you have to do this more than two or three times it's better 
to write a little function to do it, to avoid bugs.

Even better is to define with strong typing the type of such 
nil-terminated array of bytes, to avoid other mistakes. This used 
to be possible in D with typedef. Now one a little clumsy way to 
do it is to use a struct with "alias this". This is just a sketch:


struct BytesBuf {
     this(string s) {
         this.data = cast(typeof(data))(s ~ '\0');
     }
     byte[] data = [0];
     alias this = data; // new syntax
}
void main() {
    import std.stdio;
    string s = "hello";
    auto valueBin3 = BytesBuf(s);
    writeln(valueBin3);
}


Bye,
bearophile


More information about the Digitalmars-d-learn mailing list