Reading a string in binary mode
bearophile
bearophileHUGS at lycos.com
Mon Mar 3 15:27:17 PST 2014
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
More information about the Digitalmars-d-learn
mailing list