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