sandbox
Loading...
Searching...
No Matches
object.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_SCRIPTING_MANAGED_OBJECT_HPP_
3#define LIBSBX_SCRIPTING_MANAGED_OBJECT_HPP_
4
5#include <cmath>
6
7#include <array>
8#include <string>
9#include <string_view>
10#include <tuple>
11#include <type_traits>
12
13#include <libsbx/scripting/managed/fwd.hpp>
14#include <libsbx/scripting/managed/core.hpp>
15#include <libsbx/scripting/managed/string.hpp>
16
17namespace sbx::scripting::managed {
18
19enum class managed_type : std::uint8_t {
20 unknown,
21 int8,
22 uint8,
23 int16,
24 uint16,
25 int32,
26 uint32,
27 int64,
28 uint64,
29 float32,
30 float64,
31 boolean,
32 string,
33 pointer
34}; // enum class managed_type
35
36template<typename Type>
37constexpr auto get_managed_type() -> managed_type {
38 if constexpr (std::same_as<Type, std::uint8_t> || std::same_as<Type, std::byte>) {
39 return managed_type::uint8;
40 } else if constexpr (std::same_as<Type, std::uint16_t>) {
41 return managed_type::uint16;
42 } else if constexpr (std::same_as<Type, std::uint32_t> || (std::same_as<Type, unsigned long> && sizeof(Type) == 4u)) {
43 return managed_type::uint32;
44 } else if constexpr (std::same_as<Type, std::uint64_t> || (std::same_as<Type, unsigned long> && sizeof(Type) == 8u)) {
45 return managed_type::uint64;
46 } else if constexpr (std::same_as<Type, char8_t> || std::same_as<Type, std::int8_t>) {
47 return managed_type::int8;
48 } else if constexpr (std::same_as<Type, std::int16_t>) {
49 return managed_type::int16;
50 } else if constexpr (std::same_as<Type, std::int32_t> || (std::same_as<Type, long> && sizeof(Type) == 4u)) {
51 return managed_type::int32;
52 } else if constexpr (std::same_as<Type, std::int64_t> || (std::same_as<Type, long> && sizeof(Type) == 8u)) {
53 return managed_type::int64;
54 } else if constexpr (std::same_as<Type, std::float_t>) {
55 return managed_type::float32;
56 } else if constexpr (std::same_as<Type, std::double_t>) {
57 return managed_type::float64;
58 } else if constexpr (std::same_as<Type, bool>) {
59 return managed_type::boolean;
60 } else if constexpr (std::is_same_v<Type, std::string> || std::is_same_v<Type, managed::string>) {
61 return managed_type::string;
62 } else {
63 return managed_type::unknown;
64 }
65}
66
67namespace detail {
68
69template<std::size_t Size, typename Tuple, std::size_t Index>
70inline auto add_to_array(std::array<const void*, Size>& arguments, std::array<managed_type, Size>& types, const Tuple& tuple) -> void {
71 using T = std::tuple_element_t<Index, Tuple>;
72
73 types[Index] = get_managed_type<std::remove_reference_t<T>>();
74
75 if constexpr (std::is_pointer_v<std::remove_reference_t<T>>) {
76 arguments[Index] = static_cast<const void*>(std::get<Index>(tuple));
77 } else {
78 arguments[Index] = static_cast<const void*>(&std::get<Index>(tuple));
79 }
80}
81
82} // namespace detail
83
84template<std::size_t Size, typename Tuple, std::size_t... Indices>
85inline auto add_to_array(std::array<const void*, Size>& arguments, std::array<managed_type, Size>& types, const Tuple& tuple, std::index_sequence<Indices...>) -> void {
86 (detail::add_to_array<Size, Tuple, Indices>(arguments, types, tuple), ...);
87}
88
89class object {
90
91 friend class assembly;
92 friend class type;
93
94public:
95
96 template<typename Result, typename... Args>
97 auto invoke(std::string_view name, Args&&... args) const -> Result {
98 constexpr auto parameter_count = sizeof...(args);
99
100 auto result = Result{};
101
102 if constexpr (parameter_count > 0u) {
103 auto storage = std::tuple<std::decay_t<Args>...>{std::forward<Args>(args)...};
104
105 auto parameter_values = std::array<const void*, parameter_count>{};
106 auto parameter_types = std::array<managed_type, parameter_count>{};
107
108 add_to_array(parameter_values, parameter_types, storage, std::make_index_sequence<parameter_count>{});
109
110 _invoke_method_return_internal(name, parameter_values.data(), parameter_types.data(), parameter_count, &result);
111 } else {
112 _invoke_method_return_internal(name, nullptr, nullptr, 0, &result);
113 }
114
115 return result;
116 }
117
118 template<typename... Args>
119 auto invoke(std::string_view name, Args&&... args) const -> void {
120 constexpr auto parameter_count = sizeof...(args);
121
122 if constexpr (parameter_count > 0u) {
123 auto storage = std::tuple<std::decay_t<Args>...>{std::forward<Args>(args)...};
124
125 auto parameter_values = std::array<const void*, parameter_count>{};
126 auto parameter_types = std::array<managed_type, parameter_count>{};
127
128 add_to_array(parameter_values, parameter_types, storage, std::make_index_sequence<parameter_count>{});
129
130 _invoke_method_internal(name, parameter_values.data(), parameter_types.data(), parameter_count);
131 } else {
132 _invoke_method_internal(name, nullptr, nullptr, 0);
133 }
134 }
135
136 template<typename Type>
137 auto set_field_value(std::string_view name, const Type& value) const -> void {
138 set_field_value_raw(name, &value);
139 }
140
141 template<typename Type>
142 auto get_field_value(std::string_view name) const -> Type {
143 auto result = Type{};
144
145 get_field_value_raw(name, &result);
146
147 return result;
148 }
149
150 template<typename Type>
151 auto set_property_value(std::string_view name, Type value) const -> void {
152 set_property_value_raw(name, &value);
153 }
154
155 template<typename Type>
156 auto get_property_value(std::string_view name) const -> Type {
157 auto result = Type{};
158
159 get_property_value_raw(name, &result);
160
161 return result;
162 }
163
164 auto set_field_value_raw(std::string_view name, const void* value) const -> void;
165
166 auto get_field_value_raw(std::string_view name, void* value) const -> void;
167
168 auto set_property_value_raw(std::string_view name, const void* value) const -> void;
169
170 auto get_property_value_raw(std::string_view name, void* value) const -> void;
171
172 auto get_type() -> const type&;
173
174 auto destroy() -> void;
175
176 auto is_valid() const -> bool;
177
178private:
179
180 auto _invoke_method_internal(std::string_view name, const void** parameters, const managed_type* parameter_types, std::size_t length) const -> void;
181
182 auto _invoke_method_return_internal(std::string_view name, const void** parameters, const managed_type* parameter_types, std::size_t length, void* result_storage) const -> void;
183
184 void* _handle{nullptr};
185 const type* _type{nullptr};
186
187private:
188
189}; // class object
190
191template<>
192auto object::set_field_value<std::string>(std::string_view name, const std::string& value) const -> void;
193
194template<>
195auto object::set_field_value<bool>(std::string_view name, const bool& value) const -> void;
196
197template<>
198auto object::get_field_value<std::string>(std::string_view name) const -> std::string;
199
200template<>
201auto object::get_field_value<bool>(std::string_view name) const -> bool;
202
203}; // namespace sbx::scripting::managed
204
205#endif // LIBSBX_SCRIPTING_MANAGED_OBJECT_HPP_
Definition: assembly.hpp:27
Definition: object.hpp:89
Definition: type.hpp:11