Is it possible to append to a local buffer without reallocating?

tipdbmp email at example.com
Thu Jan 11 13:51:03 UTC 2018


> Have you checked what push_stuff actually returns with those 
> inputs?
Right, we get [0xFF, 0xFF, 'A'] and [0xFF, 0xFF].

I think the following is a pretty easy workaround though:

alias usize = size_t;

struct Push_Buf(T, usize stack_size) {
     T[stack_size] stack_buf;
     T[] heap_buf;
     usize p = 0;

     void opOpAssign(string op)(T e) if (op == "~") {
         if (p < stack_size) {
             stack_buf[p] = e;
             p += 1;
         }
         else {
             if (p == stack_size) {
                 heap_buf = stack_buf.dup();
                 p += 1;
             }
             heap_buf ~= e;
         }
     }

     void opOpAssign(string op)(immutable(T)[] es) if (op == "~") {
         if (p + es.length <= stack_size) {
             import core.stdc.string : memcpy;
             memcpy(&stack_buf[p], es.ptr, es.length);
             p += es.length;
         }
         else {
             if (p < stack_size) {
                 heap_buf = stack_buf[0 .. p].dup();
                 p += es.length;
             }
             heap_buf ~= es;
         }
     }

     U opCast(U: T[])() { return as_slice(); }
     U opCast(U: immutable(T)[])() { return cast(immutable(T)[]) 
as_slice(); }

     @property T[] as_slice() {
         if (p <= stack_size) { return stack_buf[0 .. p]; }
         else return heap_buf;
     }

     alias as_slice this;
}

string push_stuff(usize buf_size)(ref Push_Buf!(char, buf_size) 
buf, int x) {
     if (x == 1) {
         buf ~= 'A';
         buf ~= 'B';
         buf ~= 'C';
     }
     else {
         buf ~= 'A';
         buf ~= 'B';
     }
     return cast(string) buf;
}

void foo() {
     {
         Push_Buf!(char, 2) buf;
         string result = push_stuff(buf, 1);
         assert(buf.heap_buf.ptr == result.ptr);
     }
     {
         Push_Buf!(char, 2) buf;
         string result = push_stuff(buf, 0);
         assert(buf.stack_buf.ptr == result.ptr);
     }
}



More information about the Digitalmars-d-learn mailing list