On 2017-08-29 19:35, Moritz Maxeiner wrote:
On Tuesday, 29 August 2017 at 09:59:30 UTC, Jacob Carlborg wrote:
[...]

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.

Certainly, that's what dynamic arrays (aka vectors, e.g. std::vector in C++ STL) are for:

---
import core.exception;

import std.stdio;
import std.experimental.allocator;
import std.algorithm;

struct PoorMansVector(T)
{
private:
     T[]        store;
     size_t     length;
     IAllocator alloc;
public:
     @disable this(this);
     this(IAllocator alloc)
     {
         this.alloc = alloc;
     }
     ~this()
     {
         if (store)
         {
             alloc.dispose(store);
             store = null;
         }
     }
     void put(T t)
     {
         if (!store)
         {
             // Allocate only once for "small" vectors
             store = alloc.makeArray!T(8);
             if (!store) onOutOfMemoryError();
         }
         else if (length == store.length)
         {
             // Growth factor of 1.5
            auto expanded = alloc.expandArray!char(store, store.length / 2);
             if (!expanded) onOutOfMemoryError();
         }
         assert (length < store.length);
         moveEmplace(t, store[length++]);
     }
     char[] release()
     {
         auto elements = store[0..length];
         store = null;
         return elements;
     }
}

char[] sanitize(string value, IAllocator alloc)
{
     import std.format : formattedWrite, sformat;

     auto r = PoorMansVector!char(alloc);
     (&r).formattedWrite!"'%s'"(value); // do not copy the range
     return r.release();
}

void main()
{
     auto s = sanitize("foo", theAllocator);
     scope (exit) theAllocator.dispose(s);
     writeln(s);
}
---

Do be aware that the above vector is named "poor man's vector" for a reason, that's a hasty write down from memory and is sure to contain bugs. For better vector implementations you can use at collection libraries such as EMSI containers; my own attempt at a DbI vector container can be found here [1]

[1] https://github.com/Calrama/libds/blob/6a1fc347e1f742b8f67513e25a9fdbf79f007417/src/ds/vector.d

Thanks.

--
/Jacob Carlborg

Reply via email to