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