@@ -12,78 +12,74 @@ Created on Feb 10, 2022
12
12
#define PY_SSIZE_T_CLEAN
13
13
#include <Python.h>
14
14
15
- const char * alphabet = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" ;
15
+ const char alphabet [] = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" ;
16
+ // C adds a null at the end so it needs -1
17
+ const uint64_t alphabet_size = sizeof (alphabet ) / sizeof (alphabet [0 ]) - 1 ;
18
+ const uint8_t id_size = 8 ;
19
+
20
+ static PyObject * Tag = 0 ;
21
+ static PyObject * children_str = 0 ;
16
22
17
23
/**
18
24
* Generate a short ID (8 characters)
19
25
*/
20
- static PyObject * gen_id (PyObject * self , PyObject * obj )
26
+ static PyObject * gen_id (PyObject * mod , PyObject * obj )
21
27
{
22
- // Builtin ID
23
- PyObject * id = PyLong_FromVoidPtr (obj );
24
- if (id && PySys_Audit ("builtins.id" , "O" , id ) < 0 ) {
25
- Py_DECREF (id );
26
- return NULL ;
27
- }
28
- // TODO: Should there be some randomness?
29
- uint64_t number = PyLong_AsUnsignedLong (id );
30
- uint8_t index = 0 ;
31
- char buf [8 ];
32
- while (index < 8 )
28
+ uint64_t number = (uint64_t ) obj ;
29
+ char buf [id_size ];
30
+ for (uint8_t index = 0 ; index < id_size ; index ++ )
33
31
{
34
- // Mod must match sizeof alphabet
35
- lldiv_t r = lldiv (number , 59 );
32
+ lldiv_t r = lldiv (number , alphabet_size );
36
33
number = r .quot ;
37
34
buf [index ] = alphabet [r .rem ];
38
- index += 1 ;
39
35
}
40
- Py_DECREF (id );
41
- return PyUnicode_FromStringAndSize (buf , 8 );
36
+ return PyUnicode_FromStringAndSize (buf , id_size );
42
37
}
43
38
44
39
/**
45
40
* Lookup the index of the child tag from the parent's children list ignoring
46
41
* any pattern nodes. This provides about a 30% speedup.
47
42
*/
48
- static PyObject * lookup_child_index (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
43
+ static PyObject * lookup_child_index (PyObject * mod , PyObject * const * args , Py_ssize_t nargs )
49
44
{
50
45
if (nargs != 2 ) {
51
46
PyErr_SetString ( PyExc_ValueError , "must take exactly 2 arguments" );
52
47
return 0 ;
53
48
}
54
49
55
- PyObject * module = PyImport_ImportModule ("web.components.html" );
56
- if (!module ) {
57
- PyErr_SetString ( PyExc_ImportError , "Could not import web.components.html" );
58
- return 0 ;
59
- }
50
+ // Deferred import of web.components.html.Tag
51
+ if ( !Tag ) {
52
+ PyObject * module = PyImport_ImportModule ("web.components.html" );
53
+ if (!module ) {
54
+ PyErr_SetString ( PyExc_ImportError , "Could not import web.components.html" );
55
+ return 0 ;
56
+ }
60
57
61
- PyObject * Tag = PyObject_GetAttrString (module , "Tag" );
62
- Py_DECREF (module );
63
- if (!Tag ) {
64
- PyErr_SetString ( PyExc_ImportError , "Could not import web.components.html.Tag" );
65
- return 0 ;
58
+ Tag = PyObject_GetAttrString (module , "Tag" );
59
+ Py_DECREF (module );
60
+ if ( !Tag ) {
61
+ PyErr_SetString ( PyExc_ImportError , "Could not import web.components.html.Tag" );
62
+ return 0 ;
63
+ }
66
64
}
67
65
68
66
PyObject * parent = args [0 ];
69
67
PyObject * child = args [1 ];
70
68
if (!PyObject_IsInstance (parent , Tag ) || !PyObject_IsInstance (child , Tag )) {
71
69
PyErr_SetString ( PyExc_TypeError , "Both arguments must be Tags" );
72
- Py_DECREF (Tag );
73
70
return 0 ;
74
71
}
75
72
76
- PyObject * children = PyObject_GetAttrString (parent , "_children" );
73
+ PyObject * children = PyObject_GetAttr (parent , children_str );
77
74
if (!children || !PyList_Check (children )) {
78
75
PyErr_SetString ( PyExc_TypeError , "Tag's children must be a list" );
79
- Py_DECREF (children );
80
- Py_DECREF (Tag );
76
+ Py_XDECREF (children );
81
77
return 0 ;
82
78
}
83
79
84
80
uint32_t index = 0 ;
85
81
uint8_t found = 0 ;
86
- for (uint32_t i = 0 ; i < PyList_Size (children ); i ++ ) {
82
+ for (uint32_t i = 0 ; i < PyList_GET_SIZE (children ); i ++ ) {
87
83
PyObject * c = PyList_GET_ITEM (children , i );
88
84
if (c == child )
89
85
{
@@ -95,7 +91,6 @@ static PyObject * lookup_child_index(PyObject *self, PyObject *const *args, Py_s
95
91
index += 1 ;
96
92
}
97
93
Py_DECREF (children );
98
- Py_DECREF (Tag );
99
94
100
95
if (!found ) {
101
96
PyErr_SetString ( PyExc_KeyError , "Child not found" );
@@ -121,5 +116,9 @@ static PyModuleDef speedups_module = {
121
116
PyMODINIT_FUNC
122
117
PyInit_speedups (void )
123
118
{
119
+ children_str = PyUnicode_InternFromString ("_children" );
120
+ if ( !children_str )
121
+ return 0 ;
122
+
124
123
return PyModule_Create ( & speedups_module );
125
124
}
0 commit comments