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