summaryrefslogtreecommitdiff
path: root/src/inc/sarray.h
blob: ac361cf401f176f7792a2d3ae4130f27b3c15c6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// --------------------------------------------------------------------------------
// SArray.h
// --------------------------------------------------------------------------------


#ifndef _SARRAY_H_
#define _SARRAY_H_

#include "sbuffer.h"

// --------------------------------------------------------------------------------
// SArray is a typed array wrapper around an SBuffer.  It manages individual 
// constructors and destructors of array elements if avaiable, as well as providing
// typed access.
// --------------------------------------------------------------------------------

template <typename ELEMENT, BOOL BITWISE_COPY = TRUE>
class SArray 
{
  private:

    SBuffer m_buffer;

    static COUNT_T VerifySizeRange(ELEMENT * begin, ELEMENT * end);

  public:

    class Iterator;
    friend class Iterator;

    SArray();
    SArray(COUNT_T count);
    SArray(ELEMENT * begin, ELEMENT * end);
    ~SArray();

    void Clear();
    void Set(const SArray<ELEMENT, BITWISE_COPY> &array);

    COUNT_T GetCount() const;
    BOOL IsEmpty() const;

    void SetCount(COUNT_T count);

    COUNT_T GetAllocation() const;

    void Preallocate(int count) const;
    void Trim() const;

    void Copy(const Iterator &to, const Iterator &from, COUNT_T size);
    void Move(const Iterator &to, const Iterator &from, COUNT_T size);

    void Copy(const Iterator &i, const ELEMENT *source, COUNT_T size);
    void Copy(void *dest, const Iterator &i, COUNT_T size);

    Iterator Append()
    {
        WRAPPER_NO_CONTRACT;

        COUNT_T count = GetCount();
        if ( GetAllocation() == count )
            Preallocate( 2 * count );

        Iterator i = End();
        Insert(i);
        return i;
    }

    void Append(ELEMENT elem)
    {
        WRAPPER_NO_CONTRACT;
        *Append() = elem;
    }

    ELEMENT AppendEx(ELEMENT elem)
    {
        WRAPPER_NO_CONTRACT;

        *Append() = elem;
        return elem;
    }
    
    void Insert(const Iterator &i);
    void Delete(const Iterator &i);

    void Insert(const Iterator &i, COUNT_T count);
    void Delete(const Iterator &i, COUNT_T count);

    void Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount);

    ELEMENT *OpenRawBuffer(COUNT_T maxElementCount);
    ELEMENT *OpenRawBuffer();
    void CloseRawBuffer(COUNT_T actualElementCount);
    void CloseRawBuffer();

    Iterator Begin()
    {
        WRAPPER_NO_CONTRACT;
        return Iterator(this, 0);
    }

    Iterator End()
    {
        WRAPPER_NO_CONTRACT;
        return Iterator(this, GetCount());
    }

    Iterator operator+(COUNT_T index)
    {
        return Iterator(this, index);
    }

    ELEMENT & operator[] (int index);
    const ELEMENT & operator[] (int index) const;

    ELEMENT & operator[] (COUNT_T index);
    const ELEMENT & operator[] (COUNT_T index) const;

 protected:
    SArray(void *prealloc, COUNT_T size);

 public:

    class Iterator : public CheckedIteratorBase<SArray<ELEMENT, BITWISE_COPY> >, 
                     public Indexer<ELEMENT, Iterator>
    {
        friend class SArray;
        friend class Indexer<ELEMENT, Iterator>;

        SBuffer::Iterator m_i;

      public:
        
        Iterator(SArray *array, SCOUNT_T index)
          : CheckedIteratorBase<SArray<ELEMENT, BITWISE_COPY> >(array)
        {
            WRAPPER_NO_CONTRACT;
            m_i = array->m_buffer.Begin() + index*sizeof(ELEMENT);
        }

    protected:

        ELEMENT &GetAt(SCOUNT_T delta) const
        {
            LIMITED_METHOD_CONTRACT;
            return * (ELEMENT *) &m_i[delta*sizeof(ELEMENT)];
        }

        void Skip(SCOUNT_T delta)
        {
            LIMITED_METHOD_CONTRACT;
            m_i += delta*sizeof(ELEMENT);
        }

        COUNT_T Subtract(const Iterator &i) const
        {
            LIMITED_METHOD_CONTRACT;
            return (m_i - i.m_i)/sizeof(ELEMENT);
        }

        CHECK DoCheck(SCOUNT_T delta) const
        {
            WRAPPER_NO_CONTRACT;
            return m_i.CheckIndex(delta*sizeof(ELEMENT));
        }

      public:

        CHECK Check() const
        {
            WRAPPER_NO_CONTRACT;
            return m_i.Check();
        }
    };

    ELEMENT *GetElements() const;

  private:

    //--------------------------------------------------------------------
    // Routines for managing the buffer content.  
    //--------------------------------------------------------------------

    void ConstructBuffer(const Iterator &i, COUNT_T size);
    void CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from);
    void DestructBuffer(const Iterator &i, COUNT_T size);
};

// ================================================================================
// InlineSArray : Tempate for an SArray with preallocated element space
// ================================================================================

template <typename ELEMENT, COUNT_T SIZE, BOOL BITWISE_COPY = TRUE>
class InlineSArray : public SArray<ELEMENT, BITWISE_COPY>
{
 private:
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4200) // zero sized array
#pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads
    DECLSPEC_ALIGN(BUFFER_ALIGNMENT) BYTE m_prealloc[SIZE*sizeof(ELEMENT)];
#pragma warning(pop)
#else
     // use UINT64 to get maximum alignment of the memory
     UINT64 m_prealloc[ALIGN(SIZE*sizeof(ELEMENT),sizeof(UINT64))/sizeof(UINT64)];
#endif  // _MSC_VER

 public:
    InlineSArray();
};

// ================================================================================
// StackSArray : SArray with relatively large preallocated buffer for stack use
// ================================================================================

template <typename ELEMENT, BOOL BITWISE_COPY = TRUE>
class StackSArray : public InlineSArray<ELEMENT, STACK_ALLOC/sizeof(ELEMENT), BITWISE_COPY>
{
}; 

// ================================================================================
// Inline definitions
// ================================================================================

#include "sarray.inl"

#endif  // _SARRAY_H_