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