Skip to content

Commit e4e1229

Browse files
committed
TypeTreeHelper.cpp - use macro functions for better speed, add missing incref and decref
1 parent e3a5934 commit e4e1229

File tree

1 file changed

+62
-57
lines changed

1 file changed

+62
-57
lines changed

UnityPyBoost/TypeTreeHelper.cpp

+62-57
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,12 @@ inline PyObject *read_pair(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeRe
180180
return NULL;
181181
}
182182

183-
PyObject *first = read_typetree_value<swap>(reader, (TypeTreeNodeObject *)PyList_GetItem(node->m_Children, 0), config);
183+
PyObject *first = read_typetree_value<swap>(reader, (TypeTreeNodeObject *)PyList_GET_ITEM(node->m_Children, 0), config);
184184
if (!first)
185185
{
186186
return NULL;
187187
}
188-
PyObject *second = read_typetree_value<swap>(reader, (TypeTreeNodeObject *)PyList_GetItem(node->m_Children, 1), config);
188+
PyObject *second = read_typetree_value<swap>(reader, (TypeTreeNodeObject *)PyList_GET_ITEM(node->m_Children, 1), config);
189189
if (!second)
190190
{
191191
Py_DECREF(first);
@@ -198,10 +198,9 @@ inline PyObject *read_pair(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeRe
198198
}
199199

200200
template <bool swap>
201-
inline PyObject *read_class(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeReaderConfigT *config)
201+
inline PyObject *parse_class(ReaderT *reader, PyObject *dict, TypeTreeNodeObject *node, TypeTreeReaderConfigT *config)
202202
{
203203
PyObject *clz = NULL;
204-
PyObject *dict = PyDict_New();
205204

206205
// Determine the class based on node's _data_type
207206
if (node->_data_type == NodeDataType::pptr)
@@ -223,47 +222,38 @@ inline PyObject *read_class(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeR
223222
}
224223
}
225224

225+
// check if class is found
226226
if (clz == NULL)
227227
{
228228
PyErr_SetString(PyExc_ValueError, "Failed to get class");
229+
Py_DECREF(clz);
229230
Py_DECREF(dict);
230231
return NULL;
231232
}
232233

233-
for (int i = 0; i < PyList_GET_SIZE(node->m_Children); i++)
234-
{
235-
TypeTreeNodeObject *child = (TypeTreeNodeObject *)PyList_GetItem(node->m_Children, i);
236-
PyObject *child_value = read_typetree_value<swap>(reader, child, config);
237-
if (!child_value)
238-
{
239-
Py_DECREF(dict);
240-
return NULL;
241-
}
242-
if (PyDict_SetItem(dict, child->m_Name, child_value))
243-
{
244-
Py_DECREF(dict);
245-
Py_DECREF(child_value);
246-
return NULL;
247-
}
248-
// dict increases ref count, so we need to decref here
249-
Py_DECREF(child_value);
250-
}
251-
234+
// try to create class instance
252235
PyObject *args = PyTuple_New(0);
253236
PyObject *instance = PyObject_Call(clz, args, dict);
254237
if (instance != NULL)
255238
{
239+
// success
240+
// cleanup
241+
Py_DECREF(clz);
256242
Py_DECREF(args);
257243
Py_DECREF(dict);
244+
// return instance
258245
return instance;
259246
}
247+
// failed, clear error
260248
PyErr_Clear();
261249

250+
// clean key names
251+
PyObject *key = NULL;
262252
PyObject *keys = PyDict_Keys(dict);
263253
PyObject *clean_args = PyTuple_New(1);
264-
for (Py_ssize_t i = 0; i < PyList_Size(keys); i++)
254+
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(keys); i++)
265255
{
266-
PyObject *key = PyList_GetItem(keys, i);
256+
key = PyList_GET_ITEM(keys, i);
267257
PyTuple_SET_ITEM(clean_args, 0, key);
268258
PyObject *clean_key = PyObject_Call(config->clean_name, clean_args, NULL);
269259
if (PyUnicode_Compare(key, clean_key))
@@ -274,25 +264,33 @@ inline PyObject *read_class(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeR
274264
}
275265
Py_DECREF(clean_key);
276266
}
277-
PyTuple_SET_ITEM(clean_args, 0, Py_None);
267+
// increase ref count for key, as PyTuple_SET_ITEM steals reference, so decref there will decref key
268+
Py_INCREF(key);
278269
Py_DECREF(clean_args);
279270
Py_DECREF(keys);
280271

272+
// try to create class instance again with cleaned keys
281273
instance = PyObject_Call(clz, args, dict);
282274
if (instance != NULL)
283275
{
276+
// success
277+
// cleanup
278+
Py_DECREF(clz);
284279
Py_DECREF(args);
285280
Py_DECREF(dict);
281+
// return instance
286282
return instance;
287283
}
284+
// failed, clear error
288285
PyErr_Clear();
289286

