forked from stinos/micropython-wrap
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvariable.h
More file actions
128 lines (111 loc) · 4.13 KB
/
Copy pathvariable.h
File metadata and controls
128 lines (111 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#ifndef MICROPYTHONWRAP_VARIABLE
#define MICROPYTHONWRAP_VARIABLE
#include "classwrapper.h"
#include <stdexcept>
namespace upywrap
{
using varname = std::vector< std::string >;
namespace detail
{
inline mp_obj_t GetVariable( const char* name )
{
return mp_load_name( qstr_from_str( name ) );
}
inline mp_obj_t GetVariable( mp_obj_t instance, const char* name )
{
return mp_load_attr( instance, qstr_from_str( name ) );
}
inline mp_obj_t GetVariable( const char* instance, const char* name )
{
return GetVariable( GetVariable( instance ), name );
}
template< class... Names >
mp_obj_t GetVariable( const char* instance, const char* name, Names... names )
{
return GetVariable( GetVariable( instance, name ), names... );
}
inline mp_obj_t GetVariable( const varname& names )
{
const auto numNames = names.size();
if( !numNames )
throw std::runtime_error( "cannot get variable without a name" );
auto var = GetVariable( names[ 0 ].data() );
for( size_t i = 1 ; i < numNames ; ++i )
var = GetVariable( var, names[ i ].data() );
return var;
}
inline void SetVariable( mp_obj_t value, const char* name )
{
mp_store_name( qstr_from_str( name ), value );
}
inline void SetVariable( mp_obj_t instance, mp_obj_t value, const char* name )
{
mp_store_attr( instance, qstr_from_str( name ), value );
}
template< class... Names, size_t... Indices >
mp_obj_t GetVariableHelper( const std::tuple< Names... >& args, index_sequence< Indices... > )
{
return GetVariable( std::get< Indices >( args )... );
}
template< class... Names >
void SetVariable( mp_obj_t value, const char* instance, Names... names )
{
//get all arguments, then pass all but the last one to GetVariableHelper
const auto args = std::make_tuple( instance, names... );
mp_store_attr( GetVariableHelper( args, make_index_sequence< sizeof...( Names ) >() ), qstr_from_str( split_last( names... ) ), value );
}
inline void SetVariable( mp_obj_t value, const varname& names )
{
const auto numNames = names.size();
if( !numNames )
throw std::runtime_error( "cannot get variable without a name" );
if( numNames == 1 )
{
SetVariable( value, names[ 0 ].data() );
}
else
{
auto var = GetVariable( names[ 0 ].data() );
for( size_t i = 1 ; i < numNames - 1 ; ++i )
var = GetVariable( var, names[ i ].data() );
SetVariable( var, value, names[ numNames - 1 ].data() );
}
}
}
/**
* Get the value of any variable in scope, or an (possibly nested) attribute of an object in scope.
* Since this uses mp_store_xxx it uses the lookup rules for it, being: locals/globals/builtins,
* so it depends on the currently active scope which variabls will be found.
* For example:
* @code
auto i = upywrap::GetVariable< int >( "a" ); //get a from scope
auto i = upywrap::GetVariable< int >( "a", "b", "c" ); //get attribute c from attribute b from object a from scope, aka a.b.c
* @endcode
*/
template< class T, class... Names >
T GetVariable( Names... names )
{
return SelectFromPyObj< T >::type::Convert( detail::GetVariable( names... ) );
}
template< class T >
T GetVariable( const varname& names )
{
return SelectFromPyObj< T >::type::Convert( detail::GetVariable( names ) );
}
/**
* Set the value of any variable in scope, or an (possibly nested) attribute of an object in scope.
* Adds the variable/attribute if it does not exist, but not nested (so setting a.b.c is an error if a has no member b).
* Uses same lookup as GetVariable.
*/
template< class T, class... Names >
void SetVariable( const T& value, Names... names )
{
detail::SetVariable( SelectToPyObj< T >::type::Convert( value ), names... );
}
template< class T >
void SetVariable( const T& value, const varname& names )
{
detail::SetVariable( SelectToPyObj< T >::type::Convert( value ), names );
}
}
#endif //#ifndef MICROPYTHONWRAP_VARIABLE