1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4// --------------------------------------------------------------------------------
5// SArray.inl
6// --------------------------------------------------------------------------------
7
8#ifndef _SARRAY_INL_
9#define _SARRAY_INL_
10
11#include "sarray.h"
12
13template <typename ELEMENT, BOOL BITWISE_COPY>
14inline SArray<ELEMENT, BITWISE_COPY>::SArray()
15 : m_buffer()
16{
17 LIMITED_METHOD_CONTRACT;
18}
19
20template <typename ELEMENT, BOOL BITWISE_COPY>
21inline SArray<ELEMENT, BITWISE_COPY>::SArray(COUNT_T count)
22 : m_buffer(count * sizeof(ELEMENT))
23{
24 WRAPPER_NO_CONTRACT;
25 ConstructBuffer(Begin(), count);
26}
27
28template <typename ELEMENT, BOOL BITWISE_COPY>
29inline COUNT_T SArray<ELEMENT, BITWISE_COPY>::VerifySizeRange(ELEMENT * begin, ELEMENT *end)
30{
31 WRAPPER_NO_CONTRACT;
32
33 if (end < begin)
34 ThrowHR(COR_E_OVERFLOW);
35
36 SIZE_T bufferSize = (end - begin) * sizeof(ELEMENT);
37 if (!FitsIn<COUNT_T>(bufferSize))
38 ThrowHR(COR_E_OVERFLOW);
39
40 return static_cast<COUNT_T>(bufferSize);
41}
42
43template <typename ELEMENT, BOOL BITWISE_COPY>
44inline SArray<ELEMENT, BITWISE_COPY>::SArray(ELEMENT * begin, ELEMENT * end)
45 : m_buffer(VerifySizeRange(begin, end))
46{
47 WRAPPER_NO_CONTRACT;
48
49 CopyConstructBuffer(Begin(), static_cast<COUNT_T>(end - begin), begin);
50}
51
52template <typename ELEMENT, BOOL BITWISE_COPY>
53inline SArray<ELEMENT, BITWISE_COPY>::SArray(void *prealloc, COUNT_T count)
54 : m_buffer(SBuffer::Prealloc, prealloc, count*sizeof(ELEMENT))
55{
56 LIMITED_METHOD_CONTRACT;
57}
58
59template <typename ELEMENT, BOOL BITWISE_COPY>
60SArray<ELEMENT, BITWISE_COPY>::~SArray()
61{
62 CONTRACTL
63 {
64 NOTHROW;
65 SO_TOLERANT;
66 GC_NOTRIGGER;
67 }
68 CONTRACTL_END;
69
70 // Cannot call Clear because DestructBuffer has THROWS in its contract
71 if (!BITWISE_COPY)
72 {
73 COUNT_T elementCount = GetCount();
74 for (COUNT_T i = 0; i < elementCount; i++)
75 {
76 (&((*this)[i]))->~ELEMENT();
77 }
78 }
79}
80
81template <typename ELEMENT, BOOL BITWISE_COPY>
82inline void SArray<ELEMENT, BITWISE_COPY>::Clear()
83{
84 WRAPPER_NO_CONTRACT;
85 DestructBuffer(Begin(), GetCount());
86 m_buffer.Clear();
87}
88
89template <typename ELEMENT, BOOL BITWISE_COPY>
90inline ELEMENT* SArray<ELEMENT, BITWISE_COPY>::OpenRawBuffer(COUNT_T elementCount)
91{
92 WRAPPER_NO_CONTRACT;
93 return (ELEMENT*)m_buffer.OpenRawBuffer(elementCount * sizeof(ELEMENT));
94}
95
96template <typename ELEMENT, BOOL BITWISE_COPY>
97inline ELEMENT* SArray<ELEMENT, BITWISE_COPY>::OpenRawBuffer()
98{
99 WRAPPER_NO_CONTRACT;
100 return (ELEMENT*)m_buffer.OpenRawBuffer(GetCount() * sizeof(ELEMENT));
101}
102
103template <typename ELEMENT, BOOL BITWISE_COPY>
104inline void SArray<ELEMENT, BITWISE_COPY>::CloseRawBuffer(COUNT_T finalElementCount)
105{
106 WRAPPER_NO_CONTRACT;
107 m_buffer.CloseRawBuffer(finalElementCount * sizeof(ELEMENT));
108}
109
110template <typename ELEMENT, BOOL BITWISE_COPY>
111inline void SArray<ELEMENT, BITWISE_COPY>::CloseRawBuffer()
112{
113 WRAPPER_NO_CONTRACT;
114 m_buffer.CloseRawBuffer();
115}
116
117template <typename ELEMENT, BOOL BITWISE_COPY>
118inline void SArray<ELEMENT, BITWISE_COPY>::Set(const SArray<ELEMENT, BITWISE_COPY> &array)
119{
120 WRAPPER_NO_CONTRACT;
121 if (BITWISE_COPY)
122 {
123 m_buffer.Set(array.m_buffer);
124 }
125 else
126 {
127 DestructBuffer(Begin(), GetCount());
128 m_buffer.SetSize(0);
129 m_buffer.SetSize(array.m_buffer.GetSize());
130 CopyConstructBuffer(Begin(), GetCount(), array.GetElements());
131 }
132}
133
134template <typename ELEMENT, BOOL BITWISE_COPY>
135inline COUNT_T SArray<ELEMENT, BITWISE_COPY>::GetCount() const
136{
137 WRAPPER_NO_CONTRACT;
138 return m_buffer.GetSize()/sizeof(ELEMENT);
139}
140
141template <typename ELEMENT, BOOL BITWISE_COPY>
142inline BOOL SArray<ELEMENT, BITWISE_COPY>::IsEmpty() const
143{
144 WRAPPER_NO_CONTRACT;
145 return GetCount() == 0;
146}
147
148template <typename ELEMENT, BOOL BITWISE_COPY>
149inline void SArray<ELEMENT, BITWISE_COPY>::SetCount(COUNT_T count)
150{
151 WRAPPER_NO_CONTRACT;
152 COUNT_T oldCount = GetCount();
153 if (count > oldCount)
154 ConstructBuffer(Begin() + oldCount, count - oldCount);
155
156 m_buffer.SetSize(count*sizeof(ELEMENT));
157
158 if (oldCount > count)
159 DestructBuffer(Begin() + count, oldCount - count);
160}
161
162template <typename ELEMENT, BOOL BITWISE_COPY>
163inline COUNT_T SArray<ELEMENT, BITWISE_COPY>::GetAllocation() const
164{
165 WRAPPER_NO_CONTRACT;
166 return m_buffer.GetAllocation() / sizeof(ELEMENT);
167}
168
169template <typename ELEMENT, BOOL BITWISE_COPY>
170inline void SArray<ELEMENT, BITWISE_COPY>::Preallocate(int count) const
171{
172 WRAPPER_NO_CONTRACT;
173 m_buffer.Preallocate(count * sizeof(ELEMENT));
174}
175
176template <typename ELEMENT, BOOL BITWISE_COPY>
177inline void SArray<ELEMENT, BITWISE_COPY>::Trim() const
178{
179 WRAPPER_NO_CONTRACT;
180 m_buffer.Trim();
181}
182
183template <typename ELEMENT, BOOL BITWISE_COPY>
184inline void SArray<ELEMENT, BITWISE_COPY>::Copy(const Iterator &to, const Iterator &from, COUNT_T size)
185{
186 WRAPPER_NO_CONTRACT;
187 // @todo: destruction/construction semantics are broken on overlapping copies
188
189 DestructBuffer(to, size);
190
191 CopyConstructBuffer(to, size, from);
192}
193
194template <typename ELEMENT, BOOL BITWISE_COPY>
195inline void SArray<ELEMENT, BITWISE_COPY>::Move(const Iterator &to, const Iterator &from, COUNT_T size)
196{
197 // @todo: destruction/construction semantics are broken on overlapping moves
198
199 DestructBuffer(to, size);
200
201 m_buffer.Move(to, from, size*sizeof(ELEMENT));
202
203 ConstructBuffer(from, size);
204}
205
206template <typename ELEMENT, BOOL BITWISE_COPY>
207inline void SArray<ELEMENT, BITWISE_COPY>::Copy(const Iterator &i, const ELEMENT *source, COUNT_T size)
208{
209 WRAPPER_NO_CONTRACT;
210 DestructBuffer(i, size);
211
212 CopyConstructBuffer(i, size, source);
213}
214
215template <typename ELEMENT, BOOL BITWISE_COPY>
216inline void SArray<ELEMENT, BITWISE_COPY>::Copy(void *dest, const Iterator &i, COUNT_T size)
217{
218 WRAPPER_NO_CONTRACT;
219 // @todo: destruction/construction semantics are unclear
220
221 m_buffer.Copy(dest, i.m_i, size*sizeof(ELEMENT));
222}
223
224template <typename ELEMENT, BOOL BITWISE_COPY>
225inline void SArray<ELEMENT, BITWISE_COPY>::Insert(const Iterator &i)
226{
227 WRAPPER_NO_CONTRACT;
228 Replace(i, 0, 1);
229}
230
231template <typename ELEMENT, BOOL BITWISE_COPY>
232inline void SArray<ELEMENT, BITWISE_COPY>::Delete(const Iterator &i)
233{
234 WRAPPER_NO_CONTRACT;
235 Replace(i, 1, 0);
236}
237
238template <typename ELEMENT, BOOL BITWISE_COPY>
239inline void SArray<ELEMENT, BITWISE_COPY>::Insert(const Iterator &i, COUNT_T count)
240{
241 WRAPPER_NO_CONTRACT;
242 Replace(i, 0, count);
243}
244
245template <typename ELEMENT, BOOL BITWISE_COPY>
246inline void SArray<ELEMENT, BITWISE_COPY>::Delete(const Iterator &i, COUNT_T count)
247{
248 Delete(i, 0, count);
249}
250
251template <typename ELEMENT, BOOL BITWISE_COPY>
252inline void SArray<ELEMENT, BITWISE_COPY>:: Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount)
253{
254 WRAPPER_NO_CONTRACT;
255 DestructBuffer(i, deleteCount);
256
257 m_buffer.Replace(i.m_i, deleteCount*sizeof(ELEMENT), insertCount*sizeof(ELEMENT));
258
259 ConstructBuffer(i, insertCount);
260}
261
262template <typename ELEMENT, BOOL BITWISE_COPY>
263inline ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](int index)
264{
265 WRAPPER_NO_CONTRACT;
266 return *(GetElements() + index);
267}
268
269template <typename ELEMENT, BOOL BITWISE_COPY>
270inline const ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](int index) const
271{
272 WRAPPER_NO_CONTRACT;
273 return *(GetElements() + index);
274}
275
276template <typename ELEMENT, BOOL BITWISE_COPY>
277inline ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](COUNT_T index)
278{
279 WRAPPER_NO_CONTRACT;
280 return *(GetElements() + index);
281}
282
283template <typename ELEMENT, BOOL BITWISE_COPY>
284inline const ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](COUNT_T index) const
285{
286 return *(GetElements() + index);
287}
288
289template <typename ELEMENT, BOOL BITWISE_COPY>
290inline ELEMENT *SArray<ELEMENT, BITWISE_COPY>::GetElements() const
291{
292 LIMITED_METHOD_CONTRACT;
293 return (ELEMENT *) (const BYTE *) m_buffer;
294}
295
296template <typename ELEMENT, BOOL BITWISE_COPY>
297inline void SArray<ELEMENT, BITWISE_COPY>::ConstructBuffer(const Iterator &i, COUNT_T size)
298{
299 CONTRACTL
300 {
301 THROWS;
302 GC_NOTRIGGER;
303 }
304 CONTRACTL_END;
305
306 if (!BITWISE_COPY)
307 {
308 ELEMENT *start = GetElements() + (i - Begin());
309 ELEMENT *end = start + size;
310
311 while (start < end)
312 {
313 new (start) ELEMENT();
314 start++;
315 }
316 }
317}
318
319template <typename ELEMENT, BOOL BITWISE_COPY>
320inline void SArray<ELEMENT, BITWISE_COPY>::CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from)
321{
322 ptrdiff_t start_offset = i - Begin();
323 ELEMENT *p = (ELEMENT *) m_buffer.OpenRawBuffer(m_buffer.GetSize()) + start_offset;
324
325 if (BITWISE_COPY)
326 {
327 memmove(p, from, size * sizeof(ELEMENT));
328 }
329 else
330 {
331 ELEMENT *start = (ELEMENT *) p;
332 ELEMENT *end = (ELEMENT *) (p + size);
333
334 while (start < end)
335 {
336 new (start) ELEMENT(*from);
337
338 start++;
339 from++;
340 }
341 }
342
343 m_buffer.CloseRawBuffer();
344}
345
346template <typename ELEMENT, BOOL BITWISE_COPY>
347inline void SArray<ELEMENT, BITWISE_COPY>::DestructBuffer(const Iterator &i, COUNT_T size)
348{
349 CONTRACTL
350 {
351 THROWS;
352 GC_NOTRIGGER;
353 }
354 CONTRACTL_END;
355
356 if (!BITWISE_COPY)
357 {
358 ELEMENT *start = GetElements() + (i - Begin());
359 ELEMENT *end = start + size;
360
361 while (start < end)
362 {
363 start->ELEMENT::~ELEMENT();
364
365 start++;
366 }
367 }
368}
369
370template <typename ELEMENT, COUNT_T SIZE, BOOL BITWISE_COPY>
371inline InlineSArray<ELEMENT, SIZE, BITWISE_COPY>::InlineSArray()
372 : SArray<ELEMENT, BITWISE_COPY>((void*)m_prealloc, SIZE)
373{
374 LIMITED_METHOD_CONTRACT;
375}
376
377#endif // _SARRAY_INL_
378