287+
// some keys might be extra, check against __annotations__
290288
PyObject *annonations = PyObject_GetAttrString(clz, "__annotations__");
291289
PyObject *extras = PyDict_New();
292290
keys = PyDict_Keys(dict);
293291
for (Py_ssize_t i = 0; i < PyList_Size(keys); i++)
294292
{
295-
PyObject *key = PyList_GetItem(keys, i);
293+
PyObject *key = PyList_GET_ITEM(keys, i);
296294
if (PyDict_Contains(annonations, key) == 0)
297295
{
298296
PyObject *value = PyDict_GetItem(dict, key);
@@ -301,21 +299,29 @@ inline PyObject *read_class(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeR
301299
}
302300
}
303301
Py_DECREF(keys);
302+
Py_DECREF(annonations);
304303

304+
// try to create class instance again with cleaned keys
305305
instance = PyObject_Call(clz, args, dict);
306306
if (instance != NULL)
307307
{
308+
// success, manually set extra keys
308309
PyObject *items = PyDict_Items(extras);
309310
for (Py_ssize_t i = 0; i < PyList_Size(items); i++)
310311
{
311-
PyObject *item = PyList_GetItem(items, i);
312+
PyObject *item = PyList_GET_ITEM(items, i);
312313
PyObject *key = PyTuple_GetItem(item, 0);
313314
PyObject *value = PyTuple_GetItem(item, 1);
314315
PyObject_SetAttr(instance, key, value);
315316
}
316317
Py_DECREF(items);
317318
}
318-
319+
// cleanup
320+
Py_DECREF(clz);
321+
Py_DECREF(args);
322+
Py_DECREF(dict);
323+
Py_DECREF(extras);
324+
// return instance or NULL if failed
319325
return instance;
320326
}
321327

@@ -373,7 +379,7 @@ PyObject *read_typetree_value(ReaderT *reader, TypeTreeNodeObject *node, TypeTre
373379
TypeTreeNodeObject *child = nullptr;
374380
if (PyList_GET_SIZE(node->m_Children) > 0)
375381
{
376-
child = (TypeTreeNodeObject *)PyList_GetItem(node->m_Children, 0);
382+
child = (TypeTreeNodeObject *)PyList_GET_ITEM(node->m_Children, 0);
377383
}
378384

379385
if (child && child->_data_type == NodeDataType::array)
@@ -389,7 +395,7 @@ PyObject *read_typetree_value(ReaderT *reader, TypeTreeNodeObject *node, TypeTre
389395
return NULL;
390396
}
391397
value = PyList_New(length);
392-
child = (TypeTreeNodeObject *)PyList_GetItem(child->m_Children, 1);
398+
child = (TypeTreeNodeObject *)PyList_GET_ITEM(child->m_Children, 1);
393399
for (int i = 0; i < length; i++)
394400
{
395401
PyObject *item = read_typetree_value<swap>(reader, child, config);
@@ -405,30 +411,27 @@ PyObject *read_typetree_value(ReaderT *reader, TypeTreeNodeObject *node, TypeTre
405411
{
406412
// class
407413
value = PyDict_New();
408-
if (config->as_dict)
414+
for (int i = 0; i < PyList_GET_SIZE(node->m_Children); i++)
409415
{
410-
for (int i = 0; i < PyList_GET_SIZE(node->m_Children); i++)
416+
child = (TypeTreeNodeObject *)PyList_GET_ITEM(node->m_Children, i);
417+
PyObject *child_value = read_typetree_value<swap>(reader, child, config);
418+
if (!child_value)
411419
{
412-
child = (TypeTreeNodeObject *)PyList_GetItem(node->m_Children, i);
413-
PyObject *child_value = read_typetree_value<swap>(reader, child, config);
414-
if (!child_value)
415-
{
416-
Py_DECREF(value);
417-
return NULL;
418-
}
419-
if (PyDict_SetItem(value, child->m_Name, child_value))
420-
{
421-
Py_DECREF(value);
422-
Py_DECREF(child_value);
423-
return NULL;
424-
}
425-
// dict increases ref count, so we need to decref here
420+
Py_DECREF(value);
421+
return NULL;
422+
}
423+
if (PyDict_SetItem(value, child->m_Name, child_value))
424+
{
425+
Py_DECREF(value);
426426
Py_DECREF(child_value);
427+
return NULL;
427428
}
429+
// dict increases ref count, so we need to decref here
430+
Py_DECREF(child_value);
428431
}
429-
else
432+
if (!config->as_dict)
430433
{
431-
value = read_class<swap>(reader, node, config);
434+
value = parse_class<swap>(reader, value, node, config);
432435
}
433436
}
434437
}
@@ -481,6 +484,9 @@ PyObject *read_typetree(PyObject *self, PyObject *args, PyObject *kwargs)
481484
return NULL;
482485
}
483486
}
487+
Py_INCREF(config.assetfile);
488+
Py_INCREF(config.classes);
489+
Py_INCREF(config.clean_name);
484490

485491
volatile uint16_t bint = 0x0100;
486492
volatile bool is_big_endian = ((uint8_t *)&bint)[0] == 1;
@@ -626,14 +632,13 @@ static int TypeTreeNode_init(TypeTreeNodeObject *self, PyObject *args, PyObject
626632
Py_XINCREF(self->m_Children);
627633
}
628634

629-
#define SET_NONE_IF_NULL(field) \
630-
if (self->field == nullptr) \
631-
{ \
632-
self->field = Py_None; \
633-
} \
634-
else \
635-
{ \
636-
Py_INCREF(self->field); \
635+
#define SET_NONE_IF_NULL(field) \
636+
{ \
637+
if (self->field == nullptr) \
638+
{ \
639+
self->field = Py_None; \
640+
} \
641+
Py_INCREF(self->field); \
637642
}
638643

639644
SET_NONE_IF_NULL(m_TypeFlags);

0 commit comments

Comments
 (0)