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
31namespace 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 */
84struct 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>
96    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>
112    inline static void del(T *addr) {
113        addr->~T();
114    }
115};
116
117/** Constructor specialization for void type */
118template<>
119HIDE inline void _AUnion_impl::emplace<void>(size_t totalSize, void *addr) {
120    memset(addr, 0, totalSize);
121}
122
123/** Destructor specialization for void type */
124template<>
125HIDE 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 */
142template<typename ...Ts>
143struct AUnion {
144private:
145    using _type = typename std::aligned_union<0, Ts...>::type; ///< storage type
146    _type mValue;                                              ///< storage
147
148public:
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>
163    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>
180    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>
195    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>
208    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 */
224template<
225        typename T,
226        bool=std::is_copy_assignable<T>::value>
227struct 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     */
236    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>>>
247    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>>>
252    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>>>
258    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>>>
264    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>>>
269    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>>>
275    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>
287    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 */
299template<typename T>
300struct 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 */
321template<
322        typename T,
323        bool=std::is_move_assignable<T>::value>
324struct 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 */
394template<typename T>
395struct 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 */
412template<typename Flagger, typename U, typename ...Ts>
413struct HIDE _AData_deleter;
414
415/**
416 * Template specialization when there are still types to consider (T and rest)
417 */
418template<typename Flagger, typename U, typename T, typename ...Ts>
419struct 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 */
432template<typename Flagger, typename U>
433struct 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 */
447template<typename Flagger, typename U, typename ...Ts>
448struct HIDE _AData_copy_assigner;
449
450/**
451 * Template specialization when there are still types to consider (T and rest)
452 */
453template<typename Flagger, typename U, typename T, typename ...Ts>
454struct 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 */
469template<typename Flagger, typename U>
470struct 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 */
484template<typename Flagger, typename U, typename ...Ts>
485struct HIDE _AData_move_assigner;
486
487/**
488 * Template specialization when there are still types to consider (T and rest)
489 */
490template<typename Flagger, typename U, typename T, typename ...Ts>
491struct 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 */
520template<typename Flagger, typename U>
521struct 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 */
547template<typename ...Ts>
548struct AData {
549private:
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
554public:
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) {
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) : 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