On Saturday, 24 June 2017 at 13:11:02 UTC, Stefan Koch wrote:
On Saturday, 24 June 2017 at 12:22:54 UTC, Petar Kirov
[ZombineDev] wrote:
[ ... ]
/**
* Returns:
* A pointer to a null-terminated string in O(1) time,
* (with regards to the length of the string and the required
* memory, if any) or `null` if * the time constraint
* can't be met.
*/
immutable(T)* fastStringZ(T)(return immutable(T)[] s) @trusted
if (isSomeChar!T)
{
if (isStaticallyAllocated(s) && s.ptr[s.length] == 0)
return s.ptr;
else
return null;
}
---
(Without `isStaticallyAllocated`, `fastStringZ` may *appear* to
work but if you pass the pointer to e.g. a C library and that
library keeps it after the call has completed, good luck
tracking
memory corruption if the slice was pointing to
automatic/dynamic
memory - e.g. static array buffer on the stack or GC / RC *
heap
allocation.
* malloc or custom allocator + smart pointer wrapper)
Please note that not all static immutable strings have to be
null terminated.
It is possible to generate a string at ctfe which may appear
the same as string literal, but does not have the \0 at the end.
But in that case, the check `s.ptr[s.length] == 0` in fastStringZ
would do the trick, right?
BTW, are you sure? AFAIU, it doesn't matter if the CTFE engine
returns a
non-null-terminated string expression, since the backend or the
glue layer
would write it to the object file as if it was a null-terminated
string.
But you're right if you mean that this trick won't work in CTFE,
since
the `s.ptr[s.length] == 0` trick rightfully is disallowed.
---
void main()
{
static immutable str = generateString();
pragma (msg, str, " is null-terminated at CT: ",
str.isNullTerminated());
import std.stdio;
writeln(str, " is null-terminated at RT: ",
str.isNullTerminated());
}
string generateString()
{
string res;
foreach (i; 0 .. 26) res ~= 'a' + i;
return res;
}
import std.traits : isSomeChar;
bool isNullTerminated(T)(scope const T[] str)
if (isSomeChar!T)
{
if (!__ctfe)
return str.ptr[str.length] == 0;
else
return false;
}
---
Compilation output:
abcdefghijklmnopqrstuvwxyz is null-terminated at CT: false
Application output:
abcdefghijklmnopqrstuvwxyz is null-terminated at RT: true