1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef STAGEFRIGHT_FOUNDATION_A_DATA_H_
18 #define STAGEFRIGHT_FOUNDATION_A_DATA_H_
19 
20 #include <memory> // for std::shared_ptr, weak_ptr and unique_ptr
21 #include <type_traits> // for std::aligned_union
22 
23 #include <utils/StrongPointer.h> // for android::sp and wp
24 
25 #include <media/stagefright/foundation/TypeTraits.h>
26 #include <media/stagefright/foundation/Flagged.h>
27 
28 #undef HIDE
29 #define HIDE __attribute__((visibility("hidden")))
30 
31 namespace android {
32 
33 /**
34  * AData is a flexible union type that supports non-POD members. It supports arbitrary types as long
35  * as they are either moveable or copyable.
36  *
37  * Internally, AData is using AUnion - a structure providing the union support. AUnion should not
38  * be used by generic code as it is very unsafe - it opens type aliasing errors where an object of
39  * one type can be easily accessed as an object of another type. AData prevents this.
40  *
41  * AData allows a custom type flagger to be used for future extensions (e.g. allowing automatic
42  * type conversion). A strict and a relaxed flagger are provided as internal types.
43  *
44  * Use as follows:
45  *
46  * AData<int, float>::Basic data; // strict type support
47  * int i = 1;
48  * float f = 7.0f;
49  *
50  * data.set(5);
51  * EXPECT_TRUE(data.find(&i));
52  * EXPECT_FALSE(data.find(&f));
53  * EXPECT_EQ(i, 5);
54  *
55  * data.set(6.0f);
56  * EXPECT_FALSE(data.find(&i));
57  * EXPECT_TRUE(data.find(&f));
58  * EXPECT_EQ(f, 6.0f);
59  *
60  * AData<int, sp<RefBase>>::RelaxedBasic objdata; // relaxed type support
61  * sp<ABuffer> buf = new ABuffer(16), buf2;
62  * sp<RefBase> obj;
63  *
64  * objdata.set(buf);
65  * EXPECT_TRUE(objdata.find(&buf2));
66  * EXPECT_EQ(buf, buf2);
67  * EXPECT_FALSE(objdata.find(&i));
68  * EXPECT_TRUE(objdata.find(&obj));
69  * EXPECT_TRUE(obj == buf);
70  *
71  * obj = buf;
72  * objdata.set(obj); // storing as sp<RefBase>
73  * EXPECT_FALSE(objdata.find(&buf2));  // not stored as ABuffer(!)
74  * EXPECT_TRUE(objdata.find(&obj));
75  */
76 
77 /// \cond Internal
78 
79 /**
80  * Helper class to call constructor and destructor for a specific type in AUnion.
81  * This class is needed as member function specialization is not allowed for a
82  * templated class.
83  */
84 struct HIDE _AUnion_impl {
85     /**
86      * Calls placement constuctor for type T with arbitrary arguments for a storage at an address.
87      * Storage MUST be large enough to contain T.
88      * Also clears the slack space after type T. \todo This is not technically needed, so we may
89      * choose to do this just for debugging.
90      *
91      * \param totalSize size of the storage
92      * \param addr      pointer to where object T should be constructed
93      * \param args      arbitrary arguments for constructor
94      */
95     template<typename T, typename ...Args>
emplace_AUnion_impl96     inline static void emplace(size_t totalSize, T *addr, Args&&... args) {
97         new(addr)T(std::forward<Args>(args)...);
98         // clear slack space - this is not technically required
99         constexpr size_t size = sizeof(T);
100         memset(reinterpret_cast<uint8_t*>(addr) + size, 0, totalSize - size);
101     }
102 
103     /**
104      * Calls destuctor for an object of type T located at a specific address.
105      *
106      * \note we do not clear the storage in this case as the storage should not be used
107      * until another object is placed there, at which case the storage will be cleared.
108      *
109      * \param addr    pointer to where object T is stored
110      */
111     template<typename T>
del_AUnion_impl112     inline static void del(T *addr) {
113         addr->~T();
114     }
115 };
116 
117 /** Constructor specialization for void type */
118 template<>
119 HIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
120     memset(addr, 0, totalSize);
121 }
122 
123 /** Destructor specialization for void type */
124 template<>
125 HIDE inline void _AUnion_impl::del<void>(void *) {
126 }
127 
128 /// \endcond
129 
130 /**
131  * A templated union class that can contain specific types of data, and provides
132  * constructors, destructor and access methods strictly for those types.
133  *
134  * \note This class is VERY UNSAFE compared to a union, but it allows non-POD unions.
135  * In particular care must be taken that methods are called in a careful order to
136  * prevent accessing objects of one type as another type. This class provides no
137  * facilities to help with this ordering. This is meant to be wrapped by safer
138  * utility classes that do that.
139  *
140  * \param Ts types stored in this union.
141  */
142 template<typename ...Ts>
143 struct AUnion {
144 private:
145     using _type = typename std::aligned_union<0, Ts...>::type; ///< storage type
146     _type mValue;                                              ///< storage
147 
148 public:
149     /**
150      * Constructs an object of type T with arbitrary arguments in this union. After this call,
151      * this union will contain this object.
152      *
153      * This method MUST be called only when either 1) no object or 2) a void object (equivalent to
154      * no object) is contained in this union.
155      *
156      * \param T     type of object to be constructed. This must be one of the template parameters of
157      *              the union class with the same cv-qualification, or void.
158      * \param args  arbitrary arguments for the constructor
159      */
160     template<
161             typename T, typename ...Args,
162             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
emplaceAUnion163     inline void emplace(Args&&... args) {
164         _AUnion_impl::emplace(
165                 sizeof(_type), reinterpret_cast<T*>(&mValue), std::forward<Args>(args)...);
166     }
167 
168     /**
169      * Destructs an object of type T in this union. After this call, this union will contain no
170      * object.
171      *
172      * This method MUST be called only when this union contains an object of type T.
173      *
174      * \param T     type of object to be destructed. This must be one of the template parameters of
175      *              the union class with the same cv-qualification, or void.
176      */
177     template<
178             typename T,
179             typename=typename std::enable_if<is_one_of<T, void, Ts...>::value>::type>
delAUnion180     inline void del() {
181         _AUnion_impl::del(reinterpret_cast<T*>(&mValue));
182     }
183 
184     /**
185      * Returns a const reference to the object of type T in this union.
186      *
187      * This method MUST be called only when this union contains an object of type T.
188      *
189      * \param T     type of object to be returned. This must be one of the template parameters of
190      *              the union class with the same cv-qualification.
191      */
192     template<
193             typename T,
194             typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
getAUnion195     inline const T &get() const {
196         return *reinterpret_cast<const T*>(&mValue);
197     }
198 
199     /**
200      * Returns a reference to the object of type T in this union.
201      *
202      * This method MUST be called only when this union contains an object of type T.
203      *
204      * \param T     type of object to be returned. This must be one of the template parameters of
205      *              the union class with the same cv-qualification.
206      */
207     template<typename T>
getAUnion208     inline T &get() {
209         return *reinterpret_cast<T*>(&mValue);
210     }
211 };
212 
213 /**
214  * Helper utility class that copies an object of type T to a destination.
215  *
216  * T must be copy assignable or copy constructible.
217  *
218  * It provides:
219  *
220  * void assign(T*, const U&) // for copiable types - this leaves the source unchanged, hence const.
221  *
222  * \param T type of object to assign to
223  */
224 template<
225         typename T,
226         bool=std::is_copy_assignable<T>::value>
227 struct HIDE _AData_copier {
228     static_assert(std::is_copy_assignable<T>::value, "T must be copy assignable here");
229 
230     /**
231      * Copies src to data without modifying data.
232      *
233      * \param data pointer to destination
234      * \param src source object
235      */
assign_AData_copier236     inline static void assign(T *data, const T &src) {
237         *data = src;
238     }
239 
240     template<typename U>
241     using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
242 
243     /**
244      * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
245      */
246     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
assign_AData_copier247     inline static void assign(sp<Tp> *data, const sp<U> &src) {
248         *data = static_cast<Tp*>(src.get());
249     }
250 
251     template<typename Tp, typename U, typename=enable_if_T_is_same_as<wp<Tp>>>
assign_AData_copier252     inline static void assign(wp<Tp> *data, const wp<U> &src) {
253         sp<U> __tmp = src.promote();
254         *data = static_cast<Tp*>(__tmp.get());
255     }
256 
257     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
assign_AData_copier258     inline static void assign(sp<Tp> *data, sp<U> &&src) {
259         sp<U> __tmp = std::move(src); // move src out as get cannot
260         *data = static_cast<Tp*>(__tmp.get());
261     }
262 
263     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
assign_AData_copier264     inline static void assign(std::shared_ptr<Tp> *data, const std::shared_ptr<U> &src) {
265         *data = std::static_pointer_cast<Tp>(src);
266     }
267 
268     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
assign_AData_copier269     inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
270         std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
271         *data = std::static_pointer_cast<Tp>(__tmp);
272     }
273 
274     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::weak_ptr<Tp>>>
assign_AData_copier275     inline static void assign(std::weak_ptr<Tp> *data, const std::weak_ptr<U> &src) {
276         *data = std::static_pointer_cast<Tp>(src.lock());
277     }
278 
279     // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
280     // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
281     // they are stored as shared_ptrs.
282     /**
283      * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
284      * is not enough to detect this, only if someone is trying to find the shared_ptr.
285      */
286     template<typename Tp, typename U>
assign_AData_copier287     inline static void assign(std::shared_ptr<Tp> *, const std::weak_ptr<U> &) {
288         static_assert(std::is_same<Tp, void>::value,
289                       "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
290     }
291 };
292 
293 /**
294  * Template specialization for non copy assignable, but copy constructible types.
295  *
296  * \todo Test this. No basic classes are copy constructible but not assignable.
297  *
298  */
299 template<typename T>
300 struct HIDE _AData_copier<T, false> {
301     static_assert(!std::is_copy_assignable<T>::value, "T must not be copy assignable here");
302     static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible here");
303 
304     inline static void copy(T *data, const T &src) {
305         data->~T();
306         new(data)T(src);
307     }
308 };
309 
310 /**
311  * Helper utility class that moves an object of type T to a destination.
312  *
313  * T must be move assignable or move constructible.
314  *
315  * It provides multiple methods:
316  *
317  * void assign(T*, T&&)
318  *
319  * \param T type of object to assign
320  */
321 template<
322         typename T,
323         bool=std::is_move_assignable<T>::value>
324 struct HIDE _AData_mover {
325     static_assert(std::is_move_assignable<T>::value, "T must be move assignable here");
326 
327     /**
328      * Moves src to data while likely modifying it.
329      *
330      * \param data pointer to destination
331      * \param src source object
332      */
333     inline static void assign(T *data, T &&src) {
334         *data = std::move(src);
335     }
336 
337     template<typename U>
338     using enable_if_T_is_same_as = typename std::enable_if<std::is_same<U, T>::value>::type;
339 
340     /**
341      * Downcast specializations for sp<>, shared_ptr<> and weak_ptr<>
342      */
343     template<typename Tp, typename U, typename=enable_if_T_is_same_as<sp<Tp>>>
344     inline static void assign(sp<Tp> *data, sp<U> &&src) {
345         sp<U> __tmp = std::move(src); // move src out as get cannot
346         *data = static_cast<Tp*>(__tmp.get());
347     }
348 
349     template<typename Tp, typename U, typename=enable_if_T_is_same_as<std::shared_ptr<Tp>>>
350     inline static void assign(std::shared_ptr<Tp> *data, std::shared_ptr<U> &&src) {
351         std::shared_ptr<U> __tmp = std::move(src); // move src out as static_pointer_cast cannot
352         *data = std::static_pointer_cast<Tp>(__tmp);
353     }
354 
355     template<typename Tp, typename Td, typename U, typename Ud,
356             typename=enable_if_T_is_same_as<std::unique_ptr<Tp, Td>>>
357     inline static void assign(std::unique_ptr<Tp, Td> *data, std::unique_ptr<U, Ud> &&src) {
358         *data = std::unique_ptr<Tp, Td>(static_cast<Tp*>(src.release()));
359     }
360 
361     // shared_ptrs are implicitly convertible to weak_ptrs but not vice versa, but picking the
362     // first compatible type in Ts requires having shared_ptr types before weak_ptr types, so that
363     // they are stored as shared_ptrs.
364     /**
365      * Provide sensible error message if encountering shared_ptr/weak_ptr ambiguity. This method
366      * is not enough to detect this, only if someone is trying to remove the shared_ptr.
367      */
368     template<typename Tp, typename U>
369     inline static void assign(std::shared_ptr<Tp> *, std::weak_ptr<U> &&) {
370         static_assert(std::is_same<Tp, void>::value,
371                       "shared/weak pointer ambiguity. move shared ptr types before weak_ptrs");
372     }
373 
374     // unique_ptrs are implicitly convertible to shared_ptrs but not vice versa, but picking the
375     // first compatible type in Ts requires having unique_ptrs types before shared_ptrs types, so
376     // that they are stored as unique_ptrs.
377     /**
378      * Provide sensible error message if encountering shared_ptr/unique_ptr ambiguity. This method
379      * is not enough to detect this, only if someone is trying to remove the unique_ptr.
380      */
381     template<typename Tp, typename U>
382     inline static void assign(std::unique_ptr<Tp> *, std::shared_ptr<U> &&) {
383         static_assert(std::is_same<Tp, void>::value,
384                       "unique/shared pointer ambiguity. move unique ptr types before shared_ptrs");
385     }
386 };
387 
388 /**
389  * Template specialization for non move assignable, but move constructible types.
390  *
391  * \todo Test this. No basic classes are move constructible but not assignable.
392  *
393  */
394 template<typename T>
395 struct HIDE _AData_mover<T, false> {
396     static_assert(!std::is_move_assignable<T>::value, "T must not be move assignable here");
397     static_assert(std::is_move_constructible<T>::value, "T must be move constructible here");
398 
399     inline static void assign(T *data, T &&src) {
400         data->~T();
401         new(data)T(std::move(src));
402     }
403 };
404 
405 /**
406  * Helper template that deletes an object of a specific type (member) in an AUnion.
407  *
408  * \param Flagger type flagger class (see AData)
409  * \param U AUnion object in which the member should be deleted
410  * \param Ts types to consider for the member
411  */
412 template<typename Flagger, typename U, typename ...Ts>
413 struct HIDE _AData_deleter;
414 
415 /**
416  * Template specialization when there are still types to consider (T and rest)
417  */
418 template<typename Flagger, typename U, typename T, typename ...Ts>
419 struct HIDE _AData_deleter<Flagger, U, T, Ts...> {
420     static bool del(typename Flagger::type flags, U &data) {
421         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
422             data.template del<T>();
423             return true;
424         }
425         return _AData_deleter<Flagger, U, Ts...>::del(flags, data);
426     }
427 };
428 
429 /**
430  * Template specialization when there are no more types to consider.
431  */
432 template<typename Flagger, typename U>
433 struct HIDE _AData_deleter<Flagger, U> {
434     inline static bool del(typename Flagger::type, U &) {
435         return false;
436     }
437 };
438 
439 /**
440  * Helper template that copy assigns an object of a specific type (member) in an
441  * AUnion.
442  *
443  * \param Flagger type flagger class (see AData)
444  * \param U AUnion object in which the member should be copy assigned
445  * \param Ts types to consider for the member
446  */
447 template<typename Flagger, typename U, typename ...Ts>
448 struct HIDE _AData_copy_assigner;
449 
450 /**
451  * Template specialization when there are still types to consider (T and rest)
452  */
453 template<typename Flagger, typename U, typename T, typename ...Ts>
454 struct HIDE _AData_copy_assigner<Flagger, U, T, Ts...> {
455     static bool assign(typename Flagger::type flags, U &dst, const U &src) {
456         static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
457         // if we can delete as, we can also assign as
458         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
459             dst.template emplace<T>(src.template get<T>());
460             return true;
461         }
462         return _AData_copy_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
463     }
464 };
465 
466 /**
467  * Template specialization when there are no more types to consider.
468  */
469 template<typename Flagger, typename U>
470 struct HIDE _AData_copy_assigner<Flagger, U> {
471     inline static bool assign(typename Flagger::type, U &, const U &) {
472         return false;
473     }
474 };
475 
476 /**
477  * Helper template that move assigns an object of a specific type (member) in an
478  * AUnion.
479  *
480  * \param Flagger type flagger class (see AData)
481  * \param U AUnion object in which the member should be copy assigned
482  * \param Ts types to consider for the member
483  */
484 template<typename Flagger, typename U, typename ...Ts>
485 struct HIDE _AData_move_assigner;
486 
487 /**
488  * Template specialization when there are still types to consider (T and rest)
489  */
490 template<typename Flagger, typename U, typename T, typename ...Ts>
491 struct HIDE _AData_move_assigner<Flagger, U, T, Ts...> {
492     template<typename V = T>
493     static typename std::enable_if<std::is_move_constructible<V>::value, bool>::type
494     assign(typename Flagger::type flags, U &dst, U &src) {
495         // if we can delete as, we can also assign as
496         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
497             dst.template emplace<T>(std::move(src.template get<T>()));
498             return true;
499         }
500         return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
501     }
502 
503     // Fall back to copy construction if T is not move constructible
504     template<typename V = T>
505     static typename std::enable_if<!std::is_move_constructible<V>::value, bool>::type
506     assign(typename Flagger::type flags, U &dst, U &src) {
507         static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
508         // if we can delete as, we can also assign as
509         if (Flagger::canDeleteAs(flags, Flagger::flagFor((T*)0))) {
510             dst.template emplace<T>(src.template get<T>());
511             return true;
512         }
513         return _AData_move_assigner<Flagger, U, Ts...>::assign(flags, dst, src);
514     }
515 };
516 
517 /**
518  * Template specialization when there are no more types to consider.
519  */
520 template<typename Flagger, typename U>
521 struct HIDE _AData_move_assigner<Flagger, U> {
522     inline static bool assign(typename Flagger::type, U &, U &) {
523         return false;
524     }
525 };
526 
527 /**
528  * Container that can store an arbitrary object of a set of specified types.
529  *
530  * This struct is an outer class that contains various inner classes based on desired type
531  * strictness. The following inner classes are supported:
532  *
533  * AData<types...>::Basic   - strict type support using uint32_t flag.
534  *
535  * AData<types...>::Strict<Flag> - strict type support using custom flag.
536  * AData<types...>::Relaxed<Flag, MaxSize, Align>
537  *                          - relaxed type support with compatible (usually derived) class support
538  *                            for pointer types with added size checking for minimal additional
539  *                            safety.
540  *
541  * AData<types...>::RelaxedBasic - strict type support using uint32_t flag.
542  *
543  * AData<types...>::Custom<flagger> - custom type support (flaggers determine the supported types
544  *                                    and the base type to use for each)
545  *
546  */
547 template<typename ...Ts>
548 struct AData {
549 private:
550     static_assert(are_unique<Ts...>::value, "types must be unique");
551 
552     static constexpr size_t num_types = sizeof...(Ts); ///< number of types to support
553 
554 public:
555     /**
556      * Default (strict) type flagger provided.
557      *
558      * The default flagger simply returns the index of the type within Ts, or 0 for void.
559      *
560      * Type flaggers return a flag for a supported type.
561      *
562      * They must provide:
563      *
564      * - a flagFor(T*) method for supported types _and_ for T=void. T=void is used to mark that no
565      *   object is stored in the container. For this, an arbitrary unique value may be returned.
566      * - a mask field that contains the flag mask.
567      * - a canDeleteAs(Flag, Flag) flag comparison method that checks if a type of a flag can be
568      *   deleted as another type.
569      *
570      * \param Flag the underlying unsigned integral to use for the flags.
571      */
572     template<typename Flag>
573     struct flagger {
574     private:
575         static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
576         static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
577 
578         static constexpr Flag count = num_types + 1;
579 
580     public:
581         typedef Flag type; ///< flag type
582 
583         static constexpr Flag mask = _Flagged_helper::minMask<Flag>(count); ///< flag mask
584 
585         /**
586          * Return the stored type for T. This is itself.
587          */
588         template<typename T>
589         struct store {
590             typedef T as_type; ///< the base type that T is stored as
591         };
592 
593         /**
594          * Constexpr method that returns if two flags are compatible for deletion.
595          *
596          * \param objectFlag flag for object to be deleted
597          * \param deleteFlag flag for type that object is to be deleted as
598          */
599         static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
600             // default flagger requires strict type equality
601             return objectFlag == deleteFlag;
602         }
603 
604         /**
605          * Constexpr method that returns the flag to use for a given type.
606          *
607          * Function overload for void*.
608          */
609         static constexpr Flag flagFor(void*) {
610             return 0u;
611         }
612 
613         /**
614          * Constexpr method that returns the flag to use for a given supported type (T).
615          */
616         template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
617         static constexpr Flag flagFor(T*) {
618             return find_first<T, Ts...>::index;
619         }
620     };
621 
622     /**
623      * Relaxed flagger returns the index of the type within Ts. However, for pointers T* it returns
624      * the first type in Ts that T* can be converted into (this is normally a base type, but also
625      * works for sp<>, shared_ptr<> or unique_ptr<>). For a bit more strictness, the flag also
626      * contains the size of the class to avoid finding objects that were stored as a different
627      * derived class of the same base class.
628      *
629      * Flag is basically the index of the (base) type in Ts multiplied by the max size stored plus
630      * the size of the type (divided by alignment) for derived pointer types.
631      *
632      * \param MaxSize max supported size for derived class pointers
633      * \param Align alignment to assume for derived class pointers
634      */
635     template<typename Flag, size_t MaxSize=1024, size_t Align=4>
636     struct relaxed_flagger {
637     private:
638         static_assert(std::is_unsigned<Flag>::value, "Flag must be unsigned");
639         static_assert(std::is_integral<Flag>::value, "Flag must be an integral type");
640 
641         static constexpr Flag count = num_types + 1;
642         static_assert(std::numeric_limits<Flag>::max() / count > (MaxSize / Align),
643                       "not enough bits to fit into flag");
644 
645         static constexpr Flag max_size_stored = MaxSize / Align + 1;
646 
647         // T can be converted if it's size is <= MaxSize and it can be converted to one of the Ts
648         template<typename T, size_t size>
649         using enable_if_can_be_converted = typename std::enable_if<
650                 (size / Align < max_size_stored
651                         && find_first_convertible_to<T, Ts...>::index)>::type;
652 
653 
654         template<typename W, typename T, typename=enable_if_can_be_converted<W, sizeof(T)>>
655         static constexpr Flag relaxedFlagFor(W*, T*) {
656             return find_first_convertible_to<W, Ts...>::index * max_size_stored
657                     + (is_one_of<W, Ts...>::value ? 0 : (sizeof(T) / Align));
658         }
659 
660     public:
661         typedef Flag type; ///< flag type
662 
663         static constexpr Flag mask =
664             _Flagged_helper::minMask<Flag>(count * max_size_stored); ///< flag mask
665 
666         /**
667          * Constexpr method that returns if two flags are compatible for deletion.
668          *
669          * \param objectFlag flag for object to be deleted
670          * \param deleteFlag flag for type that object is to be deleted as
671          */
672         static constexpr bool canDeleteAs(Flag objectFlag, Flag deleteFlag) {
673             // can delete if objects have the same base type
674             return
675                 objectFlag / max_size_stored == deleteFlag / max_size_stored &&
676                 (deleteFlag % max_size_stored) == 0;
677         }
678 
679         /**
680          * Constexpr method that returns the flag to use for a given type.
681          *
682          * Function overload for void*.
683          */
684         static constexpr Flag flagFor(void*) {
685             return 0u;
686         }
687 
688         /**
689          * Constexpr method that returns the flag to use for a given supported type (T).
690          *
691          * This is a member method to enable both overloading as well as template specialization.
692          */
693         template<typename T, typename=typename std::enable_if<is_one_of<T, Ts...>::value>::type>
694         static constexpr Flag flagFor(T*) {
695             return find_first<T, Ts...>::index * max_size_stored;
696         }
697 
698         /**
699          * For precaution, we only consider converting pointers to their base classes.
700          */
701 
702         /**
703          * Template specialization for derived class pointers and managed pointers.
704          */
705         template<typename T>
706         static constexpr Flag flagFor(T**p) { return relaxedFlagFor(p, (T*)0); }
707         template<typename T>
708         static constexpr Flag flagFor(std::shared_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
709         template<typename T>
710         static constexpr Flag flagFor(std::unique_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
711         template<typename T>
712         static constexpr Flag flagFor(std::weak_ptr<T>*p) { return relaxedFlagFor(p, (T*)0); }
713         template<typename T>
714         static constexpr Flag flagFor(sp<T>*p) { return relaxedFlagFor(p, (T*)0); }
715         template<typename T>
716         static constexpr Flag flagFor(wp<T>*p) { return relaxedFlagFor(p, (T*)0); }
717 
718         /**
719          * Type support template that provodes the stored type for T.
720          * This is itself if it is one of Ts, or the first type in Ts that T is convertible to.
721          *
722          * NOTE: This template may provide a base class for an unsupported type. Support is
723          * determined by flagFor().
724          */
725         template<typename T>
726         struct store {
727             typedef typename std::conditional<
728                     is_one_of<T, Ts...>::value,
729                     T,
730                     typename find_first_convertible_to<T, Ts...>::type>::type as_type;
731         };
732     };
733 
734     /**
735      * Implementation of AData.
736      */
737     template<typename Flagger>
738     struct Custom : protected Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask> {
739         using data_t = AUnion<Ts...>;
740         using base_t = Flagged<AUnion<Ts...>, typename Flagger::type, Flagger::mask>;
741 
742         /**
743          * Constructor. Initializes this to a container that does not contain any object.
744          */
745         Custom() : base_t(Flagger::flagFor((void*)0)) { }
746 
747         /**
748          * Copy assignment operator.
749          */
750         Custom& operator=(const Custom &o) {
751             if (&o != this) {
752                 if (this->used() && !this->clear()) {
753                     __builtin_trap();
754                 }
755                 if (o.used()) {
756                     if (_AData_copy_assigner<Flagger, data_t, Ts...>::assign(
757                             o.flags(), this->get(), o.get())) {
758                         this->setFlags(o.flags());
759                     } else {
760                         __builtin_trap();
761                     }
762                 }
763             }
764             return *this;
765         }
766 
767         /**
768          * Copy constructor.
769          */
770         Custom(const Custom &o) : Custom() {
771             *this = o;
772         }
773 
774         /**
775          * Move assignment operator.
776          */
777         Custom& operator=(Custom &&o) noexcept {
778             if (&o != this) {
779                 if (this->used() && !this->clear()) {
780                     __builtin_trap();
781                 }
782                 if (o.used()) {
783                     if (_AData_move_assigner<Flagger, data_t, Ts...>::assign(
784                             o.flags(), this->get(), o.get())) {
785                         this->setFlags(o.flags());
786                         o.clear();
787                     } else {
788                         __builtin_trap();
789                     }
790                 }
791             }
792             return *this;
793         }
794 
795         /**
796          * Move constructor.
797          */
798         Custom(Custom &&o) noexcept : Custom() {
799             *this = std::move(o);
800         }
801 
802         /**
803          * Removes the contained object, if any.
804          */
805         ~Custom() {
806             if (!this->clear()) {
807                 __builtin_trap();
808                 // std::cerr << "could not delete data of type " << this->flags() << std::endl;
809             }
810         }
811 
812         /**
813          * Returns whether there is any object contained.
814          */
815         inline bool used() const {
816             return this->flags() != Flagger::flagFor((void*)0);
817         }
818 
819         /**
820          * Removes the contained object, if any. Returns true if there are no objects contained,
821          * or false on any error (this is highly unexpected).
822          */
823         bool clear() {
824             if (this->used()) {
825                 if (_AData_deleter<Flagger, data_t, Ts...>::del(this->flags(), this->get())) {
826                     this->setFlags(Flagger::flagFor((void*)0));
827                     return true;
828                 }
829                 return false;
830             }
831             return true;
832         }
833 
834         template<typename T>
835         using is_supported_by_flagger =
836             typename std::enable_if<Flagger::flagFor((T*)0) != Flagger::flagFor((void*)0)>::type;
837 
838         /**
839          * Checks if there is a copiable object of type T in this container. If there is, it copies
840          * that object into the provided address and returns true. Otherwise, it does nothing and
841          * returns false.
842          *
843          * This method normally requires a flag equality between the stored and retrieved types.
844          * However, it also allows retrieving the stored object as the stored type
845          * (usually base type).
846          *
847          * \param T type of object to sought
848          * \param data address at which the object should be retrieved
849          *
850          * \return true if the object was retrieved. false if it was not.
851          */
852         template<
853                 typename T,
854                 typename=is_supported_by_flagger<T>>
855         bool find(T *data) const {
856             using B = typename Flagger::template store<T>::as_type;
857             if (this->flags() == Flagger::flagFor((T*)0) ||
858                 Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
859                 _AData_copier<T>::assign(data, this->get().template get<B>());
860                 return true;
861             }
862             return false;
863         }
864 
865         /**
866          * Checks if there is an object of type T in this container. If there is, it moves that
867          * object into the provided address and returns true. Otherwise, it does nothing and returns
868          * false.
869          *
870          * This method normally requires a flag equality between the stored and retrieved types.
871          * However, it also allows retrieving the stored object as the stored type
872          * (usually base type).
873          *
874          * \param T type of object to sought
875          * \param data address at which the object should be retrieved.
876          *
877          * \return true if the object was retrieved. false if it was not.
878          */
879         template<
880                 typename T,
881                 typename=is_supported_by_flagger<T>>
882         bool remove(T *data) {
883             using B = typename Flagger::template store<T>::as_type;
884             if (this->flags() == Flagger::flagFor((T*)0) ||
885                 Flagger::canDeleteAs(this->flags(), Flagger::flagFor((T*)0))) {
886                 _AData_mover<T>::assign(data, std::move(this->get().template get<B>()));
887                 return true;
888             }
889             return false;
890         }
891 
892         /**
893          * Stores an object into this container by copying. If it was successful, returns true.
894          * Otherwise, (e.g. it could not destroy the already stored object) it returns false. This
895          * latter would be highly unexpected.
896          *
897          * \param T type of object to store
898          * \param data object to store
899          *
900          * \return true if the object was stored. false if it was not.
901          */
902         template<
903                 typename T,
904                 typename=is_supported_by_flagger<T>,
905                 typename=typename std::enable_if<
906                         std::is_copy_constructible<T>::value ||
907                         (std::is_default_constructible<T>::value &&
908                                 std::is_copy_assignable<T>::value)>::type>
909         bool set(const T &data) {
910             using B = typename Flagger::template store<T>::as_type;
911 
912             // if already contains an object of this type, simply assign
913             if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
914                 _AData_copier<B>::assign(&this->get().template get<B>(), data);
915                 return true;
916             } else if (this->used()) {
917                 // destroy previous object
918                 if (!this->clear()) {
919                     return false;
920                 }
921             }
922             this->get().template emplace<B>(data);
923             this->setFlags(Flagger::flagFor((T *)0));
924             return true;
925         }
926 
927         /**
928          * Moves an object into this container. If it was successful, returns true. Otherwise,
929          * (e.g. it could not destroy the already stored object) it returns false. This latter
930          * would be highly unexpected.
931          *
932          * \param T type of object to store
933          * \param data object to store
934          *
935          * \return true if the object was stored. false if it was not.
936          */
937         template<
938                 typename T,
939                 typename=is_supported_by_flagger<T>>
940         bool set(T &&data) {
941             using B = typename Flagger::template store<T>::as_type;
942 
943             // if already contains an object of this type, simply assign
944             if (this->flags() == Flagger::flagFor((T*)0) && std::is_same<T, B>::value) {
945                 _AData_mover<B>::assign(&this->get().template get<B>(), std::forward<T&&>(data));
946                 return true;
947             } else if (this->used()) {
948                 // destroy previous object
949                 if (!this->clear()) {
950                     return false;
951                 }
952             }
953             this->get().template emplace<B>(std::forward<T&&>(data));
954             this->setFlags(Flagger::flagFor((T *)0));
955             return true;
956         }
957     };
958 
959     /**
960      * Basic AData using the default type flagger and requested flag type.
961      *
962      * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
963      */
964     template<typename Flag>
965     using Strict = Custom<flagger<Flag>>;
966 
967     /**
968      * Basic AData using the default type flagger and uint32_t flag.
969      */
970     using Basic = Strict<uint32_t>;
971 
972     /**
973      * AData using the relaxed type flagger for max size and requested flag type.
974      *
975      * \param Flag desired flag type to use. Must be an unsigned and std::integral type.
976      */
977     template<typename Flag, size_t MaxSize = 1024, size_t Align = 4>
978     using Relaxed = Custom<relaxed_flagger<Flag, MaxSize, Align>>;
979 
980     /**
981      * Basic AData using the relaxed type flagger and uint32_t flag.
982      */
983     using RelaxedBasic = Relaxed<uint32_t>;
984 };
985 
986 }  // namespace android
987 
988 #endif  // STAGEFRIGHT_FOUNDATION_A_DATA_H_
989 
990