1 /*
2  * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef HISTREAMER_PLUGIN_COMMON_ANY_H
17 #define HISTREAMER_PLUGIN_COMMON_ANY_H
18 
19 #ifndef HST_ANY_WITH_RTTI
20 #ifndef HST_ANY_WITH_NO_RTTI
21 #define HST_ANY_WITH_NO_RTTI
22 #endif
23 #else
24 #ifdef HST_ANY_WITH_NO_RTTI
25 #undef HST_ANY_WITH_NO_RTTI
26 #endif
27 #endif
28 
29 #ifndef MEDIA_NO_OHOS
30 #ifndef MEDIA_OHOS
31 #define MEDIA_OHOS
32 #endif
33 #else
34 #ifdef MEDIA_OHOS
35 #undef MEDIA_OHOS
36 #endif
37 #endif
38 
39 #if defined(__clang__) || defined(__GNUC__)
40 #define CPP_STANDARD __cplusplus
41 #elif defined(_MSC_VER)
42 #define CPP_STANDARD _MSVC_LANG
43 #endif
44 
45 #if CPP_STANDARD >= 201103L
46 
47 #include <array>
48 #include <cstring>
49 #include "cpp_ext/type_cast_ext.h"
50 #include "securec.h"
51 #include <type_traits>
52 #include "message_parcel.h"
53 
54 namespace {
55 #if CPP_STANDARD < 201402L
56 template <typename T>
57 using decay_t = typename std::decay<T>::type;
58 
59 template <bool B, typename T = void>
60 using enable_if_t = typename std::enable_if<B, T>::type;
61 
62 template <bool B, typename T, typename F>
63 using conditional_t = typename std::conditional<B, T, F>::type;
64 
65 template <typename T>
66 using remove_cv_t = typename std::remove_cv<T>::type;
67 
68 template <typename T>
69 using remove_reference_t = typename std::remove_reference<T>::type;
70 #else
71 using std::decay_t;
72 using std::enable_if_t;
73 using std::conditional_t;
74 using std::remove_cv_t;
75 using std::remove_reference_t;
76 #endif
77 
78 constexpr size_t STACK_STORAGE_SIZE = 2 * sizeof(void*); // NOLINT: global var
79 
80 template <typename T>
81 struct IsTrivialStackStorable {
82     static constexpr bool value =
83         alignof(T) <= alignof(max_align_t) && std::is_trivially_copyable<T>::value && sizeof(T) <= STACK_STORAGE_SIZE;
84 };
85 
86 template <typename T>
87 struct IsStackStorable {
88     static constexpr bool value = alignof(T) <= alignof(max_align_t) && std::is_nothrow_move_constructible<T>::value &&
89         sizeof(T) <= STACK_STORAGE_SIZE;
90 };
91 
92 template <typename T>
93 struct IsValidCast {
94     static constexpr bool value = std::is_reference<T>::value || std::is_copy_constructible<T>::value;
95 };
96 } // namespace
97 namespace OHOS {
98 namespace Media {
99 
100 enum struct AnyValueType : int32_t {
101     INVALID_TYPE = 1,
102     BOOL,
103     INT8_T,
104     UINT8_T,
105     INT32_T,
106     UINT32_T,
107     INT64_T,
108     UINT64_T,
109     FLOAT,
110     DOUBLE,
111     VECTOR_UINT8,
112     VECTOR_UINT32,
113     STRING
114 };
115 /**
116  * @brief BadAnyCast exception, which is thrown when error occurs in AnyCast
117  *
118  * @since 1.0
119  * @version 1.0
120  */
121 class BadAnyCast : public std::bad_cast {
122 public:
what()123     const char* what() const noexcept override
124     {
125         return "bad any cast";
126     }
127 };
128 class Any;
129 template <typename T>
130 inline typename std::enable_if<std::is_enum<T>::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel& parcel);
131 template <typename T>
132 inline typename std::enable_if<!std::is_enum<T>::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel& parcel)
133 {
134     (void)value;
135     (void)parcel;
136     // current only support enum from parcel
137     return false;
138 }
139 template <typename T>
WriteValueToParcel(const T & value,MessageParcel & parcel)140 inline typename std::enable_if<std::is_enum<T>::value, bool>::type WriteValueToParcel(const T &value,
141                                                                                       MessageParcel &parcel)
142 {
143     parcel.WriteInt32(static_cast<int32_t>(value));
144     return true;
145 }
146 template <typename T>
147 inline typename std::enable_if<!std::is_enum<T>::value, bool>::type WriteValueToParcel(const T &value,
148                                                                                        MessageParcel &parcel)
149 {
150     (void)value;
151     (void)parcel;
152     // current only support write enum to parcel
153     return false;
154 }
155 template <typename T>
WriteValueToParcelInt64(const T & value,MessageParcel & parcel)156 inline typename std::enable_if<std::is_enum<T>::value, bool>::type WriteValueToParcelInt64(const T &value,
157                                                                                            MessageParcel &parcel)
158 {
159     parcel.WriteInt64(static_cast<int64_t>(value));
160     return true;
161 }
162 template <typename T>
163 inline typename std::enable_if<!std::is_enum<T>::value, bool>::type WriteValueToParcelInt64(const T &value,
164                                                                                             MessageParcel &parcel)
165 {
166     (void)value;
167     (void)parcel;
168     // current only support write enum to parcel
169     return false;
170 }
171 /**
172  * @brief This class describes a type-safe container for arbitrary type values which are copy constructible.
173  *
174  * @since 1.0
175  * @version 1.0
176  */
177 class Any final {
178 public:
Any()179     constexpr Any() noexcept
180     {
181     }
182 
Any(const Any & other)183     __attribute__((no_sanitize("cfi"))) Any(const Any &other) : functionTable_(other.functionTable_)
184     {
185         if (other.HasValue()) {
186             functionTable_->copy(storage_, other.storage_);
187         }
188     }
189 
Any(Any && other)190     __attribute__((no_sanitize("cfi"))) Any(Any &&other) noexcept : functionTable_(other.functionTable_)
191     {
192         if (other.HasValue()) {
193             functionTable_->move(storage_, other.storage_);
194             other.functionTable_ = nullptr;
195         }
196     }
197 
198     /**
199      * constructor from right reference value with type of ValueType.
200      *
201      * @tparam Type ValueType is not the same as Any itself. The decay type of ValueType must be copy constructible.
202      * @param value content
203      */
204     template <typename ValueType, enable_if_t<!std::is_same<decay_t<ValueType>, Any>::value &&
205         std::is_copy_constructible<decay_t<ValueType>>::value,
206         bool> = true>
Any(ValueType && value)207     Any(ValueType&& value) // NOLINT: explicit
208     {
209         DoEmplace<decay_t<ValueType>>(std::forward<ValueType>(value));
210     }
211 
212     Any& operator=(const Any& other)
213     {
214         *this = Any(other);
215         return *this;
216     }
217 
218     Any& operator=(Any&& other) noexcept
219     {
220         Reset();
221         MoveFrom(std::forward<Any>(other));
222         return *this;
223     }
224 
225     /**
226      * Assigns contents to Any.
227      *
228      * @tparam ValueType Type ValueType is not the same as Any itself. The decay type of ValueType must be copy
229      * constructible.
230      * @param value content
231      * @return
232      */
233     template <typename ValueType, enable_if_t<!std::is_same<decay_t<ValueType>, Any>::value &&
234         std::is_copy_constructible<decay_t<ValueType>>::value,
235         bool> = true>
236     Any& operator=(ValueType&& value)
237     {
238         *this = Any(std::forward<ValueType>(value));
239         return *this;
240     }
241 
242     /**
243      * Get TypeName From function info.
244      * @return Name of Type T
245      */
246     template<typename T>
GetTypeName()247     static constexpr std::string_view GetTypeName() noexcept
248     {
249         const char* functionInfo = __PRETTY_FUNCTION__ ;
250         return GetTypeNameFromFunctionInfo(functionInfo);
251     }
252 
253     template<typename T>
IsSameTypeWith(const Any & other)254     static bool IsSameTypeWith(const Any& other) noexcept
255     {
256 #ifndef HST_ANY_WITH_NO_RTTI
257         return other.SameTypeWith(typeid(T));
258 #else
259         return other.SameTypeWith(Any::GetTypeName<T>());
260 #endif
261     }
262 
~Any()263     ~Any()
264     {
265         Reset();
266     }
267 
268     /**
269      * Emplace one content with type of ValueType into object. The content is constructed by args.
270      *
271      * @tparam ValueType The decay type of ValueType must be constructible from args and copy constructible.
272      * @tparam Args args type
273      * @param args args
274      * @return content with type of decay ValueType
275      */
276     template <typename ValueType, typename... Args,
277         enable_if_t<std::is_constructible<decay_t<ValueType>, Args...>::value &&
278         std::is_copy_constructible<decay_t<ValueType>>::value,
279         bool> = true>
Emplace(Args &&...args)280     decay_t<ValueType>& Emplace(Args&&... args)
281     {
282         Reset();
283         return DoEmplace<decay_t<ValueType>>(std::forward<Args>(args)...);
284     }
285 
286     /**
287      * Emplace one content with type of ValueType into object. The content is constructed by il and args.
288      *
289      * @tparam ValueType type of conetent. The decay type of ValueType must be constructible from il and args and copy
290      * constructible
291      * @tparam U type of initializer list.
292      * @tparam Args type of other args
293      * @param il initializer list
294      * @param args args
295      * @return content with type of decay ValueType
296      */
297     template <typename ValueType, typename U, typename... Args,
298         enable_if_t<std::is_constructible<decay_t<ValueType>, std::initializer_list<U>&, Args...>::value &&
299         std::is_copy_constructible<decay_t<ValueType>>::value,
300         bool> = true>
Emplace(std::initializer_list<U> il,Args &&...args)301     decay_t<ValueType>& Emplace(std::initializer_list<U> il, Args&&... args)
302     {
303         Reset();
304         return DoEmplace<decay_t<ValueType>>(il, std::forward<Args>(args)...);
305     }
306 
307     /**
308      * Destroy the inner content if exists.
309      */
Reset()310     void __attribute__((no_sanitize("cfi"))) Reset() noexcept
311     {
312         if (HasValue()) {
313             functionTable_->destroy(storage_);
314             storage_.trivialStack_.fill(0);
315         }
316         functionTable_ = nullptr;
317     }
318 
319     /**
320      * swap contents of two any objects
321      *
322      * @param other object to swap with
323      */
Swap(Any & other)324     void Swap(Any& other) noexcept
325     {
326         Any tmp(std::move(*this));
327         *this = std::move(other);
328         other = std::move(tmp);
329     }
330 
331     /**
332      * Checks whether the object has one content.
333      *
334      * @return true if object has one content, otherwise false.
335      */
HasValue()336     bool HasValue() const noexcept
337     {
338         return IsFunctionTableValid();
339     }
340 
341 #ifndef HST_ANY_WITH_NO_RTTI
342     /**
343      * Get tye type_info of object
344      *
345      * @return type info of object
346      */
Type()347     const std::type_info& Type() const noexcept
348     {
349         if (!HasValue()) {
350             return typeid(void);
351         }
352         return functionTable_->type();
353     }
354 #else
TypeName()355     std::string_view __attribute__((no_sanitize("cfi"))) TypeName() const noexcept
356     {
357         if (!HasValue()) {
358             return "empty"; // no value
359         }
360         return functionTable_->type_name();
361     }
ToParcel(MessageParcel & parcel)362     bool __attribute__((no_sanitize("cfi"))) ToParcel(MessageParcel &parcel) const noexcept
363     {
364         if (!HasValue()) {
365             return false; // no value
366         }
367         return functionTable_->toParcel(this, parcel);
368     }
FromParcel(MessageParcel & parcel)369     bool __attribute__((no_sanitize("cfi"))) FromParcel(MessageParcel &parcel) const noexcept
370     {
371         return functionTable_->fromParcel(const_cast<Any *>(this), parcel);
372     }
373 #endif
374 
375 #ifndef HST_ANY_WITH_NO_RTTI
SameTypeWith(const std::type_info & otherInfo)376     bool SameTypeWith(const std::type_info& otherInfo) const noexcept
377     {
378         if (functionTable_ == nullptr) {
379             return false;
380         }
381         return IsSameType(functionTable_->type(), otherInfo);
382     }
383 #else
SameTypeWith(std::string_view otherTypeName)384     bool __attribute__((no_sanitize("cfi"))) SameTypeWith(std::string_view otherTypeName) const noexcept
385     {
386         if (functionTable_ == nullptr) {
387             return false;
388         }
389         return IsSameType(functionTable_->type_name(), otherTypeName);
390     }
391 #endif
392 
SameTypeWith(const Any & other)393     bool __attribute__((no_sanitize("cfi"))) SameTypeWith(const Any &other) const noexcept
394     {
395 #ifndef HST_ANY_WITH_NO_RTTI
396         return IsSameType(functionTable_->type(), other.Type());
397 #else
398         return IsSameType(functionTable_->type_name(), other.TypeName());
399 #endif
400     }
401 
402 private:
403     template <typename T>
404     friend const T* AnyCast(const Any* operand) noexcept;
405     template <typename T>
406     friend T* AnyCast(Any* operand) noexcept;
407     template <typename T>
408     friend bool AnyCast(const Any* operand, T& value) noexcept;
409 
410     union Storage {
411         using Stack = std::aligned_storage<STACK_STORAGE_SIZE, std::alignment_of<void*>::value>::type;
412         using Heap = void*;
413 
414         std::array<uint8_t, STACK_STORAGE_SIZE> trivialStack_;
415         Stack nonTrivialStack_;
416         Heap heap_;
417     };
418 
419     struct FunctionTable {
420 #ifndef HST_ANY_WITH_NO_RTTI
421         const std::type_info& (*type)() noexcept;
422 #else
423         std::string_view (*type_name)() noexcept;
424         bool (*toParcel)(const Any *operand, MessageParcel& parcel) noexcept;
425         bool (*fromParcel)(Any *operand, MessageParcel& parcel) noexcept;
426 #endif
427         void (*destroy)(Storage&) noexcept;
428         void (*copy)(Storage&, const Storage&) noexcept;
429         void (*move)(Storage&, Storage&) noexcept;
430         void* (*getPtr)(Storage&) noexcept;
431         const void* (*getConstPtr)(const Storage&) noexcept;
432     };
433     static bool BaseTypesToParcel(const Any *operand, MessageParcel& parcel) noexcept;
434     // returnValue : 0 -- success; 1 -- retry enum; 2 -- failed no retry
435     static int BaseTypesFromParcel(Any *operand, MessageParcel& parcel) noexcept;
436 
437     static std::string_view GetTypeNameFromFunctionInfo(const char* functionInfo) noexcept;
438 
439     template <typename T>
440     struct TrivialStackFunctionTable {
441 #ifndef HST_ANY_WITH_NO_RTTI
TypeTrivialStackFunctionTable442         static const std::type_info& Type() noexcept
443         {
444             return typeid(T);
445         }
446 #else
447         static std::string_view TypeName() noexcept
448         {
449             return GetTypeName<T>();
450         }
451         // Only support parcel enum value to int32_t except base types
452         static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept
453         {
454             if (BaseTypesToParcel(operand, parcel)) {
455                 return true;
456             }
457             if (sizeof(T) > sizeof(int64_t)) { // Only support enum
458                 return false;
459             }
460             if (sizeof(T) == sizeof(int64_t)) { //  support Int64 enum
461                 T value;
462                 if (AnyCast(operand, value)) {
463                     WriteValueToParcelInt64(value, parcel);
464                     return true;
465                 }
466                 return false;
467             }
468             T value;
469             if (AnyCast(operand, value)) {
470                 WriteValueToParcel(value, parcel);
471                 return true;
472             }
473             return false;
474         }
475 
476         static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept
477         {
478             int ret = BaseTypesFromParcel(operand, parcel);
479             if (ret == 0) {
480                 return true;
481             }
482             MakeAnyFromParcel<T>(*operand, parcel);
483             return true;
484         }
485 #endif
486 
DestroyTrivialStackFunctionTable487         static void Destroy(Storage& storage) noexcept
488         {
489             reinterpret_cast<T*>(storage.trivialStack_.data())->~T();
490         }
491 
CopyTrivialStackFunctionTable492         static void Copy(Storage& dest, const Storage& source) noexcept
493         {
494             // memcpy_s will always success in this function
495             (void)memcpy_s(GetPtr(dest), sizeof(Storage), GetConstPtr(source), sizeof(Storage));
496         }
497 
MoveTrivialStackFunctionTable498         static void Move(Storage& dest, Storage& source) noexcept
499         {
500             Copy(dest, source);
501             source.trivialStack_.fill(0);
502         }
503 
GetConstPtrTrivialStackFunctionTable504         static const void* GetConstPtr(const Storage& storage) noexcept
505         {
506             return reinterpret_cast<const void *>(storage.trivialStack_.data());
507         }
508 
GetPtrTrivialStackFunctionTable509         static void* GetPtr(Storage& storage) noexcept
510         {
511             return reinterpret_cast<void *>(storage.trivialStack_.data());
512         }
513     };
514 
515     template <typename T>
516     struct StackFunctionTable {
517 #ifndef HST_ANY_WITH_NO_RTTI
TypeStackFunctionTable518         static const std::type_info& Type() noexcept
519         {
520             return typeid(T);
521         }
522 #else
523         static std::string_view TypeName() noexcept
524         {
525             return GetTypeName<T>();
526         }
527         // Only support parcel enum value to int32_t except base types
528         static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept
529         {
530             if (BaseTypesToParcel(operand, parcel)) {
531                 return true;
532             }
533             if (sizeof(T) > sizeof(int64_t)) { // Only support enum
534                 return false;
535             }
536             if (sizeof(T) == sizeof(int64_t)) { //  support Int64 enum
537                 T value;
538                 if (AnyCast(operand, value)) {
539                     WriteValueToParcelInt64(value, parcel);
540                     return true;
541                 }
542                 return false;
543             }
544             T value;
545             if (AnyCast(operand, value)) {
546                 WriteValueToParcel(value, parcel);
547                 return true;
548             }
549             return false;
550         }
551 
552         static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept
553         {
554             int ret = BaseTypesFromParcel(operand, parcel);
555             if (ret == 0) {
556                 return true;
557             }
558             MakeAnyFromParcel<T>(*operand, parcel);
559             return true;
560         }
561 #endif
562 
DestroyStackFunctionTable563         static void Destroy(Storage& storage) noexcept
564         {
565             reinterpret_cast<T*>(GetPtr(storage))->~T(); // NOLINT: cast
566         }
567 
CopyStackFunctionTable568         static void Copy(Storage& dest, const Storage& source) noexcept
569         {
570             // NOLINTNEXTLINE: reinterpret_cast
571             new (reinterpret_cast<T*>(GetPtr(dest))) T(*reinterpret_cast<const T*>(GetConstPtr(source)));
572         }
573 
MoveStackFunctionTable574         static void Move(Storage& dest, Storage& source) noexcept
575         {
576             // NOLINTNEXTLINE: reinterpret_cast
577             new (reinterpret_cast<T*>(GetPtr(dest))) T(std::move(*reinterpret_cast<T*>(GetPtr(source))));
578             Destroy(source);
579         }
580 
GetConstPtrStackFunctionTable581         static const void* GetConstPtr(const Storage& storage) noexcept
582         {
583             return reinterpret_cast<const void*>(&storage.nonTrivialStack_);
584         }
585 
GetPtrStackFunctionTable586         static void* GetPtr(Storage& storage) noexcept
587         {
588             return reinterpret_cast<void*>(&storage.nonTrivialStack_);
589         }
590     };
591 
592     template <typename T>
593     struct HeapFunctionTable {
594 #ifndef HST_ANY_WITH_NO_RTTI
TypeHeapFunctionTable595         static const std::type_info& Type() noexcept
596         {
597             return typeid(T);
598         }
599 #else
600         static std::string_view TypeName() noexcept
601         {
602             return GetTypeName<T>();
603         }
604         // Only support parcel enum value to int32_t except base types
605         static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept
606         {
607             if (BaseTypesToParcel(operand, parcel)) {
608                 return true;
609             }
610             if (sizeof(T) > sizeof(int64_t)) { // Only support enum
611                 return false;
612             }
613             if (sizeof(T) == sizeof(int64_t)) { //  support Int64 enum
614                 T value;
615                 if (AnyCast(operand, value)) {
616                     WriteValueToParcelInt64(value, parcel);
617                     return true;
618                 }
619                 return false;
620             }
621             T value;
622             if (AnyCast(operand, value)) {
623                 WriteValueToParcel(value, parcel);
624                 return true;
625             }
626             return false;
627         }
628 
629         static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept
630         {
631             int ret = BaseTypesFromParcel(operand, parcel);
632             if (ret == 0) {
633                 return true;
634             }
635             MakeAnyFromParcel<T>(*operand, parcel);
636             return true;
637         }
638 #endif
639 
DestroyHeapFunctionTable640         static void Destroy(Storage& storage) noexcept
641         {
642             delete reinterpret_cast<T*>(storage.heap_); // NOLINT: cast
643             storage.heap_ = nullptr;
644         }
CopyHeapFunctionTable645         static void Copy(Storage& dest, const Storage& source) noexcept
646         {
647             dest.heap_ = new T(*reinterpret_cast<T*>(source.heap_)); // NOLINT: cast
648         }
MoveHeapFunctionTable649         static void Move(Storage& dest, Storage& source) noexcept
650         {
651             dest.heap_ = source.heap_;
652             source.heap_ = nullptr;
653         }
GetConstPtrHeapFunctionTable654         static const void* GetConstPtr(const Storage& storage) noexcept
655         {
656             return storage.heap_;
657         }
GetPtrHeapFunctionTable658         static void* GetPtr(Storage& storage) noexcept
659         {
660             return storage.heap_;
661         }
662     };
663 
664     template <typename ValueType>
GetFunctionTable()665     static FunctionTable* GetFunctionTable()
666     {
667         using DecayedValueType = decay_t<ValueType>;
668         using DetailFunctionTable =
669             conditional_t<IsTrivialStackStorable<DecayedValueType>::value,
670             TrivialStackFunctionTable<DecayedValueType>,
671             conditional_t<IsStackStorable<DecayedValueType>::value,
672             StackFunctionTable<DecayedValueType>, HeapFunctionTable<DecayedValueType>>>;
673         static FunctionTable table = {
674 #ifndef HST_ANY_WITH_NO_RTTI
675             .type = DetailFunctionTable::Type,
676 #else
677             .type_name = DetailFunctionTable::TypeName,
678             .toParcel = DetailFunctionTable::ToParcel,
679             .fromParcel = DetailFunctionTable::FromParcel,
680 #endif
681             .destroy = DetailFunctionTable::Destroy,
682             .copy = DetailFunctionTable::Copy,
683             .move = DetailFunctionTable::Move,
684             .getPtr = DetailFunctionTable::GetPtr,
685             .getConstPtr = DetailFunctionTable::GetConstPtr,
686         };
687         return &table;
688     }
689 
IsFunctionTableValid()690     bool IsFunctionTableValid() const noexcept
691     {
692         return functionTable_ != nullptr;
693     }
694 
695     template <typename DecayedValueType, typename... Args>
DoEmplace(Args &&...args)696     DecayedValueType &__attribute__((no_sanitize("cfi"))) DoEmplace(Args &&...args)
697     {
698         functionTable_ = GetFunctionTable<DecayedValueType>();
699         DecayedValueType* ptr = nullptr;
700         if (IsTrivialStackStorable<DecayedValueType>::value || IsStackStorable<DecayedValueType>::value) {
701             ptr = reinterpret_cast<DecayedValueType*>(functionTable_->getPtr(storage_));
702             new (ptr) DecayedValueType(std::forward<Args>(args)...);
703         } else {
704             storage_.heap_ = new DecayedValueType(std::forward<Args>(args)...);
705             ptr = reinterpret_cast<DecayedValueType*>(storage_.heap_);
706         }
707         return *ptr;
708     }
709 
MoveFrom(Any && other)710     void __attribute__((no_sanitize("cfi"))) MoveFrom(Any &&other) noexcept
711     {
712         if (other.HasValue()) {
713             functionTable_ = other.functionTable_;
714             functionTable_->move(storage_, other.storage_);
715             other.Reset();
716         }
717     }
718 
719     template <typename ValueType>
Cast()720     ValueType* Cast() noexcept
721     {
722         using DecayedValueType = decay_t<ValueType>;
723         if (!IsFunctionTableValid()) {
724             return nullptr;
725         }
726 #ifndef HST_ANY_WITH_NO_RTTI
727         if (!SameTypeWith(typeid(DecayedValueType))) {
728 #else
729         if (!SameTypeWith(Any::GetTypeName<DecayedValueType>())) {
730 #endif
731             return nullptr;
732         }
733         return IsTrivialStackStorable<DecayedValueType>::value
734             ? reinterpret_cast<DecayedValueType*>(storage_.trivialStack_.data())
735             : (IsStackStorable<DecayedValueType>::value
736             ? reinterpret_cast<DecayedValueType*>(&storage_.nonTrivialStack_)
737             : reinterpret_cast<DecayedValueType*>(storage_.heap_));
738     }
739     template <typename ValueType>
740     const ValueType* Cast() const noexcept
741     {
742         using DecayedValueType = decay_t<ValueType>;
743         if (!IsFunctionTableValid()) {
744             return nullptr;
745         }
746 #ifndef HST_ANY_WITH_NO_RTTI
747         if (!SameTypeWith(typeid(DecayedValueType))) {
748 #else
749             if (!SameTypeWith(Any::GetTypeName<DecayedValueType>())) {
750 #endif
751             return nullptr;
752         }
753         return IsTrivialStackStorable<DecayedValueType>::value
754             ? reinterpret_cast<const DecayedValueType*>(storage_.trivialStack_.data())
755             : (IsStackStorable<DecayedValueType>::value
756             ? reinterpret_cast<const DecayedValueType*>(&storage_.nonTrivialStack_)
757             : reinterpret_cast<const DecayedValueType*>(storage_.heap_));
758     }
759 
760 private:
761     Storage storage_ {};
762     FunctionTable* functionTable_ {nullptr};
763 };
764 
765 /**
766  * cast one Any pointer into ValueType pointer
767  *
768  * @tparam ValueType target value type
769  * @param operand any object
770  * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the
771  * const value contained by operand.
772  */
773 template <typename ValueType>
774 const ValueType* AnyCast(const Any* operand) noexcept
775 {
776     static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
777     if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
778         return nullptr;
779     }
780     return operand->Cast<ValueType>();
781 }
782 
783  /**
784   * cast one Any pointer into ValueType object
785   *
786   * @tparam ValueType target value type
787   * @param operand any object
788   * @param value ValueType
789   * @return false if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, true to the
790   *  value contained by operand.
791   */
792 template <typename ValueType>
793 bool AnyCast(const Any* operand, ValueType& value) noexcept
794 {
795     static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
796     if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
797         return false;
798     }
799 #ifndef HST_ANY_WITH_NO_RTTI
800     if (!operand->SameTypeWith(typeid(ValueType))) {
801 #else
802         if (!operand->SameTypeWith(Any::GetTypeName<ValueType>())) {
803 #endif
804         return false;
805     } else {
806         auto casted_value = operand->Cast<ValueType>();
807         if (casted_value != nullptr) {
808             value = *casted_value;
809             return true;
810         }
811         return false;
812     }
813 }
814 
815 /**
816  * cast one Any pointer into ValueType pointer
817  *
818  * @tparam ValueType target value type
819  * @param operand any object
820  * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the
821  * value contained by operand.
822  */
823 template <typename ValueType>
824 ValueType* AnyCast(Any* operand) noexcept
825 {
826     static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
827     if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
828         return nullptr;
829     }
830     return operand->Cast<ValueType>();
831 }
832 
833 /**
834  * cast one Any object into ValueType object
835  *
836  * @tparam ValueType target value type. It must match both conditions:
837  * 1. ValueType must be reference or constructible
838  * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, const U&> must be true
839  * @param operand any object
840  * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
841  * one object of ValueType contained in Any.
842  */
843 template <typename ValueType>
844 ValueType AnyCast(const Any& other)
845 {
846     using U = remove_cv_t<remove_reference_t<ValueType>>;
847     static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
848     static_assert(std::is_constructible<ValueType, const U&>::value,
849                   "any_cast<ValueType>(const any&) requires ValueType constructable from const "
850                   "remove_cv_t<remove_reference_t<ValueType>>&");
851     auto ptr = AnyCast<U>(&other);
852     return static_cast<ValueType>(*ptr);
853 }
854 
855 /**
856  * cast one Any object into ValueType object
857  *
858  * @tparam ValueType target value type. It must match both conditions:
859  * 1. ValueType must be reference or constructible
860  * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, U&> must be true
861  * @param operand any object
862  * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
863  * one object of ValueType contained in Any.
864  */
865 template <typename ValueType>
866 ValueType AnyCast(Any& other)
867 {
868     using U = remove_cv_t<remove_reference_t<ValueType>>;
869     static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
870     static_assert(std::is_constructible<ValueType, U&>::value,
871                   "any_cast<ValueType>(const any&) requires ValueType constructable from "
872                   "remove_cv_t<remove_reference_t<ValueType>>&");
873     auto ptr = AnyCast<U>(&other);
874     return static_cast<ValueType>(*ptr);
875 }
876 
877 /**
878  * cast one Any object into ValueType object
879  *
880  * @tparam ValueType target value type. It must match both conditions:
881  * 1. ValueType must be reference or constructible
882  * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, U> must be true
883  * @param operand any object
884  * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
885  * one object of ValueType contained in Any.
886  */
887 template <typename ValueType>
888 ValueType AnyCast(Any&& other)
889 {
890     using U = remove_cv_t<remove_reference_t<ValueType>>;
891     static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
892     static_assert(std::is_constructible<ValueType, U>::value,
893                   "any_cast<ValueType>(const any&) requires ValueType constructable from "
894                   "remove_cv_t<remove_reference_t<ValueType>>");
895     auto ptr = AnyCast<U>(&other);
896     return static_cast<ValueType>(std::move(*ptr));
897 }
898 
899 /**
900  * Constructs Any object, whose content is constructed by args. The content type is T.
901  *
902  * @tparam T type of Any's content
903  * @tparam Args type of args
904  * @param args args used to construct the content
905  * @return Any object
906  */
907 template <typename T, typename... Args>
908 Any MakeAny(Args&&... args)
909 {
910     Any tmp;
911     tmp.Emplace<T, Args...>(std::forward<Args>(args)...);
912     return tmp;
913 }
914 
915 /**
916  * Constructs Any object, whose content is constructed by il and args. The content type is T.
917  *
918  * @tparam T type of Any's content
919  * @tparam U type of initializer list
920  * @tparam Args type of args
921  * @param il initializer list
922  * @param args args
923  * @return Any object
924  */
925 template <typename T, typename U, typename... Args>
926 Any MakeAny(std::initializer_list<U> il, Args&&... args)
927 {
928     Any tmp;
929     tmp.Emplace<T, U, Args...>(il, std::forward<Args>(args)...);
930     return tmp;
931 }
932 
933 template <typename T>
934 inline typename std::enable_if<std::is_enum<T>::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel
935 & parcel)
936 {
937     if (sizeof(T) == sizeof(int64_t)) {
938         value.Emplace<T>(static_cast<T>(parcel.ReadInt64()));
939         return true;
940     }
941     value.Emplace<T>(static_cast<T>(parcel.ReadInt32()));
942     return true;
943 }
944 } // namespace Media
945 } // namespace OHOS
946 #endif
947 namespace std {
swap(OHOS::Media::Any & lhs,OHOS::Media::Any & rhs)948 inline void swap(OHOS::Media::Any& lhs, OHOS::Media::Any& rhs) noexcept
949 {
950     lhs.Swap(rhs);
951 }
952 } // namespace std
953 #endif // HISTREAMER_PLUGIN_COMMON_ANY_H
954