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