1 module more.alloc;
2 
3 static import core.stdc.stdlib;
4 static import core.stdc..string;
5 
6 import std.typecons : Flag, Yes, No;
7 
8 T* cmalloc(T)(Flag!"zero" zero = Yes.zero)
9 {
10     void* mem = core.stdc.stdlib.malloc(T.sizeof);
11     assert(mem, "out of memory");
12     if(zero)
13     {
14         core.stdc..string.memset(mem, 0, T.sizeof);
15     }
16     return cast(T*)mem;
17 }
18 T[] cmallocArray(T)(size_t size, Flag!"zero" zero = Yes.zero)
19 {
20     void* mem = core.stdc.stdlib.malloc(T.sizeof * size);
21     assert(mem, "out of memory");
22     if(zero)
23     {
24         core.stdc..string.memset(mem, 0, T.sizeof * size);
25     }
26     return (cast(T*)mem)[0..size];
27 }
28 void cfree(T)(T* mem)
29 {
30     core.stdc.stdlib.free(mem);
31 }
32 
33 struct Mem
34 {
35     void* ptr;
36     size_t size;
37 }
38 
39 // Always expands the memory to a power of 2 of the initial size.
40 struct GCDoubler(uint initialSize)
41 {
42     private static auto getSize(size_t currentSize, size_t requestedSize)
43     {
44         size_t size = (currentSize == 0) ? initialSize : currentSize * 2;
45         while(requestedSize > size)
46         {
47             size *= 2;
48         }
49         return size;
50     }
51 
52     static T[] expand(T)(T[] array, size_t preserveSize, size_t neededSize)
53         in { assert(array.length < neededSize); } body
54     {
55         // TODO: there might be a more efficient way to do this?
56         array.length = getSize(array.length, neededSize);
57         return array;
58     }
59 
60     static Mem alloc(Mem current, size_t newRequestedSize)
61     {
62         import core.memory : GC;
63         auto newSize = getSize(current.size, newRequestedSize);
64         return Mem(GC.malloc(newSize), newSize);
65     }
66     static Mem alloc(Mem current, size_t newRequestedSize, size_t copyOffset, size_t copyLimit)
67     {
68         import core.memory : GC;
69         auto newSize = getSize(current.size, newRequestedSize);
70         auto newMem = GC.malloc(newSize);
71         (cast(ubyte*)newMem)[copyOffset..copyLimit] = (cast(ubyte*)current.ptr)[copyOffset..copyLimit];
72         return Mem(newMem, newSize);
73     }
74 }
75 
76 struct MallocDoubler(uint initialSize)
77 {
78     static import core.stdc.stdlib;
79     static import core.stdc..string;
80 
81     static T[] expand(T)(T[] array, size_t preserveSize, size_t neededSize)
82         in { assert(array.length < neededSize); } body
83     {
84         size_t newSize = (array.length == 0) ? initialSize : array.length * 2;
85         while(neededSize > newSize)
86         {
87             newSize *= 2;
88         }
89         auto newPtr = cast(T*)core.stdc.stdlib.malloc(T.sizeof*newSize);
90         assert(newPtr, "malloc returned null");
91         if(preserveSize > 0)
92         {
93             core.stdc..string.memcpy(newPtr, array.ptr, T.sizeof*preserveSize);
94         }
95         if(array.ptr)
96         {
97             core.stdc.stdlib.free(array.ptr);
98         }
99         return newPtr[0..newSize];
100     }
101 }