welder
0.1.0
Bindings for annotated C++ types, from C++26 reflection
Toggle main menu visibility
Loading...
Searching...
No Matches
array_interface.hpp
Go to the documentation of this file.
1
#pragma once
2
#include <array>
3
#include <cstddef>
4
#include <meta>
5
#include <string>
6
#include <type_traits>
7
#include <utility>
8
28
29
namespace
welder::inline v0::
rods::python
{
30
32
consteval
std::string
ai_uint_string
(std::size_t n) {
33
if
(n == 0)
34
return
"0"
;
35
std::string s{};
36
for
(; n; n /= 10)
37
s.insert(s.begin(),
char
(
'0'
+ n % 10));
38
return
s;
39
}
40
43
consteval
bool
ai_is_unsigned
(std::meta::info t) {
44
t = std::meta::dealias(t);
45
for
(std::meta::info u :
46
{^^
unsigned
char, ^^
unsigned
short, ^^
unsigned
int, ^^
unsigned
long,
47
^^
unsigned
long
long, ^^char8_t, ^^char16_t, ^^
char32_t
})
48
if
(t == u)
49
return
true
;
50
return
false
;
51
}
52
59
consteval
std::string
numpy_typestr
(std::meta::info t) {
60
t = std::meta::dealias(t);
61
if
(t == ^^
bool
)
62
return
"|b1"
;
63
if
(t == ^^
float
)
64
return
"<f4"
;
65
if
(t == ^^
double
)
66
return
"<f8"
;
67
if
(!std::meta::is_arithmetic_type(t) || t == ^^
long
double
)
68
return
""
;
// no portable NumPy scalar
69
const
std::size_t sz{std::meta::size_of(t)};
70
const
char
code{
ai_is_unsigned
(t) ?
'u'
:
'i'
};
71
const
char
prefix{sz == 1 ?
'|'
:
'<'
};
72
return
std::string{prefix} + code +
ai_uint_string
(sz);
73
}
74
77
template
<
class
E>
78
consteval
const
char
*
ai_typestr
() {
79
return
std::define_static_string(
"|V"
+
ai_uint_string
(
sizeof
(E)));
80
}
81
84
consteval
bool
ai_all_fields_numpy
(std::meta::info E) {
85
const
auto
members{std::meta::nonstatic_data_members_of(
86
E, std::meta::access_context::unchecked())};
87
if
(members.empty())
88
return
false
;
89
for
(std::meta::info m : members)
90
if
(
numpy_typestr
(std::meta::type_of(m)).empty())
91
return
false
;
92
return
true
;
93
}
94
99
template
<
class
E>
100
consteval
bool
pod_array_eligible
() {
101
return
std::is_class_v<E> && std::is_trivially_copyable_v<E> &&
102
std::is_standard_layout_v<E> &&
ai_all_fields_numpy
(^^E);
103
}
104
107
consteval
std::size_t
ai_entry_count
(std::meta::info E) {
108
std::size_t n{0}, running{0};
109
for
(std::meta::info m : std::meta::nonstatic_data_members_of(
110
E, std::meta::access_context::unchecked())) {
111
// offset_of(m).bytes is std::ptrdiff_t (signed); a field offset is
112
// non-negative, so cast to size_t (avoids -Werror=narrowing/sign-conversion).
113
const
std::size_t off{
114
static_cast<
std::size_t
>
(std::meta::offset_of(m).bytes)};
115
if
(off > running)
116
++n;
// interior padding
117
++n;
// the field
118
running = off + std::meta::size_of(std::meta::type_of(m));
119
}
120
if
(running < std::meta::size_of(E))
121
++n;
// trailing padding
122
return
n;
123
}
124
130
template
<std::meta::info E>
131
consteval
std::array<std::pair<const char*, const char*>, ai_entry_count(E)>
132
ai_descr
() {
133
std::array<std::pair<const char*, const char*>,
ai_entry_count
(E)> out{};
134
std::size_t i{0}, running{0};
135
for
(std::meta::info m : std::meta::nonstatic_data_members_of(
136
E, std::meta::access_context::unchecked())) {
137
// offset_of(m).bytes is std::ptrdiff_t (signed); a field offset is
138
// non-negative, so cast to size_t (avoids -Werror=narrowing/sign-conversion).
139
const
std::size_t off{
140
static_cast<
std::size_t
>
(std::meta::offset_of(m).bytes)};
141
if
(off > running)
142
out[i++] = {
""
, std::define_static_string(
"|V"
+
143
ai_uint_string
(off - running))};
144
out[i++] = {std::define_static_string(std::meta::identifier_of(m)),
145
std::define_static_string(
numpy_typestr
(std::meta::type_of(m)))};
146
running = off + std::meta::size_of(std::meta::type_of(m));
147
}
148
if
(running < std::meta::size_of(E))
149
out[i++] = {
""
, std::define_static_string(
150
"|V"
+
ai_uint_string
(std::meta::size_of(E) - running))};
151
return
out;
152
}
153
154
}
// namespace welder::inline v0::rods::python
welder::rods::python
Definition
array_interface.hpp:29
welder::rods::python::pod_array_eligible
consteval bool pod_array_eligible()
Is std::vector<E> viewable as a NumPy structured array — i.e.
Definition
array_interface.hpp:100
welder::rods::python::ai_typestr
consteval const char * ai_typestr()
The array-interface typestr for the whole element E — an opaque |V<sizeof> void field; the per-field ...
Definition
array_interface.hpp:78
welder::rods::python::ai_entry_count
consteval std::size_t ai_entry_count(std::meta::info E)
The number of array-interface descr entries for E — one per field, plus one per padding gap (interior...
Definition
array_interface.hpp:107
welder::rods::python::ai_all_fields_numpy
consteval bool ai_all_fields_numpy(std::meta::info E)
Whether every one of a POD struct's fields maps to a NumPy scalar (so the descr is complete).
Definition
array_interface.hpp:84
welder::rods::python::numpy_typestr
consteval std::string numpy_typestr(std::meta::info t)
The NumPy typestr for arithmetic type t ('<' little-endian, '|' for a single byte),...
Definition
array_interface.hpp:59
welder::rods::python::ai_is_unsigned
consteval bool ai_is_unsigned(std::meta::info t)
Is t one of the unsigned integer fundamental types?
Definition
array_interface.hpp:43
welder::rods::python::ai_descr
consteval std::array< std::pair< const char *, const char * >, ai_entry_count(E)> ai_descr()
The NumPy array-interface descr for E: a splice-ready std::array of (name, typestr) pairs — each fiel...
Definition
array_interface.hpp:132
welder::rods::python::ai_uint_string
consteval std::string ai_uint_string(std::size_t n)
Decimal render of n (constexpr std::to_string is unavailable on gcc-16).
Definition
array_interface.hpp:32
src
welder
rods
python
array_interface.hpp
Generated by
1.17.0