Reading a string in binary mode

Christof Schardt csnews at schardt.info
Mon Mar 3 23:11:18 PST 2014


"bearophile" <bearophileHUGS at lycos.com> schrieb im Newsbeitrag 
news:qqcdemwimcylaizjyhfg at forum.dlang.org...
> Christof Schardt:
>
>> By "trickery" I meant having to know about things like
>> "import std.exception : assumeUnique" for this basic kind of task.
>
> Your function has signature (you use "ref" instead of "in" or "out" 
> because it performs read/write):
>
> void rw(ref string x)
>
> A string is a immutable(char)[], that is a dynamic array of immutable 
> (UTF-8) chars. In D a dynamic array is a struct (so it's a value) that 
> contains a length of the string (here in multiple of char.sizeof, that are 
> bytes) and a pointer to the actual string data. Your function gets a 
> string by reference, so it's a pointer to a mutable struct that points to 
> immutable chars.
>
> The else branch suggested by John Colvin was:
>
>>         else
>>         {
>>             size_t size;
>>             _f.rawRead((&size)[0..1]);
>>             auto tmp = new char[size];
>>             _f.rawRead(tmp);
>>             import std.exception : assumeUnique;
>>             x = tmp.assumeUnique;
>>         }
>
> This allocated a GC-managed dymamic array of chars (the buffer tmp), and 
> loads the data into them:
>
> auto tmp = new char[size];
> _f.rawRead(tmp);
>
> Now you can't just perform:
>
> x = tmp;
>
> D manages the pointer to the dynamic array x automatically, so x can be 
> seen as a dynamic array array. But their type is different, x refers to 
> immutable(char)[] while tmp is a char[]. In general you can't implicitly 
> convert immutable data with indirections to mutable data with 
> indirections, because this breaks the assumptions immutability is based on 
> (while in D you can assign a char[] to a const(char)[] variable. It's the 
> difference between const an immutable). So the "trickery" comes from 
> satisfying the strong typing of D. It's the price you have to pay for 
> safety and (in theory) a bit of improvements in concurrent code.
>
> assumeUnique is essentially a better documented cast, that converts 
> mutable to immutable. It's similar to cast(immutable). D doesn't have 
> uniqueness typing so in many cases the D compiler is not able to infer the 
> uniqueness of data for you (and unique data can be implicitly converted to 
> immutable). But the situation on this is improving (this is already 
> partially implemented and merged, and will be present in D 2.066: 
> http://wiki.dlang.org/DIP29 ).
>
> when the function you are calling is pure (unlike rawRead) you don't need 
> assumeUnique:
>
> import std.exception: assumeUnique;
>
> void foo(out char[] s) pure {
>     foreach (immutable i, ref c; s)
>         c = cast(char)i;
> }
>
> // Using assumeUnique:
> void bar1(ref string s) {
>     auto tmp = new char[10];
>     foo(tmp);
>     s = tmp.assumeUnique;
> }
>
> // Using the D type system:
> void bar2(ref string s) {
>     static string local() pure {
>         auto tmp = new char[10];
>         foo(tmp);
>         return tmp;
>     }
>     s = local;
> }
>
> void main() {}
>
> Bye,
> bearophile

Great, thanks for this insight.
Christof 




More information about the Digitalmars-d-learn mailing list