View mode: basic / threaded / horizontal-split · Log in · Help
October 29, 2012
How to place char* of stringZ to ubyte[]?
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[])
October 29, 2012
Re: How to place char* of stringZ to ubyte[]?
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
October 29, 2012
Re: How to place char* of stringZ to ubyte[]?
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[]
October 29, 2012
Re: How to place char* of stringZ to ubyte[]?
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
October 29, 2012
Re: How to place char* of stringZ to ubyte[]?
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);
> }
October 30, 2012
Re: How to place char* of stringZ to ubyte[]?
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.)
October 30, 2012
Re: How to place char* of stringZ to ubyte[]?
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
Top | Discussion index | About this forum | D home