Catching up on the DConf '22 videos, really enjoyed the tricks
Walter presents here for no-allocation strings:
[DConf '22: Strawberries and Cream aka Delightful Emergent
Properties of D -- Walter
Bright](https://www.youtube.com/watch?v=iuP-AWUyjp8)
In the Q&A segment, the first question asked whether the filename
in the path example needs memory allocation to be passed to C,
and is told it does, however the two methods presented can be
easily combined to provide no-allocation 0-terminated strings
from `chain()`ed paths by passing an `InputRange` rather than a
`const(char)` to `toCStringThen`:
```d
//version=AllowMalloc;
auto toCStringThen(alias dg, Range)(Range src) /*nothrow*/ if
(isInputRange!Range && !isInfinite!Range) {
const len = src.walkLength;
char[512] small = void;
version(AllowMalloc) {
import dmd.common.string : SmallBuffer;
auto sb = SmallBuffer!char(len + 1, small[]);
scope ptr = sb[];
} else {
enforce(len < small.length, format!"C string buffer overflow
(%s >= %s)"(len, small.length));
scope ptr = small[];
}
size_t i = 0;
foreach (char c; src)
ptr[i++] = c;
ptr[len] = '\0';
return dg(ptr);
}
void main() {
string path = "include/";
string name = "file";
string ext = ".ext";
auto filename = chain(path, name, ext);
filename.writeln;
filename.byChar.toCStringThen!(
(str) => printf("printf: {%s}\n", str.ptr)
);
}
```
May need to be cleaned up for character types and needs to
iterate twice if allocations are going to be allowed, and
walkLength/chain()'s range functions aren't nothrow as far as I
can tell. But otherwise thought this was kind of neat, just
posting it here in case anyone else finds it handy.