comparison configmix/_speedups.c @ 561:c51f484387ee

FIX: Remove bogus comment
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 06 Jan 2022 20:03:01 +0100
parents 81238ea2dbe3
children f75c5b13a1d7
comparison
equal deleted inserted replaced
560:81238ea2dbe3 561:c51f484387ee
820 } 820 }
821 /* Unpack the result tuple */ 821 /* Unpack the result tuple */
822 /* borrowed -- cannot fail -- need ownership */ 822 /* borrowed -- cannot fail -- need ownership */
823 varname = Py_NewRef(PyTuple_GetItem(tmp, 0)); 823 varname = Py_NewRef(PyTuple_GetItem(tmp, 0));
824 /* borrowed -- cannot fail -- want ownership */ 824 /* borrowed -- cannot fail -- want ownership */
825 filters = Py_NewRef(PyTuple_GetItem(tmp, 1));
826 py_clear_ref(&tmp);
827
828 tmp = PyObject_CallMethod(
829 config, "_getvar_s_with_cache_info", "O", varname);
830 if (tmp == NULL) {
831 if (PyErr_ExceptionMatches(PyExc_KeyError)) {
832 /* XXX TBD handle KeyError (None and Empty-filter) */
833 cacheable = 1;
834 if (PySequence_Contains(filters, sstate->NONE_FILTER) == 1) {
835 PyErr_Clear();
836 varvalue = Py_NewRef(Py_None);
837 }
838 else {
839 if (PySequence_Contains(filters, sstate->EMPTY_FILTER) == 1) {
840 PyErr_Clear();
841 varvalue = Py_NewRef(sstate->EMPTY_STR);
842 }
843 else {
844 PyErr_Fetch(&err_type, &err_value, &err_tb);
845 /* this does NOT steal */
846 PyDict_SetItem(cache, s, sstate->MISSING);
847 PyErr_Restore(err_type, err_value, err_tb);
848 goto error;
849 }
850 }
851 }
852 else {
853 /* other exception/error than KeyError */
854 goto error;
855 }
856 }
857 else {
858 if (PyTuple_Size(tmp) != 2) {
859 py_clear_ref(&tmp);
860 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
861 goto error;
862 }
863 /* unpack the result */
864 /* borrowed -- cannot fail -- but want ownership */
865 varvalue = Py_NewRef(PyTuple_GetItem(tmp, 0));
866 cacheable = PyObject_IsTrue(PyTuple_GetItem(tmp, 1));
867 py_clear_ref(&tmp);
868 }
869
870 if (!cacheable) {
871 use_cache = 0;
872 }
873
874 py_clear_ref(&varname);
875
876 tmp = PyObject_CallMethod(
877 config, "_apply_filters", "OO", filters, varvalue);
878 if (tmp == NULL) {
879 goto error;
880 }
881 py_clear_ref(&varvalue);
882
883 py_clear_ref(&filters);
884
885 /*
886 * Dont apply and type conversions to the variable value if
887 * the whole `s` is just one expansion
888 */
889 if (first_part_is_empty && (i == 1) && (pb_len == s_len - 2) && (idx == pb_len - 2)) {
890 res = varvalue; varvalue = NULL;
891 goto success; /* break out early */
892 }
893 if (py_object_isnot(varvalue, Py_None)) {
894 tmp = PyObject_Str(varvalue);
895 if (tmp == NULL) {
896 goto error;
897 }
898 if (PyList_Append(res_parts, tmp) < 0) {
899 py_clear_ref(&tmp);
900 goto error;
901 }
902 py_clear_ref(&tmp);
903 }
904 py_clear_ref(&varvalue);
905 /* append the rest of the string */
906 tmp = PyUnicode_Substring(pb, idx+2, pb_len);
907 if (tmp == NULL) {
908 goto error;
909 }
910 if (PyList_Append(res_parts, tmp) < 0) {
911 py_clear_ref(&tmp);
912 goto error;
913 }
914 py_clear_ref(&tmp);
915 }
916
917 res = PyUnicode_Join(sstate->EMPTY_STR, res_parts);
918 if (res == NULL) {
919 goto error;
920 }
921
922 success:
923 Py_DECREF(parts);
924 Py_DECREF(res_parts);
925
926 if (use_cache) {
927 PyDict_SetItem(cache, s, res);
928 PyErr_Clear(); /* clear any possible cache-related error */
929 }
930 return res;
931
932 error:
933 Py_XDECREF(varname);
934 Py_XDECREF(varvalue);
935 Py_XDECREF(filters);
936 Py_XDECREF(parts);
937 Py_XDECREF(res_parts);
938 Py_XDECREF(res);
939 return NULL;
940 }
941
942
943 static
944 PyObject *
945 fast_interpolate_variables(PyObject *self, PyObject *args)
946 {
947 PyObject *config;
948 PyObject *s;
949 PyObject *cache;
950
951 Py_ssize_t s_len;
952 Py_ssize_t start, rest, end;
953 PyObject *tmp;
954 PyObject *result = NULL;
955 PyObject *varname = NULL;
956 PyObject *varvalue = NULL;
957 PyObject *filters = NULL;
958 PyObject *err_type;
959 PyObject *err_value;
960 PyObject *err_tb;
961 int use_cache, cacheable;
962 struct speedups_state *sstate;
963
964 if (!PyArg_UnpackTuple(args, "s", 3, 3, &config, &s, &cache)) {
965 return NULL;
966 }
967 s_len = PyUnicode_GetLength(s); /* also an implicit type check */
968 if (s_len < 0) {
969 return NULL;
970 }
971 if (s_len < 4) {
972 return Py_NewRef(s);
973 }
974
975 sstate = PyModule_GetState(self);
976 if (sstate == NULL) {
977 PyErr_SetString(PyExc_RuntimeError, "no module state available");
978 return NULL;
979 }
980
981 start = PyUnicode_Find(s, sstate->STARTTOK, 0, s_len, 1);
982 if (start == -2) {
983 return NULL;
984 }
985 if (start == -1) {
986 return Py_NewRef(s);
987 }
988
989 result = PyDict_GetItem(cache, s); /* borrowed */
990 if (result != NULL) {
991 if (result == sstate->MISSING) {
992 return PyErr_Format(
993 PyExc_KeyError,
994 "Cannot interpolate variables in string %R (cached)",
995 s);
996 }
997 else {
998 return Py_NewRef(result);
999 }
1000 }
1001
1002 result = PyList_New(0);
1003 if (result == 0) {
1004 return NULL;
1005 }
1006
1007 rest = 0;
1008 use_cache = 1;
1009
1010 while (start != -1) {
1011 if (rest < start) {
1012 tmp = PyUnicode_Substring(s, rest, start);
1013 if (tmp == NULL) {
1014 goto error;
1015 }
1016 if (PyList_Append(result, tmp) < 0) {
1017 py_clear_ref(&tmp);
1018 goto error;
1019 }
1020 py_clear_ref(&tmp);
1021 }
1022 end = PyUnicode_Find(s, sstate->ENDTOK, start+2, s_len, 1);
1023 if (end == -2) {
1024 goto error;
1025 }
1026 if (end == -1) {
1027 rest = start;
1028 break;
1029 }
1030
1031 varname = PyUnicode_Substring(s, start+2, end); /* 2 == len(STARTTOK) */
1032 if (varname == NULL) {
1033 goto error;
1034 }
1035
1036 tmp = _fast_split_filters(varname, NULL, sstate);
1037 if (tmp == NULL) {
1038 goto error;
1039 }
1040 if (PyTuple_Size(tmp) != 2) {
1041 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
1042 py_clear_ref(&tmp);
1043 goto error;
1044 }
1045 /* Unpack the result tuple */
1046 /* borrowed -- cannot fail -- need ownership */
1047 varname = Py_NewRef(PyTuple_GetItem(tmp, 0));
1048 /* borrowed -- cannot fail -- need ownership */
1049 filters = Py_NewRef(PyTuple_GetItem(tmp, 1)); 825 filters = Py_NewRef(PyTuple_GetItem(tmp, 1));
1050 py_clear_ref(&tmp); 826 py_clear_ref(&tmp);
1051 827
1052 tmp = PyObject_CallMethod( 828 tmp = PyObject_CallMethod(
1053 config, "_getvar_s_with_cache_info", "O", varname); 829 config, "_getvar_s_with_cache_info", "O", varname);
1082 py_clear_ref(&tmp); 858 py_clear_ref(&tmp);
1083 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected"); 859 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
1084 goto error; 860 goto error;
1085 } 861 }
1086 /* unpack the result */ 862 /* unpack the result */
863 /* borrowed -- cannot fail -- but want ownership */
864 varvalue = Py_NewRef(PyTuple_GetItem(tmp, 0));
865 cacheable = PyObject_IsTrue(PyTuple_GetItem(tmp, 1));
866 py_clear_ref(&tmp);
867 }
868
869 if (!cacheable) {
870 use_cache = 0;
871 }
872
873 py_clear_ref(&varname);
874
875 tmp = PyObject_CallMethod(
876 config, "_apply_filters", "OO", filters, varvalue);
877 if (tmp == NULL) {
878 goto error;
879 }
880 py_clear_ref(&varvalue);
881
882 py_clear_ref(&filters);
883
884 /*
885 * Dont apply and type conversions to the variable value if
886 * the whole `s` is just one expansion
887 */
888 if (first_part_is_empty && (i == 1) && (pb_len == s_len - 2) && (idx == pb_len - 2)) {
889 res = varvalue; varvalue = NULL;
890 goto success; /* break out early */
891 }
892 if (py_object_isnot(varvalue, Py_None)) {
893 tmp = PyObject_Str(varvalue);
894 if (tmp == NULL) {
895 goto error;
896 }
897 if (PyList_Append(res_parts, tmp) < 0) {
898 py_clear_ref(&tmp);
899 goto error;
900 }
901 py_clear_ref(&tmp);
902 }
903 py_clear_ref(&varvalue);
904 /* append the rest of the string */
905 tmp = PyUnicode_Substring(pb, idx+2, pb_len);
906 if (tmp == NULL) {
907 goto error;
908 }
909 if (PyList_Append(res_parts, tmp) < 0) {
910 py_clear_ref(&tmp);
911 goto error;
912 }
913 py_clear_ref(&tmp);
914 }
915
916 res = PyUnicode_Join(sstate->EMPTY_STR, res_parts);
917 if (res == NULL) {
918 goto error;
919 }
920
921 success:
922 Py_DECREF(parts);
923 Py_DECREF(res_parts);
924
925 if (use_cache) {
926 PyDict_SetItem(cache, s, res);
927 PyErr_Clear(); /* clear any possible cache-related error */
928 }
929 return res;
930
931 error:
932 Py_XDECREF(varname);
933 Py_XDECREF(varvalue);
934 Py_XDECREF(filters);
935 Py_XDECREF(parts);
936 Py_XDECREF(res_parts);
937 Py_XDECREF(res);
938 return NULL;
939 }
940
941
942 static
943 PyObject *
944 fast_interpolate_variables(PyObject *self, PyObject *args)
945 {
946 PyObject *config;
947 PyObject *s;
948 PyObject *cache;
949
950 Py_ssize_t s_len;
951 Py_ssize_t start, rest, end;
952 PyObject *tmp;
953 PyObject *result = NULL;
954 PyObject *varname = NULL;
955 PyObject *varvalue = NULL;
956 PyObject *filters = NULL;
957 PyObject *err_type;
958 PyObject *err_value;
959 PyObject *err_tb;
960 int use_cache, cacheable;
961 struct speedups_state *sstate;
962
963 if (!PyArg_UnpackTuple(args, "s", 3, 3, &config, &s, &cache)) {
964 return NULL;
965 }
966 s_len = PyUnicode_GetLength(s); /* also an implicit type check */
967 if (s_len < 0) {
968 return NULL;
969 }
970 if (s_len < 4) {
971 return Py_NewRef(s);
972 }
973
974 sstate = PyModule_GetState(self);
975 if (sstate == NULL) {
976 PyErr_SetString(PyExc_RuntimeError, "no module state available");
977 return NULL;
978 }
979
980 start = PyUnicode_Find(s, sstate->STARTTOK, 0, s_len, 1);
981 if (start == -2) {
982 return NULL;
983 }
984 if (start == -1) {
985 return Py_NewRef(s);
986 }
987
988 result = PyDict_GetItem(cache, s); /* borrowed */
989 if (result != NULL) {
990 if (result == sstate->MISSING) {
991 return PyErr_Format(
992 PyExc_KeyError,
993 "Cannot interpolate variables in string %R (cached)",
994 s);
995 }
996 else {
997 return Py_NewRef(result);
998 }
999 }
1000
1001 result = PyList_New(0);
1002 if (result == 0) {
1003 return NULL;
1004 }
1005
1006 rest = 0;
1007 use_cache = 1;
1008
1009 while (start != -1) {
1010 if (rest < start) {
1011 tmp = PyUnicode_Substring(s, rest, start);
1012 if (tmp == NULL) {
1013 goto error;
1014 }
1015 if (PyList_Append(result, tmp) < 0) {
1016 py_clear_ref(&tmp);
1017 goto error;
1018 }
1019 py_clear_ref(&tmp);
1020 }
1021 end = PyUnicode_Find(s, sstate->ENDTOK, start+2, s_len, 1);
1022 if (end == -2) {
1023 goto error;
1024 }
1025 if (end == -1) {
1026 rest = start;
1027 break;
1028 }
1029
1030 varname = PyUnicode_Substring(s, start+2, end); /* 2 == len(STARTTOK) */
1031 if (varname == NULL) {
1032 goto error;
1033 }
1034
1035 tmp = _fast_split_filters(varname, NULL, sstate);
1036 if (tmp == NULL) {
1037 goto error;
1038 }
1039 if (PyTuple_Size(tmp) != 2) {
1040 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
1041 py_clear_ref(&tmp);
1042 goto error;
1043 }
1044 /* Unpack the result tuple */
1045 /* borrowed -- cannot fail -- need ownership */
1046 varname = Py_NewRef(PyTuple_GetItem(tmp, 0));
1047 /* borrowed -- cannot fail -- need ownership */
1048 filters = Py_NewRef(PyTuple_GetItem(tmp, 1));
1049 py_clear_ref(&tmp);
1050
1051 tmp = PyObject_CallMethod(
1052 config, "_getvar_s_with_cache_info", "O", varname);
1053 if (tmp == NULL) {
1054 if (PyErr_ExceptionMatches(PyExc_KeyError)) {
1055 cacheable = 1;
1056 if (PySequence_Contains(filters, sstate->NONE_FILTER) == 1) {
1057 PyErr_Clear();
1058 varvalue = Py_NewRef(Py_None);
1059 }
1060 else {
1061 if (PySequence_Contains(filters, sstate->EMPTY_FILTER) == 1) {
1062 PyErr_Clear();
1063 varvalue = Py_NewRef(sstate->EMPTY_STR);
1064 }
1065 else {
1066 PyErr_Fetch(&err_type, &err_value, &err_tb);
1067 /* this does NOT steal */
1068 PyDict_SetItem(cache, s, sstate->MISSING);
1069 PyErr_Restore(err_type, err_value, err_tb);
1070 goto error;
1071 }
1072 }
1073 }
1074 else {
1075 /* other exception/error than KeyError */
1076 goto error;
1077 }
1078 }
1079 else {
1080 if (PyTuple_Size(tmp) != 2) {
1081 py_clear_ref(&tmp);
1082 PyErr_SetString(PyExc_TypeError, "tuple of size 2 expected");
1083 goto error;
1084 }
1085 /* unpack the result */
1087 /* borrowed -- but want own */ 1086 /* borrowed -- but want own */
1088 varvalue = Py_NewRef(PyTuple_GetItem(tmp, 0)); 1087 varvalue = Py_NewRef(PyTuple_GetItem(tmp, 0));
1089 cacheable = PyObject_IsTrue(PyTuple_GetItem(tmp, 1)); 1088 cacheable = PyObject_IsTrue(PyTuple_GetItem(tmp, 1));
1090 py_clear_ref(&tmp); 1089 py_clear_ref(&tmp);
1091 } 1090 }