• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * @brief BadAnyCast exception, which is thrown when error occurs in AnyCast
101  *
102  * @since 1.0
103  * @version 1.0
104  */
105 class BadAnyCast : public std::bad_cast {
106 public:
what()107     const char* what() const noexcept override
108     {
109         return "bad any cast";
110     }
111 };
112 class Any;
113 template <typename T>
114 inline typename std::enable_if<std::is_enum<T>::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel& parcel);
115 template <typename T>
MakeAnyFromParcel(Any & value,MessageParcel & parcel)116 inline typename std::enable_if<!std::is_enum<T>::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel& parcel)
117 {
118     (void)value;
119     (void)parcel;
120     // current only support enum from parcel
121     return false;
122 }
123 template <typename T>
WriteValueToParcel(const T & value,MessageParcel & parcel)124 inline typename std::enable_if<std::is_enum<T>::value, bool>::type WriteValueToParcel(const T &value,
125                                                                                       MessageParcel &parcel)
126 {
127     parcel.WriteInt32(static_cast<int32_t>(value));
128     return true;
129 }
130 template <typename T>
WriteValueToParcel(const T & value,MessageParcel & parcel)131 inline typename std::enable_if<!std::is_enum<T>::value, bool>::type WriteValueToParcel(const T &value,
132                                                                                        MessageParcel &parcel)
133 {
134     (void)value;
135     (void)parcel;
136     // current only support write enum to parcel
137     return false;
138 }
139 template <typename T>
WriteValueToParcelInt64(const T & value,MessageParcel & parcel)140 inline typename std::enable_if<std::is_enum<T>::value, bool>::type WriteValueToParcelInt64(const T &value,
141                                                                                            MessageParcel &parcel)
142 {
143     parcel.WriteInt64(static_cast<int64_t>(value));
144     return true;
145 }
146 template <typename T>
WriteValueToParcelInt64(const T & value,MessageParcel & parcel)147 inline typename std::enable_if<!std::is_enum<T>::value, bool>::type WriteValueToParcelInt64(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 /**
156  * @brief This class describes a type-safe container for arbitrary type values which are copy constructible.
157  *
158  * @since 1.0
159  * @version 1.0
160  */
161 class Any final {
162 public:
Any()163     constexpr Any() noexcept
164     {
165     }
166 
Any(const Any & other)167     __attribute__((no_sanitize("cfi"))) Any(const Any &other) : functionTable_(other.functionTable_)
168     {
169         if (other.HasValue()) {
170             functionTable_->copy(storage_, other.storage_);
171         }
172     }
173 
Any(Any && other)174     __attribute__((no_sanitize("cfi"))) Any(Any &&other) noexcept : functionTable_(other.functionTable_)
175     {
176         if (other.HasValue()) {
177             functionTable_->move(storage_, other.storage_);
178             other.functionTable_ = nullptr;
179         }
180     }
181 
182     /**
183      * constructor from right reference value with type of ValueType.
184      *
185      * @tparam Type ValueType is not the same as Any itself. The decay type of ValueType must be copy constructible.
186      * @param value content
187      */
188     template <typename ValueType, enable_if_t<!std::is_same<decay_t<ValueType>, Any>::value &&
189         std::is_copy_constructible<decay_t<ValueType>>::value,
190         bool> = true>
Any(ValueType && value)191     Any(ValueType&& value) // NOLINT: explicit
192     {
193         DoEmplace<decay_t<ValueType>>(std::forward<ValueType>(value));
194     }
195 
196     Any& operator=(const Any& other)
197     {
198         *this = Any(other);
199         return *this;
200     }
201 
202     Any& operator=(Any&& other) noexcept
203     {
204         Reset();
205         MoveFrom(std::forward<Any>(other));
206         return *this;
207     }
208 
209     /**
210      * Assigns contents to Any.
211      *
212      * @tparam ValueType Type ValueType is not the same as Any itself. The decay type of ValueType must be copy
213      * constructible.
214      * @param value content
215      * @return
216      */
217     template <typename ValueType, enable_if_t<!std::is_same<decay_t<ValueType>, Any>::value &&
218         std::is_copy_constructible<decay_t<ValueType>>::value,
219         bool> = true>
220     Any& operator=(ValueType&& value)
221     {
222         *this = Any(std::forward<ValueType>(value));
223         return *this;
224     }
225 
226     /**
227      * Get TypeName From function info.
228      * @return Name of Type T
229      */
230     template<typename T>
GetTypeName()231     static constexpr std::string_view GetTypeName() noexcept
232     {
233         const char* functionInfo = __PRETTY_FUNCTION__ ;
234         return GetTypeNameFromFunctionInfo(functionInfo);
235     }
236 
237     template<typename T>
IsSameTypeWith(const Any & other)238     static bool IsSameTypeWith(const Any& other) noexcept
239     {
240 #ifndef HST_ANY_WITH_NO_RTTI
241         return other.SameTypeWith(typeid(T));
242 #else
243         return other.SameTypeWith(Any::GetTypeName<T>());
244 #endif
245     }
246 
~Any()247     ~Any()
248     {
249         Reset();
250     }
251 
252     /**
253      * Emplace one content with type of ValueType into object. The content is constructed by args.
254      *
255      * @tparam ValueType The decay type of ValueType must be constructible from args and copy constructible.
256      * @tparam Args args type
257      * @param args args
258      * @return content with type of decay ValueType
259      */
260     template <typename ValueType, typename... Args,
261         enable_if_t<std::is_constructible<decay_t<ValueType>, Args...>::value &&
262         std::is_copy_constructible<decay_t<ValueType>>::value,
263         bool> = true>
Emplace(Args &&...args)264     decay_t<ValueType>& Emplace(Args&&... args)
265     {
266         Reset();
267         return DoEmplace<decay_t<ValueType>>(std::forward<Args>(args)...);
268     }
269 
270     /**
271      * Emplace one content with type of ValueType into object. The content is constructed by il and args.
272      *
273      * @tparam ValueType type of conetent. The decay type of ValueType must be constructible from il and args and copy
274      * constructible
275      * @tparam U type of initializer list.
276      * @tparam Args type of other args
277      * @param il initializer list
278      * @param args args
279      * @return content with type of decay ValueType
280      */
281     template <typename ValueType, typename U, typename... Args,
282         enable_if_t<std::is_constructible<decay_t<ValueType>, std::initializer_list<U>&, Args...>::value &&
283         std::is_copy_constructible<decay_t<ValueType>>::value,
284         bool> = true>
Emplace(std::initializer_list<U> il,Args &&...args)285     decay_t<ValueType>& Emplace(std::initializer_list<U> il, Args&&... args)
286     {
287         Reset();
288         return DoEmplace<decay_t<ValueType>>(il, std::forward<Args>(args)...);
289     }
290 
291     /**
292      * Destroy the inner content if exists.
293      */
Reset()294     void __attribute__((no_sanitize("cfi"))) Reset() noexcept
295     {
296         if (HasValue()) {
297             functionTable_->destroy(storage_);
298             storage_.trivialStack_.fill(0);
299         }
300         functionTable_ = nullptr;
301     }
302 
303     /**
304      * swap contents of two any objects
305      *
306      * @param other object to swap with
307      */
Swap(Any & other)308     void Swap(Any& other) noexcept
309     {
310         Any tmp(std::move(*this));
311         *this = std::move(other);
312         other = std::move(tmp);
313     }
314 
315     /**
316      * Checks whether the object has one content.
317      *
318      * @return true if object has one content, otherwise false.
319      */
HasValue()320     bool HasValue() const noexcept
321     {
322         return IsFunctionTableValid();
323     }
324 
325 #ifndef HST_ANY_WITH_NO_RTTI
326     /**
327      * Get tye type_info of object
328      *
329      * @return type info of object
330      */
Type()331     const std::type_info& Type() const noexcept
332     {
333         if (!HasValue()) {
334             return typeid(void);
335         }
336         return functionTable_->type();
337     }
338 #else
TypeName()339     std::string_view __attribute__((no_sanitize("cfi"))) TypeName() const noexcept
340     {
341         if (!HasValue()) {
342             return "empty"; // no value
343         }
344         return functionTable_->type_name();
345     }
ToParcel(MessageParcel & parcel)346     bool __attribute__((no_sanitize("cfi"))) ToParcel(MessageParcel &parcel) const noexcept
347     {
348         if (!HasValue()) {
349             return false; // no value
350         }
351         return functionTable_->toParcel(this, parcel);
352     }
FromParcel(MessageParcel & parcel)353     bool __attribute__((no_sanitize("cfi"))) FromParcel(MessageParcel &parcel) const noexcept
354     {
355         return functionTable_->fromParcel(const_cast<Any *>(this), parcel);
356     }
357 #endif
358 
359 #ifndef HST_ANY_WITH_NO_RTTI
SameTypeWith(const std::type_info & otherInfo)360     bool SameTypeWith(const std::type_info& otherInfo) const noexcept
361     {
362         if (functionTable_ == nullptr) {
363             return false;
364         }
365         return IsSameType(functionTable_->type(), otherInfo);
366     }
367 #else
SameTypeWith(std::string_view otherTypeName)368     bool __attribute__((no_sanitize("cfi"))) SameTypeWith(std::string_view otherTypeName) const noexcept
369     {
370         if (functionTable_ == nullptr) {
371             return false;
372         }
373         return IsSameType(functionTable_->type_name(), otherTypeName);
374     }
375 #endif
376 
SameTypeWith(const Any & other)377     bool __attribute__((no_sanitize("cfi"))) SameTypeWith(const Any &other) const noexcept
378     {
379 #ifndef HST_ANY_WITH_NO_RTTI
380         return IsSameType(functionTable_->type(), other.Type());
381 #else
382         return IsSameType(functionTable_->type_name(), other.TypeName());
383 #endif
384     }
385 
386 private:
387     template <typename T>
388     friend const T* AnyCast(const Any* operand) noexcept;
389     template <typename T>
390     friend T* AnyCast(Any* operand) noexcept;
391     template <typename T>
392     friend bool AnyCast(const Any* operand, T& value) noexcept;
393 
394     union Storage {
395         using Stack = std::aligned_storage<STACK_STORAGE_SIZE, std::alignment_of<void*>::value>::type;
396         using Heap = void*;
397 
398         std::array<uint8_t, STACK_STORAGE_SIZE> trivialStack_;
399         Stack nonTrivialStack_;
400         Heap heap_;
401     };
402 
403     struct FunctionTable {
404 #ifndef HST_ANY_WITH_NO_RTTI
405         const std::type_info& (*type)() noexcept;
406 #else
407         std::string_view (*type_name)() noexcept;
408         bool (*toParcel)(const Any *operand, MessageParcel& parcel) noexcept;
409         bool (*fromParcel)(Any *operand, MessageParcel& parcel) noexcept;
410 #endif
411         void (*destroy)(Storage&) noexcept;
412         void (*copy)(Storage&, const Storage&) noexcept;
413         void (*move)(Storage&, Storage&) noexcept;
414         void* (*getPtr)(Storage&) noexcept;
415         const void* (*getConstPtr)(const Storage&) noexcept;
416     };
417     static bool BaseTypesToParcel(const Any *operand, MessageParcel& parcel) noexcept;
418     // returnValue : 0 -- success; 1 -- retry enum; 2 -- failed no retry
419     static int BaseTypesFromParcel(Any *operand, MessageParcel& parcel) noexcept;
420 
421     static std::string_view GetTypeNameFromFunctionInfo(const char* functionInfo) noexcept;
422 
423     template <typename T>
424     struct TrivialStackFunctionTable {
425 #ifndef HST_ANY_WITH_NO_RTTI
TypeTrivialStackFunctionTable426         static const std::type_info& Type() noexcept
427         {
428             return typeid(T);
429         }
430 #else
431         static std::string_view TypeName() noexcept
432         {
433             return GetTypeName<T>();
434         }
435         // Only support parcel enum value to int32_t except base types
436         static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept
437         {
438             if (BaseTypesToParcel(operand, parcel)) {
439                 return true;
440             }
441             if (sizeof(T) > sizeof(int64_t)) { // Only support enum
442                 return false;
443             }
444             if (sizeof(T) == sizeof(int64_t)) { //  support Int64 enum
445                 T value;
446                 if (AnyCast(operand, value)) {
447                     WriteValueToParcelInt64(value, parcel);
448                     return true;
449                 }
450                 return false;
451             }
452             T value;
453             if (AnyCast(operand, value)) {
454                 WriteValueToParcel(value, parcel);
455                 return true;
456             }
457             return false;
458         }
459 
460         static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept
461         {
462             int ret = BaseTypesFromParcel(operand, parcel);
463             if (ret == 0) {
464                 return true;
465             }
466             MakeAnyFromParcel<T>(*operand, parcel);
467             return true;
468         }
469 #endif
470 
DestroyTrivialStackFunctionTable471         static void Destroy(Storage& storage) noexcept
472         {
473             reinterpret_cast<T*>(storage.trivialStack_.data())->~T();
474         }
475 
CopyTrivialStackFunctionTable476         static void Copy(Storage& dest, const Storage& source) noexcept
477         {
478             // memcpy_s will always success in this function
479             (void)memcpy_s(GetPtr(dest), sizeof(Storage), GetConstPtr(source), sizeof(Storage));
480         }
481 
MoveTrivialStackFunctionTable482         static void Move(Storage& dest, Storage& source) noexcept
483         {
484             Copy(dest, source);
485             source.trivialStack_.fill(0);
486         }
487 
GetConstPtrTrivialStackFunctionTable488         static const void* GetConstPtr(const Storage& storage) noexcept
489         {
490             return reinterpret_cast<const void *>(storage.trivialStack_.data());
491         }
492 
GetPtrTrivialStackFunctionTable493         static void* GetPtr(Storage& storage) noexcept
494         {
495             return reinterpret_cast<void *>(storage.trivialStack_.data());
496         }
497     };
498 
499     template <typename T>
500     struct StackFunctionTable {
501 #ifndef HST_ANY_WITH_NO_RTTI
TypeStackFunctionTable502         static const std::type_info& Type() noexcept
503         {
504             return typeid(T);
505         }
506 #else
507         static std::string_view TypeName() noexcept
508         {
509             return GetTypeName<T>();
510         }
511         // Only support parcel enum value to int32_t except base types
512         static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept
513         {
514             if (BaseTypesToParcel(operand, parcel)) {
515                 return true;
516             }
517             if (sizeof(T) > sizeof(int64_t)) { // Only support enum
518                 return false;
519             }
520             if (sizeof(T) == sizeof(int64_t)) { //  support Int64 enum
521                 T value;
522                 if (AnyCast(operand, value)) {
523                     WriteValueToParcelInt64(value, parcel);
524                     return true;
525                 }
526                 return false;
527             }
528             T value;
529             if (AnyCast(operand, value)) {
530                 WriteValueToParcel(value, parcel);
531                 return true;
532             }
533             return false;
534         }
535 
536         static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept
537         {
538             int ret = BaseTypesFromParcel(operand, parcel);
539             if (ret == 0) {
540                 return true;
541             }
542             MakeAnyFromParcel<T>(*operand, parcel);
543             return true;
544         }
545 #endif
546 
DestroyStackFunctionTable547         static void Destroy(Storage& storage) noexcept
548         {
549             reinterpret_cast<T*>(GetPtr(storage))->~T(); // NOLINT: cast
550         }
551 
CopyStackFunctionTable552         static void Copy(Storage& dest, const Storage& source) noexcept
553         {
554             // NOLINTNEXTLINE: reinterpret_cast
555             new (reinterpret_cast<T*>(GetPtr(dest))) T(*reinterpret_cast<const T*>(GetConstPtr(source)));
556         }
557 
MoveStackFunctionTable558         static void Move(Storage& dest, Storage& source) noexcept
559         {
560             // NOLINTNEXTLINE: reinterpret_cast
561             new (reinterpret_cast<T*>(GetPtr(dest))) T(std::move(*reinterpret_cast<T*>(GetPtr(source))));
562             Destroy(source);
563         }
564 
GetConstPtrStackFunctionTable565         static const void* GetConstPtr(const Storage& storage) noexcept
566         {
567             return reinterpret_cast<const void*>(&storage.nonTrivialStack_);
568         }
569 
GetPtrStackFunctionTable570         static void* GetPtr(Storage& storage) noexcept
571         {
572             return reinterpret_cast<void*>(&storage.nonTrivialStack_);
573         }
574     };
575 
576     template <typename T>
577     struct HeapFunctionTable {
578 #ifndef HST_ANY_WITH_NO_RTTI
TypeHeapFunctionTable579         static const std::type_info& Type() noexcept
580         {
581             return typeid(T);
582         }
583 #else
584         static std::string_view TypeName() noexcept
585         {
586             return GetTypeName<T>();
587         }
588         // Only support parcel enum value to int32_t except base types
589         static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept
590         {
591             if (BaseTypesToParcel(operand, parcel)) {
592                 return true;
593             }
594             if (sizeof(T) > sizeof(int64_t)) { // Only support enum
595                 return false;
596             }
597             if (sizeof(T) == sizeof(int64_t)) { //  support Int64 enum
598                 T value;
599                 if (AnyCast(operand, value)) {
600                     WriteValueToParcelInt64(value, parcel);
601                     return true;
602                 }
603                 return false;
604             }
605             T value;
606             if (AnyCast(operand, value)) {
607                 WriteValueToParcel(value, parcel);
608                 return true;
609             }
610             return false;
611         }
612 
613         static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept
614         {
615             int ret = BaseTypesFromParcel(operand, parcel);
616             if (ret == 0) {
617                 return true;
618             }
619             MakeAnyFromParcel<T>(*operand, parcel);
620             return true;
621         }
622 #endif
623 
DestroyHeapFunctionTable624         static void Destroy(Storage& storage) noexcept
625         {
626             delete reinterpret_cast<T*>(storage.heap_); // NOLINT: cast
627             storage.heap_ = nullptr;
628         }
CopyHeapFunctionTable629         static void Copy(Storage& dest, const Storage& source) noexcept
630         {
631             dest.heap_ = new T(*reinterpret_cast<T*>(source.heap_)); // NOLINT: cast
632         }
MoveHeapFunctionTable633         static void Move(Storage& dest, Storage& source) noexcept
634         {
635             dest.heap_ = source.heap_;
636             source.heap_ = nullptr;
637         }
GetConstPtrHeapFunctionTable638         static const void* GetConstPtr(const Storage& storage) noexcept
639         {
640             return storage.heap_;
641         }
GetPtrHeapFunctionTable642         static void* GetPtr(Storage& storage) noexcept
643         {
644             return storage.heap_;
645         }
646     };
647 
648     template <typename ValueType>
GetFunctionTable()649     static FunctionTable* GetFunctionTable()
650     {
651         using DecayedValueType = decay_t<ValueType>;
652         using DetailFunctionTable =
653             conditional_t<IsTrivialStackStorable<DecayedValueType>::value,
654             TrivialStackFunctionTable<DecayedValueType>,
655             conditional_t<IsStackStorable<DecayedValueType>::value,
656             StackFunctionTable<DecayedValueType>, HeapFunctionTable<DecayedValueType>>>;
657         static FunctionTable table = {
658 #ifndef HST_ANY_WITH_NO_RTTI
659             .type = DetailFunctionTable::Type,
660 #else
661             .type_name = DetailFunctionTable::TypeName,
662             .toParcel = DetailFunctionTable::ToParcel,
663             .fromParcel = DetailFunctionTable::FromParcel,
664 #endif
665             .destroy = DetailFunctionTable::Destroy,
666             .copy = DetailFunctionTable::Copy,
667             .move = DetailFunctionTable::Move,
668             .getPtr = DetailFunctionTable::GetPtr,
669             .getConstPtr = DetailFunctionTable::GetConstPtr,
670         };
671         return &table;
672     }
673 
IsFunctionTableValid()674     bool IsFunctionTableValid() const noexcept
675     {
676         return functionTable_ != nullptr;
677     }
678 
679     template <typename DecayedValueType, typename... Args>
DoEmplace(Args &&...args)680     DecayedValueType &__attribute__((no_sanitize("cfi"))) DoEmplace(Args &&...args)
681     {
682         functionTable_ = GetFunctionTable<DecayedValueType>();
683         DecayedValueType* ptr = nullptr;
684         if (IsTrivialStackStorable<DecayedValueType>::value || IsStackStorable<DecayedValueType>::value) {
685             ptr = reinterpret_cast<DecayedValueType*>(functionTable_->getPtr(storage_));
686             new (ptr) DecayedValueType(std::forward<Args>(args)...);
687         } else {
688             storage_.heap_ = new DecayedValueType(std::forward<Args>(args)...);
689             ptr = reinterpret_cast<DecayedValueType*>(storage_.heap_);
690         }
691         return *ptr;
692     }
693 
MoveFrom(Any && other)694     void __attribute__((no_sanitize("cfi"))) MoveFrom(Any &&other) noexcept
695     {
696         if (other.HasValue()) {
697             functionTable_ = other.functionTable_;
698             functionTable_->move(storage_, other.storage_);
699             other.Reset();
700         }
701     }
702 
703     template <typename ValueType>
Cast()704     ValueType* Cast() noexcept
705     {
706         using DecayedValueType = decay_t<ValueType>;
707         if (!IsFunctionTableValid()) {
708             return nullptr;
709         }
710 #ifndef HST_ANY_WITH_NO_RTTI
711         if (!SameTypeWith(typeid(DecayedValueType))) {
712 #else
713         if (!SameTypeWith(Any::GetTypeName<DecayedValueType>())) {
714 #endif
715             return nullptr;
716         }
717         return IsTrivialStackStorable<DecayedValueType>::value
718             ? reinterpret_cast<DecayedValueType*>(storage_.trivialStack_.data())
719             : (IsStackStorable<DecayedValueType>::value
720             ? reinterpret_cast<DecayedValueType*>(&storage_.nonTrivialStack_)
721             : reinterpret_cast<DecayedValueType*>(storage_.heap_));
722     }
723     template <typename ValueType>
724     const ValueType* Cast() const noexcept
725     {
726         using DecayedValueType = decay_t<ValueType>;
727         if (!IsFunctionTableValid()) {
728             return nullptr;
729         }
730 #ifndef HST_ANY_WITH_NO_RTTI
731         if (!SameTypeWith(typeid(DecayedValueType))) {
732 #else
733             if (!SameTypeWith(Any::GetTypeName<DecayedValueType>())) {
734 #endif
735             return nullptr;
736         }
737         return IsTrivialStackStorable<DecayedValueType>::value
738             ? reinterpret_cast<const DecayedValueType*>(storage_.trivialStack_.data())
739             : (IsStackStorable<DecayedValueType>::value
740             ? reinterpret_cast<const DecayedValueType*>(&storage_.nonTrivialStack_)
741             : reinterpret_cast<const DecayedValueType*>(storage_.heap_));
742     }
743 
744 private:
745     Storage storage_ {};
746     FunctionTable* functionTable_ {nullptr};
747 };
748 
749 /**
750  * cast one Any pointer into ValueType pointer
751  *
752  * @tparam ValueType target value type
753  * @param operand any object
754  * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the
755  * const value contained by operand.
756  */
757 template <typename ValueType>
758 const ValueType* AnyCast(const Any* operand) noexcept
759 {
760     static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
761     if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
762         return nullptr;
763     }
764     return operand->Cast<ValueType>();
765 }
766 
767  /**
768   * cast one Any pointer into ValueType object
769   *
770   * @tparam ValueType target value type
771   * @param operand any object
772   * @param value ValueType
773   * @return false if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, true to the
774   *  value contained by operand.
775   */
776  template <typename ValueType>
777  bool AnyCast(const Any* operand, ValueType& value) noexcept
778  {
779      static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
780      if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
781          return false;
782      }
783 #ifndef HST_ANY_WITH_NO_RTTI
784      if (!operand->SameTypeWith(typeid(ValueType))) {
785 #else
786          if (!operand->SameTypeWith(Any::GetTypeName<ValueType>())) {
787 #endif
788          return false;
789      } else {
790          value = *(operand->Cast<ValueType>());
791          return true;
792      }
793  }
794 
795 /**
796  * cast one Any pointer into ValueType pointer
797  *
798  * @tparam ValueType target value type
799  * @param operand any object
800  * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the
801  * value contained by operand.
802  */
803 template <typename ValueType>
804 ValueType* AnyCast(Any* operand) noexcept
805 {
806     static_assert(!std::is_void<ValueType>::value, "ValueType of any_cast must not be void");
807     if (std::is_function<ValueType>::value || std::is_array<ValueType>::value || operand == nullptr) {
808         return nullptr;
809     }
810     return operand->Cast<ValueType>();
811 }
812 
813 /**
814  * cast one Any object into ValueType object
815  *
816  * @tparam ValueType target value type. It must match both conditions:
817  * 1. ValueType must be reference or constructible
818  * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, const U&> must be true
819  * @param operand any object
820  * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
821  * one object of ValueType contained in Any.
822  */
823 template <typename ValueType>
824 ValueType AnyCast(const Any& other)
825 {
826     using U = remove_cv_t<remove_reference_t<ValueType>>;
827     static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
828     static_assert(std::is_constructible<ValueType, const U&>::value,
829                   "any_cast<ValueType>(const any&) requires ValueType constructable from const "
830                   "remove_cv_t<remove_reference_t<ValueType>>&");
831     auto ptr = AnyCast<U>(&other);
832     return static_cast<ValueType>(*ptr);
833 }
834 
835 /**
836  * cast one Any object into ValueType object
837  *
838  * @tparam ValueType target value type. It must match both conditions:
839  * 1. ValueType must be reference or constructible
840  * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, U&> must be true
841  * @param operand any object
842  * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
843  * one object of ValueType contained in Any.
844  */
845 template <typename ValueType>
846 ValueType AnyCast(Any& other)
847 {
848     using U = remove_cv_t<remove_reference_t<ValueType>>;
849     static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
850     static_assert(std::is_constructible<ValueType, U&>::value,
851                   "any_cast<ValueType>(const any&) requires ValueType constructable from "
852                   "remove_cv_t<remove_reference_t<ValueType>>&");
853     auto ptr = AnyCast<U>(&other);
854     return static_cast<ValueType>(*ptr);
855 }
856 
857 /**
858  * cast one Any object into ValueType object
859  *
860  * @tparam ValueType target value type. It must match both conditions:
861  * 1. ValueType must be reference or constructible
862  * 2. Let U be remove_cv_t<remove_reference_t<ValueType>>, then std::is_constructible<ValueType, U> must be true
863  * @param operand any object
864  * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise,
865  * one object of ValueType contained in Any.
866  */
867 template <typename ValueType>
868 ValueType AnyCast(Any&& other)
869 {
870     using U = remove_cv_t<remove_reference_t<ValueType>>;
871     static_assert(IsValidCast<ValueType>::value, "template argument must be a reference or has copy constructors");
872     static_assert(std::is_constructible<ValueType, U>::value,
873                   "any_cast<ValueType>(const any&) requires ValueType constructable from "
874                   "remove_cv_t<remove_reference_t<ValueType>>");
875     auto ptr = AnyCast<U>(&other);
876     return static_cast<ValueType>(std::move(*ptr));
877 }
878 
879 /**
880  * Constructs Any object, whose content is constructed by args. The content type is T.
881  *
882  * @tparam T type of Any's content
883  * @tparam Args type of args
884  * @param args args used to construct the content
885  * @return Any object
886  */
887 template <typename T, typename... Args>
888 Any MakeAny(Args&&... args)
889 {
890     Any tmp;
891     tmp.Emplace<T, Args...>(std::forward<Args>(args)...);
892     return tmp;
893 }
894 
895 /**
896  * Constructs Any object, whose content is constructed by il and args. The content type is T.
897  *
898  * @tparam T type of Any's content
899  * @tparam U type of initializer list
900  * @tparam Args type of args
901  * @param il initializer list
902  * @param args args
903  * @return Any object
904  */
905 template <typename T, typename U, typename... Args>
906 Any MakeAny(std::initializer_list<U> il, Args&&... args)
907 {
908     Any tmp;
909     tmp.Emplace<T, U, Args...>(il, std::forward<Args>(args)...);
910     return tmp;
911 }
912 
913 template <typename T>
914 inline typename std::enable_if<std::is_enum<T>::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel
915 & parcel)
916 {
917     if (sizeof(T) == sizeof(int64_t)) {
918         value.Emplace<T>(static_cast<T>(parcel.ReadInt64()));
919         return true;
920     }
921     value.Emplace<T>(static_cast<T>(parcel.ReadInt32()));
922     return true;
923 }
924 } // namespace Media
925 } // namespace OHOS
926 #endif
927 namespace std {
swap(OHOS::Media::Any & lhs,OHOS::Media::Any & rhs)928 inline void swap(OHOS::Media::Any& lhs, OHOS::Media::Any& rhs) noexcept
929 {
930     lhs.Swap(rhs);
931 }
932 } // namespace std
933 #endif // HISTREAMER_PLUGIN_COMMON_ANY_H
934