1 module gfm.core.alignedbuffer;
2 
3 import std.c.string;
4 import gfm.core.memory;
5 
6 /// Growable array, points to a memory aligned location.
7 /// Bugs: make this class disappear when std.allocator is out.
8 final class AlignedBuffer(T)
9 {
10     public
11     {
12         /// Creates an empty aligned buffer.
13         this() nothrow
14         {
15             _size = 0;
16             _allocated = 0;
17             _data = null;
18             _alignment = 64;
19         }
20 
21         /// Creates an aligned buffer with given size.
22         this(size_t initialSize) nothrow
23         {
24             this();
25             resize(initialSize);
26         }
27 
28         /// Creates an aligned buffer by copy.
29         this(AlignedBuffer other)
30         {
31             this();
32             resize(other.length());
33             memcpy(_data, other._data, _size * T.sizeof);
34         }
35 
36         ~this()
37         {
38             close();
39         }
40 
41         void close()
42         {
43             if (_data !is null)
44             {
45                 alignedFree(_data);
46                 _data = null;
47                 _allocated = 0;
48             }
49         }
50 
51         size_t length() pure const nothrow
52         {
53             return _size;
54         }
55 
56         void resize(size_t askedSize) nothrow
57         {
58             // grow only
59             if (_allocated < askedSize)
60             {
61                 size_t numBytes = askedSize * T.sizeof;
62                 _data = cast(T*)(alignedRealloc(_data, numBytes, _alignment));
63                 _allocated = askedSize;
64             }
65             _size = askedSize;
66         }
67 
68         void pushBack(T x) nothrow
69         {
70             size_t i = _size;
71             resize(_size + 1);
72             _data[i] = x;
73         }
74 
75         // push back another buffer
76         void pushBack(AlignedBuffer other) nothrow
77         {
78             size_t oldSize = _size;
79             resize(_size + other._size);
80             memcpy(_data + oldSize, other._data, T.sizeof * other._size);
81         }
82 
83         @property T* ptr() nothrow
84         {
85             return _data;
86         }
87 
88         T opIndex(size_t i) pure nothrow
89         {
90             return _data[i];
91         }
92 
93         T opIndexAssign(T x, size_t i) nothrow
94         {
95             return _data[i] = x;
96         }
97 
98         void clear() nothrow
99         {
100             _size = 0;
101         }
102 
103         void fill(T x)
104         {
105             for (size_t i = 0; i < _size; ++i)
106             {
107                 _data[i] = x;                
108             }
109         }
110     }
111 
112     private
113     {
114         size_t _size;
115         T* _data;
116         size_t _allocated;
117         size_t _alignment;
118     }
119 }
120 
121 unittest
122 {
123     auto buf = new AlignedBuffer!int;
124     enum N = 10;
125     buf.resize(N);
126     foreach(i ; 0..N)
127         buf[i] = i;
128 
129     foreach(i ; 0..N)
130         assert(buf[i] == i);
131 }