www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to place char* of stringZ to ubyte[]?

reply "denizzzka" <4denizzz gmail.com> writes:
immutable ubyte[] valueBin = cast(immutable(ubyte[])) 
toStringz(s); // s is string type

Error: e2ir: cannot cast toStringz(s) of type immutable(char)* to 
type immutable(ubyte[])
Oct 29 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
denizzzka:

 immutable ubyte[] valueBin = cast(immutable(ubyte[])) 
 toStringz(s); // s is string type

 Error: e2ir: cannot cast toStringz(s) of type immutable(char)* 
 to type immutable(ubyte[])

One way to do it: import std.stdio; void main() { string s = "hello"; auto valueBin = cast(immutable ubyte[])s.dup; writeln(valueBin); } But what are you trying to do? Bye, bearophile
Oct 29 2012
prev sibling next sibling parent "denizzzka" <4denizzz gmail.com> writes:
On Monday, 29 October 2012 at 17:51:56 UTC, bearophile wrote:
 denizzzka:

 immutable ubyte[] valueBin = cast(immutable(ubyte[])) 
 toStringz(s); // s is string type

 Error: e2ir: cannot cast toStringz(s) of type immutable(char)* 
 to type immutable(ubyte[])

One way to do it: import std.stdio; void main() { string s = "hello"; auto valueBin = cast(immutable ubyte[])s.dup; writeln(valueBin); } But what are you trying to do?

I am trying to send to remote host utf8 text with zero byte at end (required by protocol) But sending function accepts only ubyte[]
Oct 29 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
Oct 29 2012
prev sibling next sibling parent "denizzzka" <4denizzz gmail.com> writes:
On Monday, 29 October 2012 at 18:50:58 UTC, bearophile wrote:
 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?

Incredible situation because it is text-based protocol
 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);
 }

I am concerned about the extra allocations of temp arrays. here is it, or not? compiler optimizes it? In my case it does not matter but for the future I would like to know how it can be implemented without overhead.
 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:

Yes, already implemented similar.
 struct BytesBuf {
     this(string s) {
         this.data = cast(typeof(data))(s ~ '\0');
     }
     byte[] data = [0];

Why not "byte[] data;" ?
     alias this = data; // new syntax

What difference between this syntax and "alias Something this"?
 }
 void main() {
    import std.stdio;
    string s = "hello";
    auto valueBin3 = BytesBuf(s);
    writeln(valueBin3);
 }

Oct 29 2012
prev sibling next sibling parent Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
On Mon, 29 Oct 2012 19:50:57 +0100
"bearophile" <bearophileHUGS lycos.com> wrote:

 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?

If you need to send a string with an embedded null through a null-terminated-string protocol, then you're pretty much screwed anyway. FWIW ;) ('Course, the embedded nulls could be stripped if they're not actually important.)
Oct 30 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
denizzzka:

 I am concerned about the extra allocations of temp arrays. here 
 is it, or not? compiler optimizes it?

There is one allocation, and usually the D compilers can't optimize it away.
 In my case it does not matter but for the future I would like 
 to know how it can be implemented without overhead.

If you don't want overhead you need some static buffer, bigger than any possible string, and to copy data on it and slice it as needed. Otherwise appending one null char risks allocating. If you append it in-place in the original string the risk of allocations is lower, but not zero.
    byte[] data = [0];

Why not "byte[] data;" ?

I was thinking about keeping the protocol invariant, but you are right, it's probably useless. A null is enough to denote an empty string.
    alias this = data; // new syntax

What difference between this syntax and "alias Something this"?

There's no difference. Instead of focusing on other syntaxes that actually do something useful (like [$] to define fixed-size arrays automatically, or somehting else), Walter has accepted to add one more way to do the same thing. I don't like this change. Bye, bearophile
Oct 30 2012