/src/rocksdb/util/cast_util.h
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | |
6 | | #pragma once |
7 | | |
8 | | #include <initializer_list> |
9 | | #include <memory> |
10 | | #include <type_traits> |
11 | | |
12 | | #include "rocksdb/rocksdb_namespace.h" |
13 | | |
14 | | namespace ROCKSDB_NAMESPACE { |
15 | | // The helper function to assert the move from dynamic_cast<> to |
16 | | // static_cast<> is correct. This function is to deal with legacy code. |
17 | | // It is not recommended to add new code to issue class casting. The preferred |
18 | | // solution is to implement the functionality without a need of casting. |
19 | | template <class DestClass, class SrcClass> |
20 | 2.72M | inline DestClass* static_cast_with_check(SrcClass* x) { |
21 | 2.72M | DestClass* ret = static_cast<DestClass*>(x); |
22 | | #ifdef ROCKSDB_USE_RTTI |
23 | | assert(ret == dynamic_cast<DestClass*>(x)); |
24 | | #endif |
25 | 2.72M | return ret; |
26 | 2.72M | } Unexecuted instantiation: rocksdb::ColumnFamilyHandleImpl* rocksdb::static_cast_with_check<rocksdb::ColumnFamilyHandleImpl, rocksdb::ColumnFamilyHandleImpl>(rocksdb::ColumnFamilyHandleImpl*) rocksdb::ColumnFamilyHandleImpl* rocksdb::static_cast_with_check<rocksdb::ColumnFamilyHandleImpl, rocksdb::ColumnFamilyHandle>(rocksdb::ColumnFamilyHandle*) Line | Count | Source | 20 | 1.58M | inline DestClass* static_cast_with_check(SrcClass* x) { | 21 | 1.58M | DestClass* ret = static_cast<DestClass*>(x); | 22 | | #ifdef ROCKSDB_USE_RTTI | 23 | | assert(ret == dynamic_cast<DestClass*>(x)); | 24 | | #endif | 25 | 1.58M | return ret; | 26 | 1.58M | } |
Unexecuted instantiation: rocksdb::SnapshotImpl const* rocksdb::static_cast_with_check<rocksdb::SnapshotImpl const, rocksdb::Snapshot const>(rocksdb::Snapshot const*) rocksdb::SstFileManagerImpl* rocksdb::static_cast_with_check<rocksdb::SstFileManagerImpl, rocksdb::SstFileManager>(rocksdb::SstFileManager*) Line | Count | Source | 20 | 130k | inline DestClass* static_cast_with_check(SrcClass* x) { | 21 | 130k | DestClass* ret = static_cast<DestClass*>(x); | 22 | | #ifdef ROCKSDB_USE_RTTI | 23 | | assert(ret == dynamic_cast<DestClass*>(x)); | 24 | | #endif | 25 | 130k | return ret; | 26 | 130k | } |
Unexecuted instantiation: rocksdb::LRUCacheOptions* rocksdb::static_cast_with_check<rocksdb::LRUCacheOptions, rocksdb::ShardedCacheOptions>(rocksdb::ShardedCacheOptions*) Unexecuted instantiation: rocksdb::HyperClockCacheOptions* rocksdb::static_cast_with_check<rocksdb::HyperClockCacheOptions, rocksdb::ShardedCacheOptions>(rocksdb::ShardedCacheOptions*) rocksdb::DBImpl* rocksdb::static_cast_with_check<rocksdb::DBImpl, rocksdb::DB>(rocksdb::DB*) Line | Count | Source | 20 | 1.00M | inline DestClass* static_cast_with_check(SrcClass* x) { | 21 | 1.00M | DestClass* ret = static_cast<DestClass*>(x); | 22 | | #ifdef ROCKSDB_USE_RTTI | 23 | | assert(ret == dynamic_cast<DestClass*>(x)); | 24 | | #endif | 25 | 1.00M | return ret; | 26 | 1.00M | } |
rocksdb::DBImpl* rocksdb::static_cast_with_check<rocksdb::DBImpl, rocksdb::DBImpl>(rocksdb::DBImpl*) Line | Count | Source | 20 | 10.5k | inline DestClass* static_cast_with_check(SrcClass* x) { | 21 | 10.5k | DestClass* ret = static_cast<DestClass*>(x); | 22 | | #ifdef ROCKSDB_USE_RTTI | 23 | | assert(ret == dynamic_cast<DestClass*>(x)); | 24 | | #endif | 25 | 10.5k | return ret; | 26 | 10.5k | } |
Unexecuted instantiation: rocksdb::VersionSet::LogReporter* rocksdb::static_cast_with_check<rocksdb::VersionSet::LogReporter, rocksdb::log::Reader::Reporter>(rocksdb::log::Reader::Reporter*) Unexecuted instantiation: rocksdb::WalFileImpl* rocksdb::static_cast_with_check<rocksdb::WalFileImpl, rocksdb::WalFile>(rocksdb::WalFile*) Unexecuted instantiation: mock_env.cc:rocksdb::(anonymous namespace)::MockEnvFileLock* rocksdb::static_cast_with_check<rocksdb::(anonymous namespace)::MockEnvFileLock, rocksdb::FileLock>(rocksdb::FileLock*) Unexecuted instantiation: rocksdb::MockFileSystem* rocksdb::static_cast_with_check<rocksdb::MockFileSystem, rocksdb::FileSystem>(rocksdb::FileSystem*) Unexecuted instantiation: rocksdb::HistogramImpl const* rocksdb::static_cast_with_check<rocksdb::HistogramImpl const, rocksdb::Histogram const>(rocksdb::Histogram const*) Unexecuted instantiation: rocksdb::PessimisticTransaction* rocksdb::static_cast_with_check<rocksdb::PessimisticTransaction, rocksdb::Transaction>(rocksdb::Transaction*) Unexecuted instantiation: rocksdb::PessimisticTransactionDB* rocksdb::static_cast_with_check<rocksdb::PessimisticTransactionDB, rocksdb::TransactionDB>(rocksdb::TransactionDB*) Unexecuted instantiation: rocksdb::WriteUnpreparedTxn* rocksdb::static_cast_with_check<rocksdb::WriteUnpreparedTxn, rocksdb::Transaction>(rocksdb::Transaction*) Unexecuted instantiation: rocksdb::WBWIIteratorImpl* rocksdb::static_cast_with_check<rocksdb::WBWIIteratorImpl, rocksdb::WBWIIterator>(rocksdb::WBWIIterator*) |
27 | | |
28 | | template <class DestClass, class SrcClass> |
29 | | inline std::shared_ptr<DestClass> static_cast_with_check( |
30 | | std::shared_ptr<SrcClass>&& x) { |
31 | | #if defined(ROCKSDB_USE_RTTI) && !defined(NDEBUG) |
32 | | auto orig_raw = x.get(); |
33 | | #endif |
34 | | auto ret = std::static_pointer_cast<DestClass>(std::move(x)); |
35 | | #if defined(ROCKSDB_USE_RTTI) && !defined(NDEBUG) |
36 | | assert(ret.get() == dynamic_cast<DestClass*>(orig_raw)); |
37 | | #endif |
38 | | return ret; |
39 | | } |
40 | | |
41 | | // A wrapper around static_cast for lossless conversion between integral |
42 | | // types, including enum types, and pointers to such types. For example, this |
43 | | // can be used for converting between signed/unsigned or enum type and |
44 | | // underlying type without fear of stripping away data, now or in the future. |
45 | | template <typename To, typename From> |
46 | 25.2M | inline To lossless_cast(From x) { |
47 | 25.2M | using FromValue = typename std::remove_reference_t<From>; |
48 | 25.2M | if constexpr (std::is_pointer_v<FromValue>) { |
49 | 24.4M | static_assert(std::is_pointer_v<To>); |
50 | 24.4M | using FromDeref = typename std::remove_pointer_t<FromValue>; |
51 | 24.4M | using ToDeref = typename std::remove_pointer_t<To>; |
52 | 24.4M | static_assert(std::is_integral_v<FromDeref> || std::is_enum_v<FromDeref>, |
53 | 24.4M | "Only works on integral types"); |
54 | 24.4M | static_assert(std::is_integral_v<ToDeref> || std::is_enum_v<To>, |
55 | 24.4M | "Only works on integral types"); |
56 | 24.4M | static_assert(sizeof(ToDeref) == sizeof(FromDeref), "Must be lossless"); |
57 | 24.4M | return reinterpret_cast<To>(x); |
58 | 24.4M | } else { |
59 | 715k | static_assert(std::is_integral_v<FromValue> || std::is_enum_v<FromValue>, |
60 | 715k | "Only works on integral types"); |
61 | 715k | static_assert(std::is_integral_v<To> || std::is_enum_v<To>, |
62 | 715k | "Only works on integral types"); |
63 | 715k | static_assert(sizeof(To) >= sizeof(FromValue), "Must be lossless"); |
64 | 715k | return static_cast<To>(x); |
65 | 715k | } |
66 | 25.2M | } unsigned char const* rocksdb::lossless_cast<unsigned char const*, char const*>(char const*) Line | Count | Source | 46 | 18.9M | inline To lossless_cast(From x) { | 47 | 18.9M | using FromValue = typename std::remove_reference_t<From>; | 48 | 18.9M | if constexpr (std::is_pointer_v<FromValue>) { | 49 | 18.9M | static_assert(std::is_pointer_v<To>); | 50 | 18.9M | using FromDeref = typename std::remove_pointer_t<FromValue>; | 51 | 18.9M | using ToDeref = typename std::remove_pointer_t<To>; | 52 | 18.9M | static_assert(std::is_integral_v<FromDeref> || std::is_enum_v<FromDeref>, | 53 | 18.9M | "Only works on integral types"); | 54 | 18.9M | static_assert(std::is_integral_v<ToDeref> || std::is_enum_v<To>, | 55 | 18.9M | "Only works on integral types"); | 56 | 18.9M | static_assert(sizeof(ToDeref) == sizeof(FromDeref), "Must be lossless"); | 57 | 18.9M | return reinterpret_cast<To>(x); | 58 | | } else { | 59 | | static_assert(std::is_integral_v<FromValue> || std::is_enum_v<FromValue>, | 60 | | "Only works on integral types"); | 61 | | static_assert(std::is_integral_v<To> || std::is_enum_v<To>, | 62 | | "Only works on integral types"); | 63 | | static_assert(sizeof(To) >= sizeof(FromValue), "Must be lossless"); | 64 | | return static_cast<To>(x); | 65 | | } | 66 | 18.9M | } |
unsigned char* rocksdb::lossless_cast<unsigned char*, char*>(char*) Line | Count | Source | 46 | 2.79M | inline To lossless_cast(From x) { | 47 | 2.79M | using FromValue = typename std::remove_reference_t<From>; | 48 | 2.79M | if constexpr (std::is_pointer_v<FromValue>) { | 49 | 2.79M | static_assert(std::is_pointer_v<To>); | 50 | 2.79M | using FromDeref = typename std::remove_pointer_t<FromValue>; | 51 | 2.79M | using ToDeref = typename std::remove_pointer_t<To>; | 52 | 2.79M | static_assert(std::is_integral_v<FromDeref> || std::is_enum_v<FromDeref>, | 53 | 2.79M | "Only works on integral types"); | 54 | 2.79M | static_assert(std::is_integral_v<ToDeref> || std::is_enum_v<To>, | 55 | 2.79M | "Only works on integral types"); | 56 | 2.79M | static_assert(sizeof(ToDeref) == sizeof(FromDeref), "Must be lossless"); | 57 | 2.79M | return reinterpret_cast<To>(x); | 58 | | } else { | 59 | | static_assert(std::is_integral_v<FromValue> || std::is_enum_v<FromValue>, | 60 | | "Only works on integral types"); | 61 | | static_assert(std::is_integral_v<To> || std::is_enum_v<To>, | 62 | | "Only works on integral types"); | 63 | | static_assert(sizeof(To) >= sizeof(FromValue), "Must be lossless"); | 64 | | return static_cast<To>(x); | 65 | | } | 66 | 2.79M | } |
char* rocksdb::lossless_cast<char*, unsigned char*>(unsigned char*) Line | Count | Source | 46 | 2.79M | inline To lossless_cast(From x) { | 47 | 2.79M | using FromValue = typename std::remove_reference_t<From>; | 48 | 2.79M | if constexpr (std::is_pointer_v<FromValue>) { | 49 | 2.79M | static_assert(std::is_pointer_v<To>); | 50 | 2.79M | using FromDeref = typename std::remove_pointer_t<FromValue>; | 51 | 2.79M | using ToDeref = typename std::remove_pointer_t<To>; | 52 | 2.79M | static_assert(std::is_integral_v<FromDeref> || std::is_enum_v<FromDeref>, | 53 | 2.79M | "Only works on integral types"); | 54 | 2.79M | static_assert(std::is_integral_v<ToDeref> || std::is_enum_v<To>, | 55 | 2.79M | "Only works on integral types"); | 56 | 2.79M | static_assert(sizeof(ToDeref) == sizeof(FromDeref), "Must be lossless"); | 57 | 2.79M | return reinterpret_cast<To>(x); | 58 | | } else { | 59 | | static_assert(std::is_integral_v<FromValue> || std::is_enum_v<FromValue>, | 60 | | "Only works on integral types"); | 61 | | static_assert(std::is_integral_v<To> || std::is_enum_v<To>, | 62 | | "Only works on integral types"); | 63 | | static_assert(sizeof(To) >= sizeof(FromValue), "Must be lossless"); | 64 | | return static_cast<To>(x); | 65 | | } | 66 | 2.79M | } |
Unexecuted instantiation: rocksdb::CacheTier rocksdb::lossless_cast<rocksdb::CacheTier, char>(char) Unexecuted instantiation: rocksdb::CompressionType rocksdb::lossless_cast<rocksdb::CompressionType, char>(char) Unexecuted instantiation: char rocksdb::lossless_cast<char, rocksdb::CacheTier>(rocksdb::CacheTier) Unexecuted instantiation: char rocksdb::lossless_cast<char, rocksdb::CompressionType>(rocksdb::CompressionType) rocksdb::ChecksumType rocksdb::lossless_cast<rocksdb::ChecksumType, char>(char) Line | Count | Source | 46 | 115k | inline To lossless_cast(From x) { | 47 | 115k | using FromValue = typename std::remove_reference_t<From>; | 48 | | if constexpr (std::is_pointer_v<FromValue>) { | 49 | | static_assert(std::is_pointer_v<To>); | 50 | | using FromDeref = typename std::remove_pointer_t<FromValue>; | 51 | | using ToDeref = typename std::remove_pointer_t<To>; | 52 | | static_assert(std::is_integral_v<FromDeref> || std::is_enum_v<FromDeref>, | 53 | | "Only works on integral types"); | 54 | | static_assert(std::is_integral_v<ToDeref> || std::is_enum_v<To>, | 55 | | "Only works on integral types"); | 56 | | static_assert(sizeof(ToDeref) == sizeof(FromDeref), "Must be lossless"); | 57 | | return reinterpret_cast<To>(x); | 58 | 115k | } else { | 59 | 115k | static_assert(std::is_integral_v<FromValue> || std::is_enum_v<FromValue>, | 60 | 115k | "Only works on integral types"); | 61 | 115k | static_assert(std::is_integral_v<To> || std::is_enum_v<To>, | 62 | 115k | "Only works on integral types"); | 63 | 115k | static_assert(sizeof(To) >= sizeof(FromValue), "Must be lossless"); | 64 | 115k | return static_cast<To>(x); | 65 | 115k | } | 66 | 115k | } |
unsigned char rocksdb::lossless_cast<unsigned char, char>(char) Line | Count | Source | 46 | 600k | inline To lossless_cast(From x) { | 47 | 600k | using FromValue = typename std::remove_reference_t<From>; | 48 | | if constexpr (std::is_pointer_v<FromValue>) { | 49 | | static_assert(std::is_pointer_v<To>); | 50 | | using FromDeref = typename std::remove_pointer_t<FromValue>; | 51 | | using ToDeref = typename std::remove_pointer_t<To>; | 52 | | static_assert(std::is_integral_v<FromDeref> || std::is_enum_v<FromDeref>, | 53 | | "Only works on integral types"); | 54 | | static_assert(std::is_integral_v<ToDeref> || std::is_enum_v<To>, | 55 | | "Only works on integral types"); | 56 | | static_assert(sizeof(ToDeref) == sizeof(FromDeref), "Must be lossless"); | 57 | | return reinterpret_cast<To>(x); | 58 | 600k | } else { | 59 | 600k | static_assert(std::is_integral_v<FromValue> || std::is_enum_v<FromValue>, | 60 | 600k | "Only works on integral types"); | 61 | 600k | static_assert(std::is_integral_v<To> || std::is_enum_v<To>, | 62 | 600k | "Only works on integral types"); | 63 | 600k | static_assert(sizeof(To) >= sizeof(FromValue), "Must be lossless"); | 64 | 600k | return static_cast<To>(x); | 65 | 600k | } | 66 | 600k | } |
Unexecuted instantiation: unsigned char rocksdb::lossless_cast<unsigned char, rocksdb::CompressionType>(rocksdb::CompressionType) |
67 | | |
68 | | // For disambiguating a potentially heterogeneous aggregate as a homogeneous |
69 | | // initializer list. E.g. might be able to write List({x, y}) in some cases |
70 | | // instead of std::vector<const Widget&>({x, y}). |
71 | | template <typename T> |
72 | | inline const std::initializer_list<T>& List( |
73 | | const std::initializer_list<T>& list) { |
74 | | return list; |
75 | | } |
76 | | |
77 | | // UnownedPtr<T> is useful as an efficient "optional reference" that can't |
78 | | // be accidentally converted to std::shared_ptr<T> nor std::unique_ptr<T>. |
79 | | template <typename T> |
80 | | class UnownedPtr { |
81 | | public: |
82 | 43.4k | UnownedPtr() = default; |
83 | 251k | UnownedPtr(std::nullptr_t) {}rocksdb::UnownedPtr<rocksdb::SeqnoToTimeMapping const>::UnownedPtr(decltype(nullptr)) Line | Count | Source | 83 | 48.1k | UnownedPtr(std::nullptr_t) {} |
rocksdb::UnownedPtr<rocksdb::Compressor>::UnownedPtr(decltype(nullptr)) Line | Count | Source | 83 | 87.7k | UnownedPtr(std::nullptr_t) {} |
rocksdb::UnownedPtr<rocksdb::Decompressor>::UnownedPtr(decltype(nullptr)) Line | Count | Source | 83 | 115k | UnownedPtr(std::nullptr_t) {} |
|
84 | 552k | UnownedPtr(T* ptr) : ptr_(ptr) {}rocksdb::UnownedPtr<rocksdb::SeqnoToTimeMapping const>::UnownedPtr(rocksdb::SeqnoToTimeMapping const*) Line | Count | Source | 84 | 33.8k | UnownedPtr(T* ptr) : ptr_(ptr) {} |
rocksdb::UnownedPtr<rocksdb::CompressionManager>::UnownedPtr(rocksdb::CompressionManager*) Line | Count | Source | 84 | 224k | UnownedPtr(T* ptr) : ptr_(ptr) {} |
Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::Compressor>::UnownedPtr(rocksdb::Compressor*) rocksdb::UnownedPtr<rocksdb::Decompressor>::UnownedPtr(rocksdb::Decompressor*) Line | Count | Source | 84 | 283k | UnownedPtr(T* ptr) : ptr_(ptr) {} |
rocksdb::UnownedPtr<rocksdb::TruncatedRangeDelIterator>::UnownedPtr(rocksdb::TruncatedRangeDelIterator*) Line | Count | Source | 84 | 10.9k | UnownedPtr(T* ptr) : ptr_(ptr) {} |
|
85 | | UnownedPtr(const UnownedPtr&) = default; |
86 | | UnownedPtr(UnownedPtr&&) = default; |
87 | | UnownedPtr& operator=(const UnownedPtr&) = default; |
88 | | UnownedPtr& operator=(UnownedPtr&&) = default; |
89 | | |
90 | 141k | T* get() const { return ptr_; }rocksdb::UnownedPtr<rocksdb::Decompressor>::get() const Line | Count | Source | 90 | 97.6k | T* get() const { return ptr_; } |
rocksdb::UnownedPtr<rocksdb::Compressor>::get() const Line | Count | Source | 90 | 43.4k | T* get() const { return ptr_; } |
|
91 | 0 | T* operator->() const { return ptr_; }Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::CompressionManager>::operator->() const Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::SeqnoToTimeMapping const>::operator->() const Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::Compressor>::operator->() const Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::Decompressor>::operator->() const Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::TruncatedRangeDelIterator>::operator->() const |
92 | 0 | T& operator*() const { return *ptr_; }Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::SeqnoToTimeMapping const>::operator*() const Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::Decompressor>::operator*() const |
93 | 324k | operator bool() const { return ptr_ != nullptr; }rocksdb::UnownedPtr<rocksdb::CompressionManager>::operator bool() const Line | Count | Source | 93 | 202k | operator bool() const { return ptr_ != nullptr; } |
rocksdb::UnownedPtr<rocksdb::SeqnoToTimeMapping const>::operator bool() const Line | Count | Source | 93 | 24.6k | operator bool() const { return ptr_ != nullptr; } |
rocksdb::UnownedPtr<rocksdb::Compressor>::operator bool() const Line | Count | Source | 93 | 86.3k | operator bool() const { return ptr_ != nullptr; } |
Unexecuted instantiation: rocksdb::UnownedPtr<rocksdb::Decompressor>::operator bool() const rocksdb::UnownedPtr<rocksdb::TruncatedRangeDelIterator>::operator bool() const Line | Count | Source | 93 | 10.9k | operator bool() const { return ptr_ != nullptr; } |
|
94 | | |
95 | | private: |
96 | | T* ptr_ = nullptr; |
97 | | }; |
98 | | |
99 | | } // namespace ROCKSDB_NAMESPACE |