Output range with custom string type
Moritz Maxeiner via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Aug 28 14:45:36 PDT 2017
On Monday, 28 August 2017 at 14:27:19 UTC, Jacob Carlborg wrote:
> I'm working on some code that sanitizes and converts values of
> different types to strings. I thought it would be a good idea
> to wrap the sanitized string in a struct to have some type
> safety. Ideally it should not be possible to create this type
> without going through the sanitizing functions.
>
> The problem I have is that I would like these functions to push
> up the allocation decision to the caller. Internally these
> functions use formattedWrite. I thought the natural design
> would be that the sanitize functions take an output range and
> pass that to formattedWrite.
>
> [...]
>
> Any suggestions how to fix this or a better idea?
If you want the caller to be just in charge of allocation, that's
what std.experimental.allocator provides. In this case, I would
polish up the old "format once to get the length, allocate,
format second time into allocated buffer" method used with
snprintf for D:
--- test.d ---
import std.stdio;
import std.experimental.allocator;
struct CountingOutputRange
{
private:
size_t _count;
public:
size_t count() { return _count; }
void put(char c) { _count++; }
}
char[] sanitize(string value, IAllocator alloc)
{
import std.format : formattedWrite, sformat;
CountingOutputRange r;
(&r).formattedWrite!"'%s'"(value); // do not copy the range
auto s = alloc.makeArray!char(r.count);
scope (failure) alloc.dispose(s);
// This should only throw if the user provided allocator
returned less
// memory than was requested
return s.sformat!"'%s'"(value);
}
void main()
{
auto s = sanitize("foo", theAllocator);
scope (exit) theAllocator.dispose(s);
writeln(s);
}
--------------
More information about the Digitalmars-d-learn
mailing list