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 | |
13 | template <typename ELEMENT, BOOL BITWISE_COPY> |
14 | inline SArray<ELEMENT, BITWISE_COPY>::SArray() |
15 | : m_buffer() |
16 | { |
17 | LIMITED_METHOD_CONTRACT; |
18 | } |
19 | |
20 | template <typename ELEMENT, BOOL BITWISE_COPY> |
21 | inline 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 | |
28 | template <typename ELEMENT, BOOL BITWISE_COPY> |
29 | inline 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 | |
43 | template <typename ELEMENT, BOOL BITWISE_COPY> |
44 | inline 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 | |
52 | template <typename ELEMENT, BOOL BITWISE_COPY> |
53 | inline 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 | |
59 | template <typename ELEMENT, BOOL BITWISE_COPY> |
60 | SArray<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 | |
81 | template <typename ELEMENT, BOOL BITWISE_COPY> |
82 | inline void SArray<ELEMENT, BITWISE_COPY>::Clear() |
83 | { |
84 | WRAPPER_NO_CONTRACT; |
85 | DestructBuffer(Begin(), GetCount()); |
86 | m_buffer.Clear(); |
87 | } |
88 | |
89 | template <typename ELEMENT, BOOL BITWISE_COPY> |
90 | inline 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 | |
96 | template <typename ELEMENT, BOOL BITWISE_COPY> |
97 | inline ELEMENT* SArray<ELEMENT, BITWISE_COPY>::OpenRawBuffer() |
98 | { |
99 | WRAPPER_NO_CONTRACT; |
100 | return (ELEMENT*)m_buffer.OpenRawBuffer(GetCount() * sizeof(ELEMENT)); |
101 | } |
102 | |
103 | template <typename ELEMENT, BOOL BITWISE_COPY> |
104 | inline void SArray<ELEMENT, BITWISE_COPY>::CloseRawBuffer(COUNT_T finalElementCount) |
105 | { |
106 | WRAPPER_NO_CONTRACT; |
107 | m_buffer.CloseRawBuffer(finalElementCount * sizeof(ELEMENT)); |
108 | } |
109 | |
110 | template <typename ELEMENT, BOOL BITWISE_COPY> |
111 | inline void SArray<ELEMENT, BITWISE_COPY>::CloseRawBuffer() |
112 | { |
113 | WRAPPER_NO_CONTRACT; |
114 | m_buffer.CloseRawBuffer(); |
115 | } |
116 | |
117 | template <typename ELEMENT, BOOL BITWISE_COPY> |
118 | inline 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 | |
134 | template <typename ELEMENT, BOOL BITWISE_COPY> |
135 | inline COUNT_T SArray<ELEMENT, BITWISE_COPY>::GetCount() const |
136 | { |
137 | WRAPPER_NO_CONTRACT; |
138 | return m_buffer.GetSize()/sizeof(ELEMENT); |
139 | } |
140 | |
141 | template <typename ELEMENT, BOOL BITWISE_COPY> |
142 | inline BOOL SArray<ELEMENT, BITWISE_COPY>::IsEmpty() const |
143 | { |
144 | WRAPPER_NO_CONTRACT; |
145 | return GetCount() == 0; |
146 | } |
147 | |
148 | template <typename ELEMENT, BOOL BITWISE_COPY> |
149 | inline 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 | |
162 | template <typename ELEMENT, BOOL BITWISE_COPY> |
163 | inline COUNT_T SArray<ELEMENT, BITWISE_COPY>::GetAllocation() const |
164 | { |
165 | WRAPPER_NO_CONTRACT; |
166 | return m_buffer.GetAllocation() / sizeof(ELEMENT); |
167 | } |
168 | |
169 | template <typename ELEMENT, BOOL BITWISE_COPY> |
170 | inline void SArray<ELEMENT, BITWISE_COPY>::Preallocate(int count) const |
171 | { |
172 | WRAPPER_NO_CONTRACT; |
173 | m_buffer.Preallocate(count * sizeof(ELEMENT)); |
174 | } |
175 | |
176 | template <typename ELEMENT, BOOL BITWISE_COPY> |
177 | inline void SArray<ELEMENT, BITWISE_COPY>::Trim() const |
178 | { |
179 | WRAPPER_NO_CONTRACT; |
180 | m_buffer.Trim(); |
181 | } |
182 | |
183 | template <typename ELEMENT, BOOL BITWISE_COPY> |
184 | inline 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 | |
194 | template <typename ELEMENT, BOOL BITWISE_COPY> |
195 | inline 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 | |
206 | template <typename ELEMENT, BOOL BITWISE_COPY> |
207 | inline 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 | |
215 | template <typename ELEMENT, BOOL BITWISE_COPY> |
216 | inline 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 | |
224 | template <typename ELEMENT, BOOL BITWISE_COPY> |
225 | inline void SArray<ELEMENT, BITWISE_COPY>::Insert(const Iterator &i) |
226 | { |
227 | WRAPPER_NO_CONTRACT; |
228 | Replace(i, 0, 1); |
229 | } |
230 | |
231 | template <typename ELEMENT, BOOL BITWISE_COPY> |
232 | inline void SArray<ELEMENT, BITWISE_COPY>::Delete(const Iterator &i) |
233 | { |
234 | WRAPPER_NO_CONTRACT; |
235 | Replace(i, 1, 0); |
236 | } |
237 | |
238 | template <typename ELEMENT, BOOL BITWISE_COPY> |
239 | inline void SArray<ELEMENT, BITWISE_COPY>::Insert(const Iterator &i, COUNT_T count) |
240 | { |
241 | WRAPPER_NO_CONTRACT; |
242 | Replace(i, 0, count); |
243 | } |
244 | |
245 | template <typename ELEMENT, BOOL BITWISE_COPY> |
246 | inline void SArray<ELEMENT, BITWISE_COPY>::Delete(const Iterator &i, COUNT_T count) |
247 | { |
248 | Delete(i, 0, count); |
249 | } |
250 | |
251 | template <typename ELEMENT, BOOL BITWISE_COPY> |
252 | inline 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 | |
262 | template <typename ELEMENT, BOOL BITWISE_COPY> |
263 | inline ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](int index) |
264 | { |
265 | WRAPPER_NO_CONTRACT; |
266 | return *(GetElements() + index); |
267 | } |
268 | |
269 | template <typename ELEMENT, BOOL BITWISE_COPY> |
270 | inline const ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](int index) const |
271 | { |
272 | WRAPPER_NO_CONTRACT; |
273 | return *(GetElements() + index); |
274 | } |
275 | |
276 | template <typename ELEMENT, BOOL BITWISE_COPY> |
277 | inline ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](COUNT_T index) |
278 | { |
279 | WRAPPER_NO_CONTRACT; |
280 | return *(GetElements() + index); |
281 | } |
282 | |
283 | template <typename ELEMENT, BOOL BITWISE_COPY> |
284 | inline const ELEMENT &SArray<ELEMENT, BITWISE_COPY>::operator[](COUNT_T index) const |
285 | { |
286 | return *(GetElements() + index); |
287 | } |
288 | |
289 | template <typename ELEMENT, BOOL BITWISE_COPY> |
290 | inline ELEMENT *SArray<ELEMENT, BITWISE_COPY>::GetElements() const |
291 | { |
292 | LIMITED_METHOD_CONTRACT; |
293 | return (ELEMENT *) (const BYTE *) m_buffer; |
294 | } |
295 | |
296 | template <typename ELEMENT, BOOL BITWISE_COPY> |
297 | inline 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 | |
319 | template <typename ELEMENT, BOOL BITWISE_COPY> |
320 | inline 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 | |
346 | template <typename ELEMENT, BOOL BITWISE_COPY> |
347 | inline 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 | |
370 | template <typename ELEMENT, COUNT_T SIZE, BOOL BITWISE_COPY> |
371 | inline 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 | |