Lagrange
Loading...
Searching...
No Matches
bind_value.h
1/*
2 * Copyright 2024 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/Logger.h>
15#include <lagrange/python/binding.h>
16#include <lagrange/scene/SceneExtension.h>
17
18NAMESPACE_BEGIN(NB_NAMESPACE)
19NAMESPACE_BEGIN(detail)
20
21template <>
22struct type_caster<lagrange::scene::Value>
23{
24 NB_TYPE_CASTER(lagrange::scene::Value, const_name("int | float | str | list | dict | bool"));
25
26 template <typename T>
27 bool try_cast(const handle& src, uint8_t flags, cleanup_list* cleanup)
28 {
29 using CasterT = make_caster<T>;
30
31 CasterT caster;
32 if (!caster.from_python(src, flags, cleanup)) return false;
33 value.set(caster.operator cast_t<T>());
34 return true;
35 }
36
37 bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept
38 {
39 if (PyNumber_Check(src.ptr())) {
40 lagrange::logger().debug("Number!");
41 return try_cast<int>(src, flags, cleanup) || try_cast<double>(src, flags, cleanup);
42 } else if (try_cast<std::string>(src, flags, cleanup)) {
43 lagrange::logger().debug("String!");
44 return true;
45 } else if (PySequence_Check(src.ptr())) {
46 lagrange::logger().debug("Array of size {}!", PySequence_Size(src.ptr()));
47
48 size_t n;
49 PyObject* temp;
50 /* Will initialize 'temp' (NULL in the case of a failure.) */
51 PyObject** o = seq_get(src.ptr(), &n, &temp);
52
53 bool success = o != nullptr;
54
55 if (success) {
56 lagrange::scene::Value::Array arr;
57 arr.reserve(n);
58 make_caster<lagrange::scene::Value> caster;
59
60 for (size_t i = 0; i < n; ++i) {
61 if (!caster.from_python(o[i], flags, cleanup)) {
62 success = false;
63 break;
64 }
65
66 arr.push_back(caster.operator cast_t<lagrange::scene::Value>());
67 }
68 value.set(arr);
69 }
70
71 Py_XDECREF(temp);
72 return success;
73 } else if (PyMapping_Check(src.ptr())) {
74 lagrange::logger().debug("Dict!");
75
76 PyObject* items = PyMapping_Items(src.ptr());
77 if (items == nullptr) {
78 PyErr_Clear();
79 return false;
80 }
81
82 Py_ssize_t size = NB_LIST_GET_SIZE(items);
83 bool success = size >= 0;
84
85 make_caster<std::string> key_caster;
86 make_caster<lagrange::scene::Value> val_caster;
87 lagrange::scene::Value::Object obj;
88
89 for (Py_ssize_t i = 0; i < size; ++i) {
90 PyObject* item = NB_LIST_GET_ITEM(items, i);
91 PyObject* key = NB_TUPLE_GET_ITEM(item, 0);
92 PyObject* val = NB_TUPLE_GET_ITEM(item, 1);
93
94 if (!key_caster.from_python(key, flags, cleanup)) {
95 success = false;
96 break;
97 }
98
99 if (!val_caster.from_python(val, flags, cleanup)) {
100 success = false;
101 break;
102 }
103
104 obj.emplace(
105 key_caster.operator cast_t<std::string>(),
106 val_caster.operator cast_t<lagrange::scene::Value>());
107 }
108 value.set(obj);
109
110 Py_DECREF(items);
111
112 return success;
113 }
114
115 return false;
116 }
117
118 static handle
119 from_cpp(const lagrange::scene::Value& value, rv_policy policy, cleanup_list* cleanup) noexcept
120 {
121 if (value.is_bool()) {
122 return make_caster<bool>::from_cpp(value.get_bool(), policy, cleanup);
123 } else if (value.is_int()) {
124 return make_caster<int>::from_cpp(value.get_int(), policy, cleanup);
125 } else if (value.is_real()) {
126 return make_caster<double>::from_cpp(value.get_real(), policy, cleanup);
127 } else if (value.is_string()) {
128 return make_caster<std::string>::from_cpp(value.get_string(), policy, cleanup);
129 } else if (value.is_buffer()) {
130 return make_caster<lagrange::scene::Value::Buffer>::from_cpp(
131 value.get_buffer(),
132 policy,
133 cleanup);
134 } else if (value.is_array()) {
135 return make_caster<lagrange::scene::Value::Array>::from_cpp(
136 value.get_array(),
137 policy,
138 cleanup);
139 } else if (value.is_object()) {
140 return make_caster<lagrange::scene::Value::Object>::from_cpp(
141 value.get_object(),
142 policy,
143 cleanup);
144 }
145 return none().release();
146 }
147};
148
149NAMESPACE_END(detail)
150NAMESPACE_END(NB_NAMESPACE)
Definition SceneExtension.h:34
LA_CORE_API spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:40
Main namespace for Lagrange.