1#pragma once
2
3namespace nn::gfx::detail {
4
5template <class T>
6class CasterBase {
7protected:
8 T* m_Value;
9
10public:
11 explicit CasterBase(T* value) : m_Value(value) {}
12
13 T* operator->() { return m_Value; }
14
15 operator bool();
16 operator bool() const;
17 bool IsNull();
18
19 template <class U>
20 operator U*() {
21 return static_cast<U*>(m_Value);
22 }
23};
24
25template <class T>
26class Caster : public CasterBase<T> {
27public:
28 explicit Caster(T* value) : CasterBase<T>(value) {}
29
30 template <class U>
31 operator U&() {
32 return static_cast<U&>(*CasterBase<T>::m_Value);
33 }
34};
35
36template <class T>
37class Caster<const T> : public CasterBase<const T> {
38public:
39 explicit Caster(const T* value) : CasterBase<const T>(value) {}
40
41 template <class U>
42 operator const U&() {
43 return static_cast<const U&>(*CasterBase<const T>::m_Value);
44 }
45};
46
47template <class T>
48class Caster<volatile T> : public CasterBase<volatile T> {
49public:
50 explicit Caster(volatile T* value) : CasterBase<volatile T>(value) {}
51};
52
53template <class T>
54class Caster<const volatile T> : public CasterBase<const volatile T> {
55public:
56 explicit Caster(const volatile T* value) : CasterBase<const volatile T>(value) {}
57};
58
59template <class TData>
60class DataContainer : protected TData {
61public:
62 typedef TData DataType;
63
64 DataContainer() : TData() {}
65
66 Caster<TData> ToData() { return Caster<TData>(static_cast<DataType*>(this)); }
67
68 Caster<const TData> ToData() const {
69 return Caster<const TData>(static_cast<const DataType*>(this));
70 }
71
72 Caster<volatile TData> ToData() volatile;
73 Caster<const volatile TData> ToData() const volatile;
74
75 static Caster<DataContainer> DataToAccessor(TData* pData) {
76 return Caster<DataContainer>(static_cast<DataContainer*>(pData));
77 }
78
79 static Caster<const DataContainer> DataToAccessor(const TData* pData) {
80 return Caster<const DataContainer>(static_cast<const DataContainer*>(pData));
81 }
82
83 static Caster<volatile DataContainer> DataToAccessor(volatile TData*);
84 static Caster<const volatile DataContainer> DataToAccessor(const volatile TData*);
85
86 static Caster<DataContainer> DataToAccessor(TData& data) { return DataToAccessor(&data); }
87
88 static Caster<const DataContainer> DataToAccessor(const TData& data) {
89 return DataToAccessor(&data);
90 }
91
92 static Caster<volatile DataContainer> DataToAccessor(volatile TData&);
93 static Caster<const volatile DataContainer> DataToAccessor(const volatile TData&);
94};
95
96} // namespace nn::gfx::detail
97
98// helper functions, made for convenience
99namespace nn::gfx {
100
101template <typename TData>
102detail::Caster<detail::DataContainer<TData>> DataToAccessor(TData& data) {
103 return detail::DataContainer<TData>::DataToAccessor(data);
104}
105
106template <typename TData>
107detail::Caster<const detail::DataContainer<TData>> DataToAccessor(const TData& data) {
108 return detail::DataContainer<TData>::DataToAccessor(data);
109}
110
111template <typename TData>
112detail::Caster<const detail::DataContainer<TData>> DataToAccessor(const TData* data) {
113 return detail::DataContainer<TData>::DataToAccessor(data);
114}
115
116} // namespace nn::gfx