|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #ifndef STLPORT_UNIT_TEST_STACK_ALLOCATOR_H |
|
18 #define STLPORT_UNIT_TEST_STACK_ALLOCATOR_H |
|
19 |
|
20 #include <algorithm> |
|
21 |
|
22 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) |
|
23 //For bad_alloc: |
|
24 # include <new> |
|
25 #endif |
|
26 |
|
27 #if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES) |
|
28 # define __STD std:: |
|
29 #else |
|
30 # define __STD |
|
31 #endif |
|
32 |
|
33 struct State { |
|
34 char *m_beg, *m_end, *m_cur; |
|
35 bool m_isOk, m_swaped; |
|
36 int m_nbAlloc; |
|
37 |
|
38 //The following members are shared among all StackAllocator instance created from |
|
39 //a reference StackAllocator instance: |
|
40 char **m_sharedCur; |
|
41 bool *m_sharedOk; |
|
42 int *m_sharedNbAlloc; |
|
43 |
|
44 #if defined (__DMC__) |
|
45 State(){} |
|
46 #endif |
|
47 |
|
48 State(char *beg, char *end) |
|
49 : m_beg(beg), m_end(end), m_cur(m_beg), m_isOk(true), m_swaped(false), m_nbAlloc(0), |
|
50 m_sharedCur(&m_cur), m_sharedOk(&m_isOk), m_sharedNbAlloc(&m_nbAlloc) {} |
|
51 |
|
52 State(const State& other) |
|
53 : m_beg(other.m_beg), m_end(other.m_end), m_cur(0), |
|
54 m_isOk(true), m_swaped(other.m_swaped), m_nbAlloc(0), |
|
55 m_sharedCur(other.m_sharedCur), m_sharedOk(other.m_sharedOk), |
|
56 m_sharedNbAlloc(other.m_sharedNbAlloc) {} |
|
57 }; |
|
58 |
|
59 /* This allocator is not thread safe: |
|
60 */ |
|
61 template <class _Tp> |
|
62 struct StackAllocator |
|
63 #if (defined (__BORLANDC__) || defined (__DMC__)) && \ |
|
64 defined (STLPORT) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER) |
|
65 //Special Borland workaround that have problem with function |
|
66 //overloading when one of the overloaded version is a template |
|
67 //one. This is the case for the std::swap function. |
|
68 : public __STD __stlport_class<StackAllocator<_Tp> > |
|
69 #endif |
|
70 { |
|
71 typedef _Tp value_type; |
|
72 typedef value_type * pointer; |
|
73 typedef const _Tp* const_pointer; |
|
74 typedef _Tp& reference; |
|
75 typedef const _Tp& const_reference; |
|
76 typedef size_t size_type; |
|
77 typedef ptrdiff_t difference_type; |
|
78 |
|
79 #if defined (__DMC__) |
|
80 StackAllocator(){} |
|
81 #endif |
|
82 |
|
83 StackAllocator(char *beg, char *end) |
|
84 : m_state(beg, end) {} |
|
85 |
|
86 const State& getState() const { return m_state; } |
|
87 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATES) |
|
88 template <class _OtherTp> |
|
89 StackAllocator(StackAllocator<_OtherTp> const& other) |
|
90 : m_state(other.getState()) {} |
|
91 #else |
|
92 StackAllocator(const State& state) |
|
93 : m_state(state) {} |
|
94 #endif |
|
95 |
|
96 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATE_CLASSES) |
|
97 template <class _Other> |
|
98 struct rebind { |
|
99 typedef StackAllocator<_Other> other; |
|
100 }; |
|
101 #endif |
|
102 |
|
103 _Tp* allocate(size_type n, void* = 0) { |
|
104 if (n == 0) |
|
105 return 0; |
|
106 |
|
107 ++(*m_state.m_sharedNbAlloc); |
|
108 |
|
109 if (*m_state.m_sharedCur + (n * sizeof(_Tp)) < m_state.m_end) { |
|
110 char *ret = *m_state.m_sharedCur; |
|
111 *m_state.m_sharedCur += n * sizeof(_Tp); |
|
112 return reinterpret_cast<_Tp*>(ret); |
|
113 } |
|
114 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) |
|
115 throw __STD bad_alloc(); |
|
116 # if defined (__DMC__) |
|
117 return 0; |
|
118 # endif |
|
119 #else |
|
120 return 0; |
|
121 #endif |
|
122 } |
|
123 |
|
124 #if (defined (__BORLANDC__) || defined (__DMC__)) && \ |
|
125 defined (STLPORT) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER) |
|
126 //Necessary extension to make StackAllocator a real STLport allocator |
|
127 //implementation: |
|
128 _Tp* allocate(size_type n, size_type &new_n) { |
|
129 new_n = n; |
|
130 return allocate(n); |
|
131 } |
|
132 #endif |
|
133 |
|
134 void deallocate(pointer p, size_type n) { |
|
135 if (p == 0) |
|
136 return; |
|
137 |
|
138 --(*m_state.m_sharedNbAlloc); |
|
139 |
|
140 if ((char*)p == (*m_state.m_sharedCur - n * sizeof(_Tp))) { |
|
141 *m_state.m_sharedCur -= n * sizeof(_Tp); |
|
142 } |
|
143 |
|
144 if ((char*)p < m_state.m_beg || (char*)p >= m_state.m_end) { |
|
145 //An object has been returned to the bad allocator instance: |
|
146 *m_state.m_sharedOk = false; |
|
147 } |
|
148 } |
|
149 |
|
150 pointer address(reference __x) const {return &__x;} |
|
151 const_pointer address(const_reference __x) const { return &__x; } |
|
152 size_type max_size() const { return m_state.m_end - *m_state.m_sharedCur; } |
|
153 void construct(pointer __p, const_reference __val) { new(__p) _Tp(__val); } |
|
154 void destroy(pointer __p) { __p->~_Tp(); } |
|
155 |
|
156 bool ok() const { return m_state.m_isOk && (m_state.m_nbAlloc == 0); } |
|
157 void reset () { |
|
158 m_state.m_cur = m_state.m_beg; |
|
159 m_state.m_isOk = true; |
|
160 m_state.m_swaped = false; |
|
161 } |
|
162 bool swaped() const { return m_state.m_swaped; } |
|
163 void swap(StackAllocator &other) { |
|
164 __STD swap(m_state, other.m_state); |
|
165 m_state.m_swaped = true; |
|
166 other.m_state.m_swaped = true; |
|
167 } |
|
168 |
|
169 //2 StackAllocator instance are identical if they are built on top |
|
170 //of the same buffer. |
|
171 bool operator == (StackAllocator const& other) const |
|
172 { return m_state.m_beg == other.m_state.m_beg; } |
|
173 |
|
174 bool operator != (StackAllocator const& other) const |
|
175 { return !(*this == other); } |
|
176 |
|
177 private: |
|
178 State m_state; |
|
179 }; |
|
180 |
|
181 #if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES) |
|
182 namespace std { |
|
183 #endif |
|
184 |
|
185 # if defined (STLPORT) && (defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || !defined (_STLP_MEMBER_TEMPLATES)) |
|
186 template <class _Tp1, class _Tp2> |
|
187 inline StackAllocator<_Tp2>& |
|
188 __stl_alloc_rebind(StackAllocator<_Tp1>& __a, const _Tp2*) { return (StackAllocator<_Tp2>&)(__a); } |
|
189 template <class _Tp1, class _Tp2> |
|
190 inline StackAllocator<_Tp2> |
|
191 __stl_alloc_create(const StackAllocator<_Tp1>& __a, const _Tp2*) { return StackAllocator<_Tp2>(__a.getState()); } |
|
192 # endif |
|
193 |
|
194 # if !defined (STLPORT) || defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER) |
|
195 template <class _Tp> |
|
196 inline void swap(StackAllocator<_Tp>& __a, StackAllocator<_Tp>& __b) |
|
197 { __a.swap(__b); } |
|
198 # else |
|
199 //TheFollowing overloads depends on instanciation, if new unit tests are written |
|
200 //with new StackAllocator instanciations associated swap overload should also be |
|
201 //written |
|
202 inline void swap(StackAllocator<int>& __a, StackAllocator<int>& __b) |
|
203 { __a.swap(__b); } |
|
204 inline void swap(StackAllocator<char>& __a, StackAllocator<char>& __b) |
|
205 { __a.swap(__b); } |
|
206 inline void swap(StackAllocator<pair<const int, int> >& __a, |
|
207 StackAllocator<pair<const int, int> >& __b) |
|
208 { __a.swap(__b); } |
|
209 # endif |
|
210 |
|
211 #if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES) |
|
212 } |
|
213 #endif |
|
214 |
|
215 #undef __STD |
|
216 |
|
217 #endif //STLPORT_UNIT_TEST_STACK_ALLOCATOR_H |