Output range with custom string type

Jacob Carlborg via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Aug 29 23:38:27 PDT 2017


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


More information about the Digitalmars-d-learn mailing list