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.h |
6 | // -------------------------------------------------------------------------------- |
7 | |
8 | |
9 | #ifndef _SARRAY_H_ |
10 | #define _SARRAY_H_ |
11 | |
12 | #include "sbuffer.h" |
13 | |
14 | // -------------------------------------------------------------------------------- |
15 | // SArray is a typed array wrapper around an SBuffer. It manages individual |
16 | // constructors and destructors of array elements if avaiable, as well as providing |
17 | // typed access. |
18 | // -------------------------------------------------------------------------------- |
19 | |
20 | template <typename ELEMENT, BOOL BITWISE_COPY = TRUE> |
21 | class SArray |
22 | { |
23 | private: |
24 | |
25 | SBuffer m_buffer; |
26 | |
27 | static COUNT_T VerifySizeRange(ELEMENT * begin, ELEMENT * end); |
28 | |
29 | public: |
30 | |
31 | class Iterator; |
32 | friend class Iterator; |
33 | |
34 | SArray(); |
35 | SArray(COUNT_T count); |
36 | SArray(ELEMENT * begin, ELEMENT * end); |
37 | ~SArray(); |
38 | |
39 | void Clear(); |
40 | void Set(const SArray<ELEMENT, BITWISE_COPY> &array); |
41 | |
42 | COUNT_T GetCount() const; |
43 | BOOL IsEmpty() const; |
44 | |
45 | void SetCount(COUNT_T count); |
46 | |
47 | COUNT_T GetAllocation() const; |
48 | |
49 | void Preallocate(int count) const; |
50 | void Trim() const; |
51 | |
52 | void Copy(const Iterator &to, const Iterator &from, COUNT_T size); |
53 | void Move(const Iterator &to, const Iterator &from, COUNT_T size); |
54 | |
55 | void Copy(const Iterator &i, const ELEMENT *source, COUNT_T size); |
56 | void Copy(void *dest, const Iterator &i, COUNT_T size); |
57 | |
58 | Iterator Append() |
59 | { |
60 | WRAPPER_NO_CONTRACT; |
61 | |
62 | COUNT_T count = GetCount(); |
63 | if ( GetAllocation() == count ) |
64 | Preallocate( 2 * count ); |
65 | |
66 | Iterator i = End(); |
67 | Insert(i); |
68 | return i; |
69 | } |
70 | |
71 | void Append(ELEMENT elem) |
72 | { |
73 | WRAPPER_NO_CONTRACT; |
74 | *Append() = elem; |
75 | } |
76 | |
77 | ELEMENT AppendEx(ELEMENT elem) |
78 | { |
79 | WRAPPER_NO_CONTRACT; |
80 | |
81 | *Append() = elem; |
82 | return elem; |
83 | } |
84 | |
85 | void Insert(const Iterator &i); |
86 | void Delete(const Iterator &i); |
87 | |
88 | void Insert(const Iterator &i, COUNT_T count); |
89 | void Delete(const Iterator &i, COUNT_T count); |
90 | |
91 | void Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount); |
92 | |
93 | ELEMENT *OpenRawBuffer(COUNT_T maxElementCount); |
94 | ELEMENT *OpenRawBuffer(); |
95 | void CloseRawBuffer(COUNT_T actualElementCount); |
96 | void CloseRawBuffer(); |
97 | |
98 | Iterator Begin() |
99 | { |
100 | WRAPPER_NO_CONTRACT; |
101 | return Iterator(this, 0); |
102 | } |
103 | |
104 | Iterator End() |
105 | { |
106 | WRAPPER_NO_CONTRACT; |
107 | return Iterator(this, GetCount()); |
108 | } |
109 | |
110 | Iterator operator+(COUNT_T index) |
111 | { |
112 | return Iterator(this, index); |
113 | } |
114 | |
115 | ELEMENT & operator[] (int index); |
116 | const ELEMENT & operator[] (int index) const; |
117 | |
118 | ELEMENT & operator[] (COUNT_T index); |
119 | const ELEMENT & operator[] (COUNT_T index) const; |
120 | |
121 | protected: |
122 | SArray(void *prealloc, COUNT_T size); |
123 | |
124 | public: |
125 | |
126 | class Iterator : public CheckedIteratorBase<SArray<ELEMENT, BITWISE_COPY> >, |
127 | public Indexer<ELEMENT, Iterator> |
128 | { |
129 | friend class SArray; |
130 | friend class Indexer<ELEMENT, Iterator>; |
131 | |
132 | SBuffer::Iterator m_i; |
133 | |
134 | public: |
135 | |
136 | Iterator(SArray *array, SCOUNT_T index) |
137 | : CheckedIteratorBase<SArray<ELEMENT, BITWISE_COPY> >(array) |
138 | { |
139 | WRAPPER_NO_CONTRACT; |
140 | m_i = array->m_buffer.Begin() + index*sizeof(ELEMENT); |
141 | } |
142 | |
143 | protected: |
144 | |
145 | ELEMENT &GetAt(SCOUNT_T delta) const |
146 | { |
147 | LIMITED_METHOD_CONTRACT; |
148 | return * (ELEMENT *) &m_i[delta*sizeof(ELEMENT)]; |
149 | } |
150 | |
151 | void Skip(SCOUNT_T delta) |
152 | { |
153 | LIMITED_METHOD_CONTRACT; |
154 | m_i += delta*sizeof(ELEMENT); |
155 | } |
156 | |
157 | COUNT_T Subtract(const Iterator &i) const |
158 | { |
159 | LIMITED_METHOD_CONTRACT; |
160 | return (m_i - i.m_i)/sizeof(ELEMENT); |
161 | } |
162 | |
163 | CHECK DoCheck(SCOUNT_T delta) const |
164 | { |
165 | WRAPPER_NO_CONTRACT; |
166 | return m_i.CheckIndex(delta*sizeof(ELEMENT)); |
167 | } |
168 | |
169 | public: |
170 | |
171 | CHECK Check() const |
172 | { |
173 | WRAPPER_NO_CONTRACT; |
174 | return m_i.Check(); |
175 | } |
176 | }; |
177 | |
178 | ELEMENT *GetElements() const; |
179 | |
180 | private: |
181 | |
182 | //-------------------------------------------------------------------- |
183 | // Routines for managing the buffer content. |
184 | //-------------------------------------------------------------------- |
185 | |
186 | void ConstructBuffer(const Iterator &i, COUNT_T size); |
187 | void CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from); |
188 | void DestructBuffer(const Iterator &i, COUNT_T size); |
189 | }; |
190 | |
191 | // ================================================================================ |
192 | // InlineSArray : Tempate for an SArray with preallocated element space |
193 | // ================================================================================ |
194 | |
195 | template <typename ELEMENT, COUNT_T SIZE, BOOL BITWISE_COPY = TRUE> |
196 | class InlineSArray : public SArray<ELEMENT, BITWISE_COPY> |
197 | { |
198 | private: |
199 | #ifdef _MSC_VER |
200 | #pragma warning(push) |
201 | #pragma warning(disable:4200) // zero sized array |
202 | #pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads |
203 | DECLSPEC_ALIGN(BUFFER_ALIGNMENT) BYTE m_prealloc[SIZE*sizeof(ELEMENT)]; |
204 | #pragma warning(pop) |
205 | #else |
206 | // use UINT64 to get maximum alignment of the memory |
207 | UINT64 m_prealloc[ALIGN(SIZE*sizeof(ELEMENT),sizeof(UINT64))/sizeof(UINT64)]; |
208 | #endif // _MSC_VER |
209 | |
210 | public: |
211 | InlineSArray(); |
212 | }; |
213 | |
214 | // ================================================================================ |
215 | // StackSArray : SArray with relatively large preallocated buffer for stack use |
216 | // ================================================================================ |
217 | |
218 | template <typename ELEMENT, BOOL BITWISE_COPY = TRUE> |
219 | class StackSArray : public InlineSArray<ELEMENT, STACK_ALLOC/sizeof(ELEMENT), BITWISE_COPY> |
220 | { |
221 | }; |
222 | |
223 | // ================================================================================ |
224 | // Inline definitions |
225 | // ================================================================================ |
226 | |
227 | #include "sarray.inl" |
228 | |
229 | #endif // _SARRAY_H_ |
230 | |