comparison configmix/_speedups.c @ 704:457ef358c1a0

filter-only expansions also implemented in the C extension. BUGS: No caching yet (pure Python and C extension).
author Franz Glasner <f.glasner@feldmann-mg.com>
date Mon, 14 Aug 2023 13:00:19 +0200
parents 193a616e0b3c
children 0485a033c95d
comparison
equal deleted inserted replaced
703:193a616e0b3c 704:457ef358c1a0
38 PyObject *DEL_VALUE; 38 PyObject *DEL_VALUE;
39 }; 39 };
40 40
41 41
42 static PyObject * _fast_getvar_s(PyObject *config, PyObject *varname, PyObject *default_, struct speedups_state *sstate, int *cacheable); 42 static PyObject * _fast_getvar_s(PyObject *config, PyObject *varname, PyObject *default_, struct speedups_state *sstate, int *cacheable);
43 static PyObject * _fast_interpolate_variables(PyObject *self, PyObject *config, PyObject *s, PyObject *cache);
43 44
44 45
45 static 46 static
46 int 47 int
47 _hex2ucs4(PyObject *s, Py_ssize_t end, Py_UCS4 *result) 48 _hex2ucs4(PyObject *s, Py_ssize_t end, Py_UCS4 *result)
1033 { 1034 {
1034 PyObject *config; 1035 PyObject *config;
1035 PyObject *s; 1036 PyObject *s;
1036 PyObject *cache = NULL; 1037 PyObject *cache = NULL;
1037 1038
1039 if (!PyArg_UnpackTuple(args, "s", 2, 3, &config, &s, &cache)) {
1040 return NULL;
1041 }
1042 return _fast_interpolate_variables(self, config, s, cache);
1043 }
1044
1045
1046 static
1047 PyObject *
1048 _fast_interpolate_variables(PyObject *self, PyObject *config, PyObject *s, PyObject *cache)
1049 {
1038 int cmp; 1050 int cmp;
1039 Py_ssize_t s_len; 1051 Py_ssize_t s_len;
1040 Py_ssize_t start, rest, end; 1052 Py_ssize_t start, rest, end;
1041 PyObject *tmp; 1053 PyObject *tmp;
1042 PyObject *result = NULL; 1054 PyObject *result = NULL;
1047 PyObject *err_value; 1059 PyObject *err_value;
1048 PyObject *err_tb; 1060 PyObject *err_tb;
1049 int use_cache, cacheable; 1061 int use_cache, cacheable;
1050 struct speedups_state *sstate; 1062 struct speedups_state *sstate;
1051 1063
1052 if (!PyArg_UnpackTuple(args, "s", 2, 3, &config, &s, &cache)) {
1053 return NULL;
1054 }
1055 /* Disable caching if the cache param is given as None */ 1064 /* Disable caching if the cache param is given as None */
1056 if ((cache != NULL) && py_object_is(cache, Py_None)) { 1065 if ((cache != NULL) && py_object_is(cache, Py_None)) {
1057 cache = NULL; 1066 cache = NULL;
1058 } 1067 }
1059 s_len = PyUnicode_GetLength(s); /* also an implicit type check */ 1068 s_len = PyUnicode_GetLength(s); /* also an implicit type check */
1099 return Py_NewRef(result); 1108 return Py_NewRef(result);
1100 } 1109 }
1101 } 1110 }
1102 } 1111 }
1103 1112
1113 /* Check for {{| ... |}} */
1104 if ((s_len >= 6) 1114 if ((s_len >= 6)
1105 && (start == 0) 1115 && (start == 0)
1106 && (PyUnicode_ReadChar(s, 2) == 0x7c /* | */)) { 1116 && (PyUnicode_ReadChar(s, 2) == 0x7c /* `|' */)) {
1107 end = PyUnicode_Find(s, sstate->ENDTOK_FILTER, start+3, s_len, 1); 1117 end = PyUnicode_Find(s, sstate->ENDTOK_FILTER, start+3, s_len, 1);
1108 if (end == -2) { 1118 if (end == -2) {
1109 return NULL; 1119 return NULL;
1110 } 1120 }
1111 if (end != (s_len - 3)) { 1121 if (end != (s_len - 3)) {
1112 PyErr_SetString(PyExc_ValueError, "XXX") ; /*`{{|' global filter interpolation must end with `|}}'"); */ 1122 PyErr_SetString(PyExc_ValueError, "`{{|' global filter interpolation must end with `|}}'");
1113 return NULL; 1123 return NULL;
1114 } 1124 }
1125 /*
1126 * Handle {{| ... |filters, ... |}} :
1127 * split and recurse and apply filters
1128 */
1115 tmp = PyUnicode_Substring(s, 3, s_len-3); 1129 tmp = PyUnicode_Substring(s, 3, s_len-3);
1116 if (tmp == NULL) { 1130 if (tmp == NULL) {
1117 return NULL; 1131 return NULL;
1118 } 1132 }
1119 filters = _fast_split_filters(tmp, NULL, sstate); 1133 filters = _fast_split_filters(tmp, NULL, sstate);
1125 py_clear_ref(&tmp); 1139 py_clear_ref(&tmp);
1126 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected"); 1140 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
1127 goto error; 1141 goto error;
1128 } 1142 }
1129 py_transfer_owned(&tmp, &filters); 1143 py_transfer_owned(&tmp, &filters);
1130 1144 /* Unpack the result tuple */
1131 /* XXX TBD */ 1145 /* borrowed -- cannot fail -- need ownership */
1146 varname = Py_NewRef(PyTuple_GetItem(tmp, 0));
1147 /* borrowed -- cannot fail -- need ownership */
1148 filters = Py_NewRef(PyTuple_GetItem(tmp, 1));
1132 py_clear_ref(&tmp); 1149 py_clear_ref(&tmp);
1133 PyErr_SetString(PyExc_KeyError, "ERRRRRRR in C"); 1150
1134 return NULL; 1151 varvalue = _fast_interpolate_variables(self, config, varname, cache);
1152 if (varvalue == NULL) {
1153 if (PyErr_ExceptionMatches(PyExc_KeyError)) {
1154 if (PySequence_Contains(filters, sstate->NONE_FILTER) == 1) {
1155 PyErr_Clear();
1156 varvalue = Py_NewRef(Py_None);
1157 }
1158 else {
1159 if (PySequence_Contains(filters, sstate->EMPTY_FILTER) == 1) {
1160 PyErr_Clear();
1161 varvalue = Py_NewRef(sstate->EMPTY_STR);
1162 }
1163 else {
1164 goto error;
1165 }
1166 }
1167 }
1168 else {
1169 /* other exception/error than KeyError */
1170 goto error;
1171 }
1172 }
1173 py_clear_ref(&varname);
1174 result = PyObject_CallMethod(
1175 config, "_apply_filters", "OO", filters, varvalue);
1176 if (result == NULL) {
1177 goto error;
1178 }
1179 py_clear_ref(&varvalue);
1180 py_clear_ref(&filters);
1181 return result;
1135 } 1182 }
1136 1183
1137 result = PyList_New(0); 1184 result = PyList_New(0);
1138 if (result == NULL) { 1185 if (result == NULL) {
1139 return NULL; 1186 return NULL;