1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  *   https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  *   Redistribution and use in source and binary forms, with or
10  *   without modification, are permitted provided that the following
11  *   conditions are met:
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above
15  *     copyright notice, this list of conditions and the following
16  *     disclaimer in the documentation and/or other materials provided
17  *     with the distribution.
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *   POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef DART_COMMON_DETAIL_SPECIALIZEDFORASPECT_HPP_
34 #define DART_COMMON_DETAIL_SPECIALIZEDFORASPECT_HPP_
35 
36 #include "dart/common/SpecializedForAspect.hpp"
37 
38 // This preprocessor token should only be used by the unittest that is
39 // responsible for checking that the specialized routines are being used to
40 // access specialized Aspects
41 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
42 bool usedSpecializedAspectAccess;
43 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
44 
45 namespace dart {
46 namespace common {
47 
48 //==============================================================================
49 template <class SpecAspect>
SpecializedForAspect()50 SpecializedForAspect<SpecAspect>::SpecializedForAspect()
51 {
52   mSpecAspectIterator
53       = mAspectMap
54             .insert(std::make_pair<std::type_index, std::unique_ptr<Aspect>>(
55                 typeid(SpecAspect), nullptr))
56             .first;
57 }
58 
59 //==============================================================================
60 template <class SpecAspect>
61 template <class T>
has() const62 bool SpecializedForAspect<SpecAspect>::has() const
63 {
64   return _has(type<T>());
65 }
66 
67 //==============================================================================
68 template <class SpecAspect>
69 template <class T>
get()70 T* SpecializedForAspect<SpecAspect>::get()
71 {
72   return _get(type<T>());
73 }
74 
75 //==============================================================================
76 template <class SpecAspect>
77 template <class T>
get() const78 const T* SpecializedForAspect<SpecAspect>::get() const
79 {
80   return _get(type<T>());
81 }
82 
83 //==============================================================================
84 template <class SpecAspect>
85 template <class T>
set(const T * aspect)86 void SpecializedForAspect<SpecAspect>::set(const T* aspect)
87 {
88   _set(type<T>(), aspect);
89 }
90 
91 //==============================================================================
92 template <class SpecAspect>
93 template <class T>
set(std::unique_ptr<T> && aspect)94 void SpecializedForAspect<SpecAspect>::set(std::unique_ptr<T>&& aspect)
95 {
96   _set(type<T>(), std::move(aspect));
97 }
98 
99 //==============================================================================
100 template <class SpecAspect>
101 template <class T, typename... Args>
102 T* SpecializedForAspect<SpecAspect>::createAspect(Args&&... args)
103 {
104   return _createAspect(type<T>(), std::forward<Args>(args)...);
105 }
106 
107 //==============================================================================
108 template <class SpecAspect>
109 template <class T>
removeAspect()110 void SpecializedForAspect<SpecAspect>::removeAspect()
111 {
112   _removeAspect(type<T>());
113 }
114 
115 //==============================================================================
116 template <class SpecAspect>
117 template <class T>
releaseAspect()118 std::unique_ptr<T> SpecializedForAspect<SpecAspect>::releaseAspect()
119 {
120   return _releaseAspect(type<T>());
121 }
122 
123 //==============================================================================
124 template <class SpecAspect>
125 template <class T>
isSpecializedFor()126 constexpr bool SpecializedForAspect<SpecAspect>::isSpecializedFor()
127 {
128   return _isSpecializedFor(type<T>());
129 }
130 
131 //==============================================================================
132 template <class SpecAspect>
133 template <class T>
_has(type<T>) const134 bool SpecializedForAspect<SpecAspect>::_has(type<T>) const
135 {
136 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
137   usedSpecializedAspectAccess = true;
138 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
139 
140   return Composite::has<T>();
141 }
142 
143 //==============================================================================
144 template <class SpecAspect>
_has(type<SpecAspect>) const145 bool SpecializedForAspect<SpecAspect>::_has(type<SpecAspect>) const
146 {
147 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
148   usedSpecializedAspectAccess = true;
149 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
150 
151   return (mSpecAspectIterator->second.get() != nullptr);
152 }
153 
154 //==============================================================================
155 template <class SpecAspect>
156 template <class T>
_get(type<T>)157 T* SpecializedForAspect<SpecAspect>::_get(type<T>)
158 {
159   return Composite::get<T>();
160 }
161 
162 //==============================================================================
163 template <class SpecAspect>
_get(type<SpecAspect>)164 SpecAspect* SpecializedForAspect<SpecAspect>::_get(type<SpecAspect>)
165 {
166 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
167   usedSpecializedAspectAccess = true;
168 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
169 
170   return static_cast<SpecAspect*>(mSpecAspectIterator->second.get());
171 }
172 
173 //==============================================================================
174 template <class SpecAspect>
175 template <class T>
_get(type<T>) const176 const T* SpecializedForAspect<SpecAspect>::_get(type<T>) const
177 {
178   return Composite::get<T>();
179 }
180 
181 //==============================================================================
182 template <class SpecAspect>
_get(type<SpecAspect>) const183 const SpecAspect* SpecializedForAspect<SpecAspect>::_get(type<SpecAspect>) const
184 {
185 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
186   usedSpecializedAspectAccess = true;
187 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
188 
189   return static_cast<SpecAspect*>(mSpecAspectIterator->second.get());
190 }
191 
192 //==============================================================================
193 template <class SpecAspect>
194 template <class T>
_set(type<T>,const T * aspect)195 void SpecializedForAspect<SpecAspect>::_set(type<T>, const T* aspect)
196 {
197   Composite::set<T>(aspect);
198 }
199 
200 //==============================================================================
201 template <class SpecAspect>
_set(type<SpecAspect>,const SpecAspect * aspect)202 void SpecializedForAspect<SpecAspect>::_set(
203     type<SpecAspect>, const SpecAspect* aspect)
204 {
205 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
206   usedSpecializedAspectAccess = true;
207 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
208 
209   if (aspect)
210   {
211     mSpecAspectIterator->second = aspect->cloneAspect();
212     addToComposite(mSpecAspectIterator->second.get());
213   }
214   else
215   {
216     mSpecAspectIterator->second = nullptr;
217   }
218 }
219 
220 //==============================================================================
221 template <class SpecAspect>
222 template <class T>
_set(type<T>,std::unique_ptr<T> && aspect)223 void SpecializedForAspect<SpecAspect>::_set(
224     type<T>, std::unique_ptr<T>&& aspect)
225 {
226   Composite::set<T>(std::move(aspect));
227 }
228 
229 //==============================================================================
230 template <class SpecAspect>
_set(type<SpecAspect>,std::unique_ptr<SpecAspect> && aspect)231 void SpecializedForAspect<SpecAspect>::_set(
232     type<SpecAspect>, std::unique_ptr<SpecAspect>&& aspect)
233 {
234 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
235   usedSpecializedAspectAccess = true;
236 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
237 
238   mSpecAspectIterator->second = std::move(aspect);
239   addToComposite(mSpecAspectIterator->second.get());
240 }
241 
242 //==============================================================================
243 template <class SpecAspect>
244 template <class T, typename... Args>
245 T* SpecializedForAspect<SpecAspect>::_createAspect(type<T>, Args&&... args)
246 {
247   return Composite::createAspect<T>(std::forward<Args>(args)...);
248 }
249 
250 //==============================================================================
251 template <class SpecAspect>
252 template <typename... Args>
_createAspect(type<SpecAspect>,Args &&...args)253 SpecAspect* SpecializedForAspect<SpecAspect>::_createAspect(
254     type<SpecAspect>, Args&&... args)
255 {
256 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
257   usedSpecializedAspectAccess = true;
258 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
259 
260   SpecAspect* aspect = new SpecAspect(std::forward<Args>(args)...);
261   mSpecAspectIterator->second = std::unique_ptr<SpecAspect>(aspect);
262   addToComposite(aspect);
263 
264   return aspect;
265 }
266 
267 //==============================================================================
268 template <class SpecAspect>
269 template <class T>
_removeAspect(type<T>)270 void SpecializedForAspect<SpecAspect>::_removeAspect(type<T>)
271 {
272   Composite::removeAspect<T>();
273 }
274 
275 //==============================================================================
276 template <class SpecAspect>
_removeAspect(type<SpecAspect>)277 void SpecializedForAspect<SpecAspect>::_removeAspect(type<SpecAspect>)
278 {
279 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
280   usedSpecializedAspectAccess = true;
281 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
282 
283   DART_COMMON_CHECK_ILLEGAL_ASPECT_ERASE(erase, SpecAspect, DART_BLANK);
284 
285   removeFromComposite(mSpecAspectIterator->second.get());
286   mSpecAspectIterator->second = nullptr;
287 }
288 
289 //==============================================================================
290 template <class SpecAspect>
291 template <class T>
_releaseAspect(type<T>)292 std::unique_ptr<T> SpecializedForAspect<SpecAspect>::_releaseAspect(type<T>)
293 {
294   return Composite::releaseAspect<T>();
295 }
296 
297 //==============================================================================
298 template <class SpecAspect>
_releaseAspect(type<SpecAspect>)299 std::unique_ptr<SpecAspect> SpecializedForAspect<SpecAspect>::_releaseAspect(
300     type<SpecAspect>)
301 {
302 #ifdef DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
303   usedSpecializedAspectAccess = true;
304 #endif // DART_UNITTEST_SPECIALIZED_ASPECT_ACCESS
305 
306   DART_COMMON_CHECK_ILLEGAL_ASPECT_ERASE(release, SpecAspect, nullptr);
307 
308   removeFromComposite(mSpecAspectIterator->second.get());
309   std::unique_ptr<SpecAspect> extraction(
310       static_cast<SpecAspect*>(mSpecAspectIterator->second.release()));
311 
312   return extraction;
313 }
314 
315 //==============================================================================
316 template <class SpecAspect>
317 template <class T>
_isSpecializedFor(type<T>)318 constexpr bool SpecializedForAspect<SpecAspect>::_isSpecializedFor(type<T>)
319 {
320   return false;
321 }
322 
323 //==============================================================================
324 template <class SpecAspect>
_isSpecializedFor(type<SpecAspect>)325 constexpr bool SpecializedForAspect<SpecAspect>::_isSpecializedFor(
326     type<SpecAspect>)
327 {
328   return true;
329 }
330 
331 } // namespace common
332 } // namespace dart
333 
334 #endif // DART_COMMON_DETAIL_SPECIALIZEDFORASPECT_HPP_
335