On 2017-08-28 23:45, Moritz Maxeiner wrote:

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);
}
--------------

I guess that would work.

But if I keep the range internal, can't I just do the allocation inside the range and only use "formattedWrite"? Instead of using both formattedWrite and sformat and go through the data twice. Then of course the final size is not known before allocating.

--
/Jacob Carlborg

Reply via email to