1 /*
2 Copyright (c) 2015 Timur Gafarov 
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 
6 Permission is hereby granted, free of charge, to any person or organization
7 obtaining a copy of the software and accompanying documentation covered by
8 this license (the "Software") to use, reproduce, display, distribute,
9 execute, and transmit the Software, and to prepare derivative works of the
10 Software, and to permit third-parties to whom the Software is furnished to
11 do so, all subject to the following:
12 
13 The copyright notices in the Software and this entire statement, including
14 the above license grant, this restriction and the following disclaimer,
15 must be included in all copies of the Software, in whole or in part, and
16 all derivative works of the Software, unless such copies or derivative
17 works are solely in the form of machine-executable object code generated by
18 a source language processor.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 DEALINGS IN THE SOFTWARE.
27 */
28 
29 // dimage is actually stripped out part of dlib - just to support reading PNG and JPEG
30 module dimage.array; //dlib.container.array
31 
32 import dimage.memory;
33 
34 /*
35  * GC-free dynamic array implementation.
36  * Very efficient for small-sized arrays.
37  */
38 
39 struct DynamicArray(T, size_t chunkSize = 32)
40 {
41     T[chunkSize] staticStorage;
42     T[] dynamicStorage;
43     uint numChunks = 0;
44     uint pos = 0;
45 
46     T* storage()
47     {
48         if (numChunks == 0)
49             return staticStorage.ptr;
50         else
51             return dynamicStorage.ptr;
52     }
53 
54     void addChunk()
55     {
56         if (numChunks == 0)
57         {
58             dynamicStorage = New!(T[])(chunkSize);
59         }
60         else
61         {
62             reallocateArray(
63                 dynamicStorage, 
64                 dynamicStorage.length + chunkSize);
65         }
66         numChunks++;
67     }
68 
69     void shiftRight()
70     {
71         append(T.init);
72 
73         for(uint i = pos-1; i > 0; i--)
74         {
75             storage[i] = storage[i-1];
76         }
77     }
78 
79     void shiftLeft(uint n)
80     {
81         for(uint i = 0; i < pos; i++)
82         {
83             if (n + i < pos)
84                 storage[i] = storage[n + i];
85             else
86                 storage[i] = T.init;
87         }
88     }
89 
90     void append(T c)
91     {
92         if (numChunks == 0)
93         {
94             staticStorage[pos] = c;
95             pos++;
96             if (pos == chunkSize)
97             {
98                 addChunk();
99                 foreach(i, ref v; dynamicStorage)
100                     v = staticStorage[i];
101             }
102         }
103         else
104         {
105             if (pos == dynamicStorage.length)
106                 addChunk(); 
107 
108             dynamicStorage[pos] = c;
109             pos++;          
110         }
111     }
112 
113     void appendLeft(T c)
114     {
115         shiftRight();
116         storage[0] = c;
117     }
118 
119     void append(const(T)[] s)
120     {
121         foreach(c; s)
122             append(cast(T)c);
123     }
124 
125     void appendLeft(const(T)[] s)
126     {
127         foreach(c; s)
128             appendLeft(cast(T)c);
129     }
130 
131     auto opCatAssign(T c)
132     {
133         append(c);
134         return this;
135     }
136 
137     auto opCatAssign(const(T)[] s)
138     {
139         append(s);
140         return this;
141     }
142 
143     uint remove(uint n)
144     {
145         if (pos == n)
146         {
147             pos = 0;
148             return n;
149         }
150         else if (pos >= n)
151         {
152             pos -= n;
153             return n;
154         }
155         else 
156         {
157             n = pos;
158             pos = 0;
159             return n;
160         }   
161     }
162 
163     uint removeLeft(uint n)
164     {
165         if (pos == n)
166         {
167             pos = 0;
168             return n;
169         }
170         else if (pos > n)
171         {
172             shiftLeft(n);
173             pos -= n;
174             return n;
175         }
176         else
177         {
178             n = pos;
179             pos = 0;
180             return n;
181         }
182     }
183 
184     size_t length()
185     {
186         return pos;
187     }
188 
189     T[] data()
190     {
191         return storage[0..pos];
192     }
193 
194     T opIndex(size_t index)
195     {
196         return data[index];
197     }
198 
199     T opIndexAssign(T t, size_t index)
200     {
201         data[index] = t;
202         return t;
203     }
204 
205     int opApply(int delegate(size_t i, ref T) dg)
206     {
207         foreach(i, ref v; data)
208         {
209             dg(i, v);
210         }
211 
212         return 0;
213     }
214 
215     int opApply(int delegate(ref T) dg)
216     {
217         foreach(i, ref v; data)
218         {
219             dg(v);
220         }
221 
222         return 0;
223     }
224 
225     void free()
226     {
227         if (dynamicStorage.length)
228             Delete(dynamicStorage);
229         numChunks = 0;
230         pos = 0;
231     }
232 }
233 
234 void reallocateArray(T)(ref T[] buffer, size_t len)
235 {
236     T[] buffer2 = New!(T[])(len);
237     for(uint i = 0; i < buffer2.length; i++)
238         if (i < buffer.length)
239             buffer2[i] = buffer[i];
240     Delete(buffer);
241     buffer = buffer2;
242 }
243