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