1 module musicpulator.core;
2 
3 /// A collection that can maximum contain a specific amount of items.
4 struct MaxSizeCollection(T, size_t initMaxSize = 0)
5 {
6   private:
7   /// The collection.
8   T[] _collection;
9   /// The current index.
10   size_t _current;
11   /// The max size.
12   size_t _maxSize = initMaxSize;
13 
14   public:
15   static if (!initMaxSize)
16   {
17     /**
18     * Creates a new max size collection.
19     * Params:
20     *   maxSize = The maximum size of the collection.
21     */
22     this(size_t maxSize)
23     {
24       _maxSize = maxSize;
25     }
26   }
27 
28   @property
29   {
30     /// Gets the maximum size of the collection.
31     size_t maxSize() { return _maxSize; }
32 
33     /// Gets the length of the collection.
34     size_t length() { return _collection ? _collection.length : 0; }
35   }
36 
37   /**
38   * Adds an item to the collection.
39   * Params:
40   *   item = The item to add.
41   */
42   void add(T item)
43   {
44     if (_collection && _collection.length == _maxSize)
45     {
46       return;
47     }
48 
49     _collection ~= item;
50   }
51 
52   /// Clears the collection.
53   void clear()
54   {
55     _collection = null;
56   }
57 
58   // Range Implementation:
59   @property
60   {
61     T front()
62     {
63       if (!_collection)
64       {
65         return T.init;
66       }
67 
68       return _collection[_current];
69     }
70 
71     bool empty()
72     {
73       return !_collection || !_collection.length || _current >= _collection.length;
74     }
75   }
76 
77   void popFront()
78   {
79     _current++;
80   }
81 
82   T opIndex(size_t index)
83   {
84     return _collection[index];
85   }
86 
87   void opIndexAssign(T item, size_t index)
88   {
89     if (index >= _maxSize)
90     {
91       return;
92     }
93 
94     if (_collection.length < index)
95     {
96       _collection.length = index;
97     }
98 
99     _collection[index] = item;
100   }
101 
102   T[] array()
103   {
104     return _collection;
105   }
106 }
107 
108 /// A collection that can only be modified within the package.
109 struct InternalCollection(T)
110 {
111   private:
112   /// The collection.
113   T[] _collection;
114   /// The current index.
115   size_t _current;
116 
117   public:
118   @property
119   {
120     /// Gets the length of the collection.
121     size_t length() { return _collection ? _collection.length : 0; }
122   }
123 
124   package(musicpulator)
125   {
126     /**
127     * Adds an item to the collection.
128     * Params:
129     *   item = The item to add.
130     */
131     void add(T item)
132     {
133       _collection ~= item;
134     }
135 
136     /// Clears the collection.
137     void clear()
138     {
139       _collection = null;
140     }
141   }
142 
143   // Range Implementation:
144   @property
145   {
146     T front()
147     {
148       if (!_collection)
149       {
150         return T.init;
151       }
152 
153       return _collection[_current];
154     }
155 
156     bool empty()
157     {
158       return !_collection || !_collection.length || _current >= _collection.length;
159     }
160   }
161 
162   void popFront()
163   {
164     _current++;
165   }
166 
167   T opIndex(size_t index)
168   {
169     return _collection[index];
170   }
171 
172   void opIndexAssign(T item, size_t index)
173   {
174     _collection[index] = item;
175   }
176 
177   T[] array()
178   {
179     return _collection;
180   }
181 }
182 
183 /// A collection that can maximum contain a specific amount of items and can only be modified internally in the package.
184 struct InternalMaxSizeCollection(T, size_t initMaxSize = 0)
185 {
186   private:
187   /// The collection.
188   T[] _collection;
189   /// The current index.
190   size_t _current;
191   /// The max size.
192   size_t _maxSize = initMaxSize;
193 
194   public:
195   static if (!initMaxSize)
196   {
197     /**
198     * Creates a new max size collection.
199     * Params:
200     *   maxSize = The maximum size of the collection.
201     */
202     this(size_t maxSize)
203     {
204       _maxSize = maxSize;
205     }
206   }
207 
208   @property
209   {
210     /// Gets the maximum size of the collection.
211     size_t maxSize() { return _maxSize; }
212 
213     /// Gets the length of the collection.
214     size_t length() { return _collection ? _collection.length : 0; }
215   }
216 
217   package(musicpulator)
218   {
219     /**
220     * Adds an item to the collection.
221     * Params:
222     *   item = The item to add.
223     */
224     void add(T item)
225     {
226       if (_collection && _collection.length == _maxSize)
227       {
228         return;
229       }
230 
231       _collection ~= item;
232     }
233 
234     /// Clears the collection.
235     void clear()
236     {
237       _collection = null;
238     }
239   }
240 
241   /// Clears the collection.
242   void clear()
243   {
244     _collection = null;
245   }
246 
247   // Range Implementation:
248   @property
249   {
250     T front()
251     {
252       if (!_collection)
253       {
254         return T.init;
255       }
256 
257       return _collection[_current];
258     }
259 
260     bool empty()
261     {
262       return !_collection || !_collection.length || _current >= _collection.length;
263     }
264   }
265 
266   void popFront()
267   {
268     _current++;
269   }
270 
271   T opIndex(size_t index)
272   {
273     return _collection[index];
274   }
275 
276   void opIndexAssign(T item, size_t index)
277   {
278     if (index >= _maxSize)
279     {
280       return;
281     }
282 
283     if (_collection.length < index)
284     {
285       _collection.length = index;
286     }
287 
288     _collection[index] = item;
289   }
290 
291   T[] array()
292   {
293     return _collection;
294   }
295 }