diff options
-rw-r--r-- | Include/stringobject.h | 1 | ||||
-rw-r--r-- | Objects/dictobject.c | 7 | ||||
-rw-r--r-- | Objects/stringobject.c | 89 |
3 files changed, 81 insertions, 16 deletions
diff --git a/Include/stringobject.h b/Include/stringobject.h index 12df75a..fbcff31 100644 --- a/Include/stringobject.h +++ b/Include/stringobject.h @@ -58,6 +58,7 @@ extern DL_IMPORT(char *) PyString_AsString(PyObject *); extern DL_IMPORT(void) PyString_Concat(PyObject **, PyObject *); extern DL_IMPORT(void) PyString_ConcatAndDel(PyObject **, PyObject *); extern DL_IMPORT(int) _PyString_Resize(PyObject **, int); +extern DL_IMPORT(int) _PyString_Eq(PyObject *, PyObject*); extern DL_IMPORT(PyObject *) PyString_Format(PyObject *, PyObject *); extern DL_IMPORT(PyObject *) _PyString_FormatLong(PyObject*, int, int, int, char**, int*); diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 2854efc..d5700c9 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -294,7 +294,7 @@ lookdict(dictobject *mp, PyObject *key, register long hash) * this assumption allows testing for errors during PyObject_Compare() to * be dropped; string-string comparisons never raise exceptions. This also * means we don't need to go through PyObject_Compare(); we can always use - * the tp_compare slot of the string type object directly. + * _PyString_Eq directly. * * This really only becomes meaningful if proper error handling in lookdict() * is too expensive. @@ -308,7 +308,6 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash) register unsigned int mask = mp->ma_size-1; dictentry *ep0 = mp->ma_table; register dictentry *ep; - cmpfunc compare = PyString_Type.tp_compare; /* make sure this function doesn't have to handle non-string keys */ if (!PyString_Check(key)) { @@ -328,7 +327,7 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash) freeslot = ep; else { if (ep->me_hash == hash - && compare(ep->me_key, key) == 0) { + && _PyString_Eq(ep->me_key, key)) { return ep; } freeslot = NULL; @@ -347,7 +346,7 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash) if (ep->me_key == key || (ep->me_hash == hash && ep->me_key != dummy - && compare(ep->me_key, key) == 0)) + && _PyString_Eq(ep->me_key, key))) return ep; if (ep->me_key == dummy && freeslot == NULL) freeslot = ep; diff --git a/Objects/stringobject.c b/Objects/stringobject.c index cf6421a..da49d81 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -630,20 +630,79 @@ string_item(PyStringObject *a, register int i) return v; } -static int -string_compare(PyStringObject *a, PyStringObject *b) +static PyObject* +string_richcompare(PyStringObject *a, PyStringObject *b, int op) { - int len_a = a->ob_size, len_b = b->ob_size; - int min_len = (len_a < len_b) ? len_a : len_b; - int cmp; + int c; + int len_a, len_b; + int min_len; + PyObject *result; + + /* One of the objects is a string object. Make sure the + other one is one, too. */ + if (a->ob_type != b->ob_type) { + result = Py_NotImplemented; + goto out; + } + if (a == b) { + switch (op) { + case Py_EQ:case Py_LE:case Py_GE: + result = Py_True; + goto out; + case Py_NE:case Py_LT:case Py_GT: + result = Py_False; + goto out; + } + } + if (op == Py_EQ) { + /* Supporting Py_NE here as well does not save + much time, since Py_NE is rarely used. */ + if (a->ob_size == b->ob_size + && (a->ob_sval[0] == b->ob_sval[0] + && memcmp(a->ob_sval, b->ob_sval, + a->ob_size) == 0)) { + result = Py_True; + } else { + result = Py_False; + } + goto out; + } + len_a = a->ob_size; len_b = b->ob_size; + min_len = (len_a < len_b) ? len_a : len_b; if (min_len > 0) { - cmp = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); - if (cmp == 0) - cmp = memcmp(a->ob_sval, b->ob_sval, min_len); - if (cmp != 0) - return cmp; + c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); + if (c==0) + c = memcmp(a->ob_sval, b->ob_sval, min_len); + }else + c = 0; + if (c == 0) + c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; + switch (op) { + case Py_LT: c = c < 0; break; + case Py_LE: c = c <= 0; break; + case Py_EQ: assert(0); break; /* unreachable */ + case Py_NE: c = c != 0; break; + case Py_GT: c = c > 0; break; + case Py_GE: c = c >= 0; break; + default: + result = Py_NotImplemented; + goto out; } - return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; + result = c ? Py_True : Py_False; + out: + Py_INCREF(result); + return result; +} + +int +_PyString_Eq(PyObject *o1, PyObject *o2) +{ + PyStringObject *a, *b; + a = (PyStringObject*)o1; + b = (PyStringObject*)o2; + return a->ob_size == b->ob_size + && *a->ob_sval == *b->ob_sval + && memcmp(a->ob_sval, b->ob_sval, a->ob_size) == 0; } static long @@ -2466,7 +2525,7 @@ PyTypeObject PyString_Type = { (printfunc)string_print, /*tp_print*/ (getattrfunc)string_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ - (cmpfunc)string_compare, /*tp_compare*/ + 0, /*tp_compare*/ (reprfunc)string_repr, /*tp_repr*/ 0, /*tp_as_number*/ &string_as_sequence, /*tp_as_sequence*/ @@ -2479,6 +2538,12 @@ PyTypeObject PyString_Type = { &string_as_buffer, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + (richcmpfunc)string_richcompare, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ }; void |