-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathalloca_array.h
More file actions
159 lines (151 loc) · 3.56 KB
/
alloca_array.h
File metadata and controls
159 lines (151 loc) · 3.56 KB
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
#pragma once
// Copyright David Lawrence Bien 1997 - 2021.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt).
// alloca_array.h
// Simple typed stack allocated array with optional element lifetime ownership.
// dbien
// 20JAN2021
#include "bienutil.h"
__BIENUTIL_BEGIN_NAMESPACE
template < class t_TyEl, bool t_fOwnObjectLifetime >
class AllocaArray
{
typedef AllocaArray _TyThis;
public:
typedef t_TyEl _TyEl;
static constexpr bool s_kfOwnObjectLifetime = t_fOwnObjectLifetime;
~AllocaArray()
{
AssertValid();
if ( s_kfOwnObjectLifetime )
_Clear();
}
AllocaArray() = delete;
AllocaArray(size_t _nEls, _TyEl * _pEls)
: m_nElsPool( _nEls ),
m_rgEls( _pEls ),
m_pElEnd( _pEls )
{
}
AllocaArray( AllocaArray const & ) = delete;
AllocaArray & operator=( AllocaArray const & ) = delete;
AllocaArray( AllocaArray && _rr )
{
_rr.AssertValid();
swap( _rr );
}
AllocaArray & operator=( AllocaArray && _rr )
{
_rr.AssertValid();
AllocaArray acquire( std::move( _rr ) );
swap( acquire );
}
void swap( _TyThis & _r )
{
AssertValid();
_r.AssertValid();
std::swap( m_rgEls, _r.m_rgEls );
std::swap( m_nElsPool, _r.m_nElsPool );
}
template < class ... t_TysArgs >
_TyEl & emplaceAtEnd( t_TysArgs ... _args )
{
AssertValid();
Assert( m_pElEnd < m_rgEls + m_nElsPool );
new( m_pElEnd ) _TyEl( std::forward< t_TysArgs >( _args ) ... );
++m_pElEnd;
}
size_t GetSize() const
{
return m_pElEnd - m_rgEls;
}
size_t GetAllocSize() const
{
return m_nElsPool;
}
_TyEl * begin()
{
return m_rgEls;
}
const _TyEl * begin() const
{
return m_rgEls;
}
_TyEl * end()
{
return m_pElEnd;
}
const _TyEl * end() const
{
return m_pElEnd;
}
_TyEl const & ElGet( size_t _n ) const
{
Assert( _n < GetSize() );
AssertValid();
return m_rgEls[ _n ];
}
_TyEl & ElGet( size_t _n )
{
Assert( _n < GetSize() );
AssertValid();
return m_rgEls[ _n ];
}
_TyEl const & operator[]( size_t _n ) const
{
return ElGet( _n );
}
_TyEl & operator[]( size_t _n )
{
return ElGet( _n );
}
template < class t_TyFunctor >
void Apply( size_t _nFrom, size_t _nTo, t_TyFunctor && _rrf ) const
{
AssertValid();
Assert( _nFrom <= _nTo );
if ( _nTo == _nFrom )
return;
const _TyEl * pelCur = &ElGet( _nFrom );
const _TyEl * const pelEnd = pelCur + ( _nTo - _nFrom );
for ( ; pelEnd > pelCur; ++pelCur )
std::forward< t_TyFunctor >( _rrf )( *pelCur );
}
template < class t_TyFunctor >
void Apply( size_t _nFrom, size_t _nTo, t_TyFunctor && _rrf )
{
AssertValid();
Assert( _nFrom <= _nTo );
if ( _nTo == _nFrom )
return;
_TyEl * pelCur = &ElGet( _nFrom );
_TyEl * const pelEnd = pelCur + ( _nTo - _nFrom );
for ( ; pelEnd > pelCur; ++pelCur )
std::forward< t_TyFunctor >( _rrf )( *pelCur );
}
void AssertValid()
{
#if ASSERTSENABLED
Assert( m_pElEnd >= m_rgEls );
Assert( m_pElEnd <= m_rgEls + m_nElsPool );
#endif //ASSERTSENABLED
}
protected:
void _Clear()
{
if ( !s_kfOwnObjectLifetime )
return;
_TyEl * pelBegin = begin();
_TyEl * pelCur = end();
m_pElEnd = m_rgEls;
for ( ; pelBegin != pelCur; )
(--pelCur)->~_TyEl();
}
_TyEl * m_rgEls{nullptr};
_TyEl * m_pElEnd{nullptr};
size_t m_nElsPool{0};
};
#define ALLOCA_ARRAY_ALLOC( TYPE, N ) (TYPE*)alloca( (N) * sizeof(TYPE) )
__BIENUTIL_END_NAMESPACE