CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
_speedups.c201 linesDownload Raw Back to markupsafe
1#include <Python.h>
2
3#define GET_DELTA(inp, inp_end, delta) \
4	while (inp < inp_end) { \
5		switch (*inp++) { \
6		case '"': \
7		case '\'': \
8		case '&': \
9			delta += 4; \
10			break; \
11		case '<': \
12		case '>': \
13			delta += 3; \
14			break; \
15		} \
16	}
17
18#define DO_ESCAPE(inp, inp_end, outp) \
19	{ \
20		Py_ssize_t ncopy = 0; \
21		while (inp < inp_end) { \
22			switch (*inp) { \
23			case '"': \
24				memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
25				outp += ncopy; ncopy = 0; \
26				*outp++ = '&'; \
27				*outp++ = '#'; \
28				*outp++ = '3'; \
29				*outp++ = '4'; \
30				*outp++ = ';'; \
31				break; \
32			case '\'': \
33				memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
34				outp += ncopy; ncopy = 0; \
35				*outp++ = '&'; \
36				*outp++ = '#'; \
37				*outp++ = '3'; \
38				*outp++ = '9'; \
39				*outp++ = ';'; \
40				break; \
41			case '&': \
42				memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
43				outp += ncopy; ncopy = 0; \
44				*outp++ = '&'; \
45				*outp++ = 'a'; \
46				*outp++ = 'm'; \
47				*outp++ = 'p'; \
48				*outp++ = ';'; \
49				break; \
50			case '<': \
51				memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
52				outp += ncopy; ncopy = 0; \
53				*outp++ = '&'; \
54				*outp++ = 'l'; \
55				*outp++ = 't'; \
56				*outp++ = ';'; \
57				break; \
58			case '>': \
59				memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
60				outp += ncopy; ncopy = 0; \
61				*outp++ = '&'; \
62				*outp++ = 'g'; \
63				*outp++ = 't'; \
64				*outp++ = ';'; \
65				break; \
66			default: \
67				ncopy++; \
68			} \
69			inp++; \
70		} \
71		memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
72	}
73
74static PyObject*
75escape_unicode_kind1(PyUnicodeObject *in)
76{
77	Py_UCS1 *inp = PyUnicode_1BYTE_DATA(in);
78	Py_UCS1 *inp_end = inp + PyUnicode_GET_LENGTH(in);
79	Py_UCS1 *outp;
80	PyObject *out;
81	Py_ssize_t delta = 0;
82
83	GET_DELTA(inp, inp_end, delta);
84	if (!delta) {
85		Py_INCREF(in);
86		return (PyObject*)in;
87	}
88
89	out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta,
90						PyUnicode_IS_ASCII(in) ? 127 : 255);
91	if (!out)
92		return NULL;
93
94	inp = PyUnicode_1BYTE_DATA(in);
95	outp = PyUnicode_1BYTE_DATA(out);
96	DO_ESCAPE(inp, inp_end, outp);
97	return out;
98}
99
100static PyObject*
101escape_unicode_kind2(PyUnicodeObject *in)
102{
103	Py_UCS2 *inp = PyUnicode_2BYTE_DATA(in);
104	Py_UCS2 *inp_end = inp + PyUnicode_GET_LENGTH(in);
105	Py_UCS2 *outp;
106	PyObject *out;
107	Py_ssize_t delta = 0;
108
109	GET_DELTA(inp, inp_end, delta);
110	if (!delta) {
111		Py_INCREF(in);
112		return (PyObject*)in;
113	}
114
115	out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 65535);
116	if (!out)
117		return NULL;
118
119	inp = PyUnicode_2BYTE_DATA(in);
120	outp = PyUnicode_2BYTE_DATA(out);
121	DO_ESCAPE(inp, inp_end, outp);
122	return out;
123}
124
125
126static PyObject*
127escape_unicode_kind4(PyUnicodeObject *in)
128{
129	Py_UCS4 *inp = PyUnicode_4BYTE_DATA(in);
130	Py_UCS4 *inp_end = inp + PyUnicode_GET_LENGTH(in);
131	Py_UCS4 *outp;
132	PyObject *out;
133	Py_ssize_t delta = 0;
134
135	GET_DELTA(inp, inp_end, delta);
136	if (!delta) {
137		Py_INCREF(in);
138		return (PyObject*)in;
139	}
140
141	out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 1114111);
142	if (!out)
143		return NULL;
144
145	inp = PyUnicode_4BYTE_DATA(in);
146	outp = PyUnicode_4BYTE_DATA(out);
147	DO_ESCAPE(inp, inp_end, outp);
148	return out;
149}
150
151static PyObject*
152escape_unicode(PyObject *self, PyObject *s)
153{
154	if (!PyUnicode_Check(s))
155		return NULL;
156
157    // This check is no longer needed in Python 3.12.
158	if (PyUnicode_READY(s))
159		return NULL;
160
161	switch (PyUnicode_KIND(s)) {
162	case PyUnicode_1BYTE_KIND:
163		return escape_unicode_kind1((PyUnicodeObject*) s);
164	case PyUnicode_2BYTE_KIND:
165		return escape_unicode_kind2((PyUnicodeObject*) s);
166	case PyUnicode_4BYTE_KIND:
167		return escape_unicode_kind4((PyUnicodeObject*) s);
168	}
169	assert(0);  /* shouldn't happen */
170	return NULL;
171}
172
173static PyMethodDef module_methods[] = {
174	{"_escape_inner", (PyCFunction)escape_unicode, METH_O, NULL},
175	{NULL, NULL, 0, NULL}  /* Sentinel */
176};
177
178static PyModuleDef_Slot module_slots[] = {
179#ifdef Py_mod_multiple_interpreters  // Python 3.12+
180	{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
181#endif
182#ifdef Py_mod_gil  // Python 3.13+
183	{Py_mod_gil, Py_MOD_GIL_NOT_USED},
184#endif
185	{0, NULL}  /* Sentinel */
186};
187
188static struct PyModuleDef module_definition = {
189	.m_base = PyModuleDef_HEAD_INIT,
190	.m_name = "markupsafe._speedups",
191	.m_size = 0,
192	.m_methods = module_methods,
193	.m_slots = module_slots,
194};
195
196PyMODINIT_FUNC
197PyInit__speedups(void)
198{
199	return PyModuleDef_Init(&module_definition);
200}
201 
Aluode/PerceptionLabPortable · CoolFace