summaryrefslogtreecommitdiff
path: root/Objects
diff options
context:
space:
mode:
authorMariatta Wijaya <mariatta.wijaya@gmail.com>2017-02-06 20:16:58 -0800
committerMariatta Wijaya <mariatta.wijaya@gmail.com>2017-02-06 20:16:58 -0800
commitda79bcf8ac7ae72218ab023e1ed54390bc1a3a27 (patch)
tree74845e2dbd9521d9748b9c32f1922f4123083bf3 /Objects
parente3c7e835bdfc97750eb9b7fc0ad2493108c2d438 (diff)
parent1fe806ac56f8b83694d24ab604eb695d00bc8497 (diff)
downloadcpython-da79bcf8ac7ae72218ab023e1ed54390bc1a3a27.tar.gz
Issue #29371: merge with 3.5
Diffstat (limited to 'Objects')
-rw-r--r--Objects/abstract.c653
-rw-r--r--Objects/bytearrayobject.c1048
-rw-r--r--Objects/bytes_methods.c431
-rw-r--r--Objects/bytesobject.c2340
-rw-r--r--Objects/classobject.c29
-rw-r--r--Objects/clinic/bytearrayobject.c.h134
-rw-r--r--Objects/clinic/bytesobject.c.h137
-rw-r--r--Objects/clinic/dictobject.c.h5
-rw-r--r--Objects/clinic/unicodeobject.c.h5
-rw-r--r--Objects/codeobject.c116
-rw-r--r--Objects/complexobject.c63
-rw-r--r--Objects/descrobject.c38
-rw-r--r--Objects/dict-common.h60
-rw-r--r--Objects/dictobject.c1868
-rw-r--r--Objects/enumobject.c12
-rw-r--r--Objects/exceptions.c40
-rw-r--r--Objects/fileobject.c11
-rw-r--r--Objects/floatobject.c352
-rw-r--r--Objects/frameobject.c14
-rw-r--r--Objects/funcobject.c35
-rw-r--r--Objects/genobject.c1065
-rw-r--r--Objects/iterobject.c40
-rw-r--r--Objects/listobject.c66
-rw-r--r--Objects/listsort.txt2
-rw-r--r--Objects/lnotab_notes.txt47
-rw-r--r--Objects/longobject.c542
-rw-r--r--Objects/memoryobject.c100
-rw-r--r--Objects/methodobject.c152
-rw-r--r--Objects/moduleobject.c13
-rw-r--r--Objects/namespaceobject.c8
-rw-r--r--Objects/object.c85
-rw-r--r--Objects/obmalloc.c432
-rw-r--r--Objects/odictobject.c73
-rw-r--r--Objects/rangeobject.c34
-rw-r--r--Objects/setobject.c625
-rw-r--r--Objects/stringlib/codecs.h220
-rw-r--r--Objects/stringlib/ctype.h5
-rw-r--r--Objects/stringlib/fastsearch.h150
-rw-r--r--Objects/stringlib/find.h82
-rw-r--r--Objects/stringlib/find_max_char.h5
-rw-r--r--Objects/stringlib/join.h8
-rw-r--r--Objects/stringlib/localeutil.h4
-rw-r--r--Objects/stringlib/transmogrify.h615
-rw-r--r--Objects/stringlib/unicode_format.h2
-rw-r--r--Objects/structseq.c32
-rw-r--r--Objects/tupleobject.c19
-rw-r--r--Objects/typeobject.c544
-rw-r--r--Objects/unicodeobject.c2486
-rw-r--r--Objects/unicodetype_db.h1573
-rw-r--r--Objects/weakrefobject.c4
50 files changed, 9509 insertions, 6915 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 88205bd0ce..d838856d45 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -32,8 +32,10 @@ PyObject_Type(PyObject *o)
{
PyObject *v;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
v = (PyObject *)o->ob_type;
Py_INCREF(v);
return v;
@@ -137,12 +139,16 @@ PyObject_GetItem(PyObject *o, PyObject *key)
{
PyMappingMethods *m;
- if (o == NULL || key == NULL)
+ if (o == NULL || key == NULL) {
return null_error();
+ }
m = o->ob_type->tp_as_mapping;
- if (m && m->mp_subscript)
- return m->mp_subscript(o, key);
+ if (m && m->mp_subscript) {
+ PyObject *item = m->mp_subscript(o, key);
+ assert((item != NULL) ^ (PyErr_Occurred() != NULL));
+ return item;
+ }
if (o->ob_type->tp_as_sequence) {
if (PyIndex_Check(key)) {
@@ -669,13 +675,31 @@ PyObject_Format(PyObject *obj, PyObject *format_spec)
PyObject *result = NULL;
_Py_IDENTIFIER(__format__);
+ if (format_spec != NULL && !PyUnicode_Check(format_spec)) {
+ PyErr_Format(PyExc_SystemError,
+ "Format specifier must be a string, not %.200s",
+ Py_TYPE(format_spec)->tp_name);
+ return NULL;
+ }
+
+ /* Fast path for common types. */
+ if (format_spec == NULL || PyUnicode_GET_LENGTH(format_spec) == 0) {
+ if (PyUnicode_CheckExact(obj)) {
+ Py_INCREF(obj);
+ return obj;
+ }
+ if (PyLong_CheckExact(obj)) {
+ return PyObject_Str(obj);
+ }
+ }
+
/* If no format_spec is provided, use an empty string */
if (format_spec == NULL) {
empty = PyUnicode_New(0, 0);
format_spec = empty;
}
- /* Find the (unbound!) __format__ method (a borrowed reference) */
+ /* Find the (unbound!) __format__ method */
meth = _PyObject_LookupSpecial(obj, &PyId___format__);
if (meth == NULL) {
if (!PyErr_Occurred())
@@ -1122,8 +1146,10 @@ PyNumber_Negative(PyObject *o)
{
PyNumberMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
m = o->ob_type->tp_as_number;
if (m && m->nb_negative)
return (*m->nb_negative)(o);
@@ -1136,8 +1162,10 @@ PyNumber_Positive(PyObject *o)
{
PyNumberMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
m = o->ob_type->tp_as_number;
if (m && m->nb_positive)
return (*m->nb_positive)(o);
@@ -1150,8 +1178,10 @@ PyNumber_Invert(PyObject *o)
{
PyNumberMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
m = o->ob_type->tp_as_number;
if (m && m->nb_invert)
return (*m->nb_invert)(o);
@@ -1164,8 +1194,10 @@ PyNumber_Absolute(PyObject *o)
{
PyNumberMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
m = o->ob_type->tp_as_number;
if (m && m->nb_absolute)
return m->nb_absolute(o);
@@ -1181,8 +1213,10 @@ PyObject *
PyNumber_Index(PyObject *item)
{
PyObject *result = NULL;
- if (item == NULL)
+ if (item == NULL) {
return null_error();
+ }
+
if (PyLong_Check(item)) {
Py_INCREF(item);
return item;
@@ -1265,42 +1299,55 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err)
PyObject *
PyNumber_Long(PyObject *o)
{
+ PyObject *result;
PyNumberMethods *m;
PyObject *trunc_func;
Py_buffer view;
_Py_IDENTIFIER(__trunc__);
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
if (PyLong_CheckExact(o)) {
Py_INCREF(o);
return o;
}
m = o->ob_type->tp_as_number;
if (m && m->nb_int) { /* This should include subclasses of int */
- return (PyObject *)_PyLong_FromNbInt(o);
+ result = (PyObject *)_PyLong_FromNbInt(o);
+ if (result != NULL && !PyLong_CheckExact(result)) {
+ Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
+ }
+ return result;
}
trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__);
if (trunc_func) {
- PyObject *truncated = PyEval_CallObject(trunc_func, NULL);
- PyObject *int_instance;
+ result = PyEval_CallObject(trunc_func, NULL);
Py_DECREF(trunc_func);
- if (truncated == NULL || PyLong_Check(truncated))
- return truncated;
+ if (result == NULL || PyLong_CheckExact(result)) {
+ return result;
+ }
+ if (PyLong_Check(result)) {
+ Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
+ return result;
+ }
/* __trunc__ is specified to return an Integral type,
but int() needs to return an int. */
- m = truncated->ob_type->tp_as_number;
+ m = result->ob_type->tp_as_number;
if (m == NULL || m->nb_int == NULL) {
PyErr_Format(
PyExc_TypeError,
"__trunc__ returned non-Integral (type %.200s)",
- truncated->ob_type->tp_name);
- Py_DECREF(truncated);
+ result->ob_type->tp_name);
+ Py_DECREF(result);
return NULL;
}
- int_instance = (PyObject *)_PyLong_FromNbInt(truncated);
- Py_DECREF(truncated);
- return int_instance;
+ Py_SETREF(result, (PyObject *)_PyLong_FromNbInt(result));
+ if (result != NULL && !PyLong_CheckExact(result)) {
+ Py_SETREF(result, _PyLong_Copy((PyLongObject *)result));
+ }
+ return result;
}
if (PyErr_Occurred())
return NULL;
@@ -1322,7 +1369,7 @@ PyNumber_Long(PyObject *o)
PyByteArray_GET_SIZE(o), 10);
if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == 0) {
- PyObject *result, *bytes;
+ PyObject *bytes;
/* Copy to NUL-terminated buffer. */
bytes = PyBytes_FromStringAndSize((const char *)view.buf, view.len);
@@ -1346,23 +1393,43 @@ PyNumber_Float(PyObject *o)
{
PyNumberMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
+
+ if (PyFloat_CheckExact(o)) {
+ Py_INCREF(o);
+ return o;
+ }
m = o->ob_type->tp_as_number;
if (m && m->nb_float) { /* This should include subclasses of float */
PyObject *res = m->nb_float(o);
- if (res && !PyFloat_Check(res)) {
+ double val;
+ if (!res || PyFloat_CheckExact(res)) {
+ return res;
+ }
+ if (!PyFloat_Check(res)) {
PyErr_Format(PyExc_TypeError,
- "__float__ returned non-float (type %.200s)",
- res->ob_type->tp_name);
+ "%.50s.__float__ returned non-float (type %.50s)",
+ o->ob_type->tp_name, res->ob_type->tp_name);
Py_DECREF(res);
return NULL;
}
- return res;
+ /* Issue #26983: warn if 'res' not of exact type float. */
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "%.50s.__float__ returned non-float (type %.50s). "
+ "The ability to return an instance of a strict subclass of float "
+ "is deprecated, and may be removed in a future version of Python.",
+ o->ob_type->tp_name, res->ob_type->tp_name)) {
+ Py_DECREF(res);
+ return NULL;
+ }
+ val = PyFloat_AS_DOUBLE(res);
+ Py_DECREF(res);
+ return PyFloat_FromDouble(val);
}
if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */
- PyFloatObject *po = (PyFloatObject *)o;
- return PyFloat_FromDouble(po->ob_fval);
+ return PyFloat_FromDouble(PyFloat_AS_DOUBLE(o));
}
return PyFloat_FromString(o);
}
@@ -1430,8 +1497,9 @@ PySequence_Concat(PyObject *s, PyObject *o)
{
PySequenceMethods *m;
- if (s == NULL || o == NULL)
+ if (s == NULL || o == NULL) {
return null_error();
+ }
m = s->ob_type->tp_as_sequence;
if (m && m->sq_concat)
@@ -1454,8 +1522,9 @@ PySequence_Repeat(PyObject *o, Py_ssize_t count)
{
PySequenceMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
m = o->ob_type->tp_as_sequence;
if (m && m->sq_repeat)
@@ -1483,8 +1552,9 @@ PySequence_InPlaceConcat(PyObject *s, PyObject *o)
{
PySequenceMethods *m;
- if (s == NULL || o == NULL)
+ if (s == NULL || o == NULL) {
return null_error();
+ }
m = s->ob_type->tp_as_sequence;
if (m && m->sq_inplace_concat)
@@ -1507,8 +1577,9 @@ PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count)
{
PySequenceMethods *m;
- if (o == NULL)
+ if (o == NULL) {
return null_error();
+ }
m = o->ob_type->tp_as_sequence;
if (m && m->sq_inplace_repeat)
@@ -1536,16 +1607,19 @@ PySequence_GetItem(PyObject *s, Py_ssize_t i)
{
PySequenceMethods *m;
- if (s == NULL)
+ if (s == NULL) {
return null_error();
+ }
m = s->ob_type->tp_as_sequence;
if (m && m->sq_item) {
if (i < 0) {
if (m->sq_length) {
Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
+ if (l < 0) {
+ assert(PyErr_Occurred());
return NULL;
+ }
i += l;
}
}
@@ -1560,7 +1634,9 @@ PySequence_GetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)
{
PyMappingMethods *mp;
- if (!s) return null_error();
+ if (!s) {
+ return null_error();
+ }
mp = s->ob_type->tp_as_mapping;
if (mp && mp->mp_subscript) {
@@ -1687,8 +1763,9 @@ PySequence_Tuple(PyObject *v)
PyObject *result = NULL;
Py_ssize_t j;
- if (v == NULL)
+ if (v == NULL) {
return null_error();
+ }
/* Special-case the common tuple and list cases, for efficiency. */
if (PyTuple_CheckExact(v)) {
@@ -1768,8 +1845,9 @@ PySequence_List(PyObject *v)
PyObject *result; /* result list */
PyObject *rv; /* return value from PyList_Extend */
- if (v == NULL)
+ if (v == NULL) {
return null_error();
+ }
result = PyList_New(0);
if (result == NULL)
@@ -1789,8 +1867,9 @@ PySequence_Fast(PyObject *v, const char *m)
{
PyObject *it;
- if (v == NULL)
+ if (v == NULL) {
return null_error();
+ }
if (PyList_CheckExact(v) || PyTuple_CheckExact(v)) {
Py_INCREF(v);
@@ -1973,8 +2052,9 @@ PyMapping_GetItemString(PyObject *o, const char *key)
{
PyObject *okey, *r;
- if (key == NULL)
+ if (key == NULL) {
return null_error();
+ }
okey = PyUnicode_FromString(key);
if (okey == NULL)
@@ -2118,20 +2198,18 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
}
else {
if (err_occurred) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
-
Py_DECREF(result);
- if (func)
- PyErr_Format(PyExc_SystemError,
- "%R returned a result with an error set",
- func);
- else
- PyErr_Format(PyExc_SystemError,
- "%s returned a result with an error set",
- where);
- _PyErr_ChainExceptions(exc, val, tb);
+ if (func) {
+ _PyErr_FormatFromCause(PyExc_SystemError,
+ "%R returned a result with an error set",
+ func);
+ }
+ else {
+ _PyErr_FormatFromCause(PyExc_SystemError,
+ "%s returned a result with an error set",
+ where);
+ }
#ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */
Py_FatalError("a function returned a result with an error set");
@@ -2143,7 +2221,7 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
}
PyObject *
-PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
+PyObject_Call(PyObject *func, PyObject *args, PyObject *kwargs)
{
ternaryfunc call;
PyObject *result;
@@ -2152,6 +2230,8 @@ PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
because it may clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
+ assert(PyTuple_Check(args));
+ assert(kwargs == NULL || PyDict_Check(kwargs));
call = func->ob_type->tp_call;
if (call == NULL) {
@@ -2163,108 +2243,343 @@ PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
if (Py_EnterRecursiveCall(" while calling a Python object"))
return NULL;
- result = (*call)(func, arg, kw);
+ result = (*call)(func, args, kwargs);
Py_LeaveRecursiveCall();
return _Py_CheckFunctionResult(func, result, NULL);
}
-static PyObject*
-call_function_tail(PyObject *callable, PyObject *args)
+PyObject*
+_PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
{
- PyObject *retval;
+ PyObject *args;
+ Py_ssize_t i;
- if (args == NULL)
+ args = PyTuple_New(nargs);
+ if (args == NULL) {
return NULL;
+ }
- if (!PyTuple_Check(args)) {
- PyObject *a;
+ for (i=0; i < nargs; i++) {
+ PyObject *item = stack[i];
+ Py_INCREF(item);
+ PyTuple_SET_ITEM(args, i, item);
+ }
+
+ return args;
+}
+
+PyObject *
+_PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
+ PyObject *kwargs)
+{
+ ternaryfunc call;
+ PyObject *result = NULL;
+
+ /* _PyObject_FastCallDict() must not be called with an exception set,
+ because it may clear it (directly or indirectly) and so the
+ caller loses its exception */
+ assert(!PyErr_Occurred());
+
+ assert(func != NULL);
+ assert(nargs >= 0);
+ assert(nargs == 0 || args != NULL);
+ assert(kwargs == NULL || PyDict_Check(kwargs));
+
+ if (Py_EnterRecursiveCall(" while calling a Python object")) {
+ return NULL;
+ }
- a = PyTuple_New(1);
- if (a == NULL) {
- Py_DECREF(args);
+ if (PyFunction_Check(func)) {
+ result = _PyFunction_FastCallDict(func, args, nargs, kwargs);
+ }
+ else if (PyCFunction_Check(func)) {
+ result = _PyCFunction_FastCallDict(func, args, nargs, kwargs);
+ }
+ else {
+ PyObject *tuple;
+
+ /* Slow-path: build a temporary tuple */
+ call = func->ob_type->tp_call;
+ if (call == NULL) {
+ PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
+ func->ob_type->tp_name);
+ goto exit;
+ }
+
+ tuple = _PyStack_AsTuple(args, nargs);
+ if (tuple == NULL) {
+ goto exit;
+ }
+
+ result = (*call)(func, tuple, kwargs);
+ Py_DECREF(tuple);
+
+ result = _Py_CheckFunctionResult(func, result, NULL);
+ }
+
+exit:
+ Py_LeaveRecursiveCall();
+
+ return result;
+}
+
+/* Positional arguments are obj followed by args. */
+PyObject *
+_PyObject_Call_Prepend(PyObject *func,
+ PyObject *obj, PyObject *args, PyObject *kwargs)
+{
+ PyObject *small_stack[8];
+ PyObject **stack;
+ Py_ssize_t argcount;
+ PyObject *result;
+
+ assert(PyTuple_Check(args));
+
+ argcount = PyTuple_GET_SIZE(args);
+ if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
+ stack = small_stack;
+ }
+ else {
+ stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *));
+ if (stack == NULL) {
+ PyErr_NoMemory();
return NULL;
}
- PyTuple_SET_ITEM(a, 0, args);
- args = a;
}
- retval = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+ /* use borrowed references */
+ stack[0] = obj;
+ memcpy(&stack[1],
+ &PyTuple_GET_ITEM(args, 0),
+ argcount * sizeof(PyObject *));
- return retval;
+ result = _PyObject_FastCallDict(func,
+ stack, argcount + 1,
+ kwargs);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
+ return result;
+}
+
+PyObject *
+_PyStack_AsDict(PyObject **values, PyObject *kwnames)
+{
+ Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames);
+ PyObject *kwdict;
+ Py_ssize_t i;
+
+ kwdict = PyDict_New();
+ if (kwdict == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < nkwargs; i++) {
+ PyObject *key = PyTuple_GET_ITEM(kwnames, i);
+ PyObject *value = *values++;
+ assert(PyUnicode_CheckExact(key));
+ assert(PyDict_GetItem(kwdict, key) == NULL);
+ if (PyDict_SetItem(kwdict, key, value)) {
+ Py_DECREF(kwdict);
+ return NULL;
+ }
+ }
+ return kwdict;
+}
+
+PyObject **
+_PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
+ PyObject **p_kwnames, PyObject *func)
+{
+ PyObject **stack, **kwstack;
+ Py_ssize_t nkwargs;
+ Py_ssize_t pos, i;
+ PyObject *key, *value;
+ PyObject *kwnames;
+
+ assert(nargs >= 0);
+ assert(kwargs == NULL || PyDict_CheckExact(kwargs));
+
+ nkwargs = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
+ if (!nkwargs) {
+ *p_kwnames = NULL;
+ return args;
+ }
+
+ if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
+ if (stack == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ kwnames = PyTuple_New(nkwargs);
+ if (kwnames == NULL) {
+ PyMem_Free(stack);
+ return NULL;
+ }
+
+ /* Copy position arguments (borrowed references) */
+ memcpy(stack, args, nargs * sizeof(stack[0]));
+
+ kwstack = stack + nargs;
+ pos = i = 0;
+ /* This loop doesn't support lookup function mutating the dictionary
+ to change its size. It's a deliberate choice for speed, this function is
+ called in the performance critical hot code. */
+ while (PyDict_Next(kwargs, &pos, &key, &value)) {
+ Py_INCREF(key);
+ PyTuple_SET_ITEM(kwnames, i, key);
+ /* The stack contains borrowed references */
+ kwstack[i] = value;
+ i++;
+ }
+
+ *p_kwnames = kwnames;
+ return stack;
+}
+
+PyObject *
+_PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
+ PyObject *kwnames)
+{
+ PyObject *kwdict, *result;
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+
+ assert(nargs >= 0);
+ assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
+ assert((nargs == 0 && nkwargs == 0) || stack != NULL);
+ /* kwnames must only contains str strings, no subclass, and all keys must
+ be unique: these are implemented in Python/ceval.c and
+ _PyArg_ParseStack(). */
+
+ if (PyFunction_Check(func)) {
+ return _PyFunction_FastCallKeywords(func, stack, nargs, kwnames);
+ }
+
+ if (PyCFunction_Check(func)) {
+ return _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames);
+ }
+
+ if (nkwargs > 0) {
+ kwdict = _PyStack_AsDict(stack + nargs, kwnames);
+ if (kwdict == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ kwdict = NULL;
+ }
+
+ result = _PyObject_FastCallDict(func, stack, nargs, kwdict);
+ Py_XDECREF(kwdict);
+ return result;
+}
+
+static PyObject*
+call_function_tail(PyObject *callable, PyObject *args)
+{
+ PyObject *result;
+
+ assert(args != NULL);
+
+ if (!PyTuple_Check(args)) {
+ result = _PyObject_CallArg1(callable, args);
+ }
+ else {
+ result = PyObject_Call(callable, args, NULL);
+ }
+
+ return result;
}
PyObject *
PyObject_CallFunction(PyObject *callable, const char *format, ...)
{
va_list va;
- PyObject *args;
+ PyObject *args, *result;
- if (callable == NULL)
+ if (callable == NULL) {
return null_error();
+ }
- if (format && *format) {
- va_start(va, format);
- args = Py_VaBuildValue(format, va);
- va_end(va);
+ if (!format || !*format) {
+ return _PyObject_CallNoArg(callable);
}
- else
- args = PyTuple_New(0);
- if (args == NULL)
+
+ va_start(va, format);
+ args = Py_VaBuildValue(format, va);
+ va_end(va);
+ if (args == NULL) {
return NULL;
+ }
- return call_function_tail(callable, args);
+ result = call_function_tail(callable, args);
+ Py_DECREF(args);
+ return result;
}
PyObject *
_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
{
va_list va;
- PyObject *args;
+ PyObject *args, *result;
- if (callable == NULL)
+ if (callable == NULL) {
return null_error();
+ }
- if (format && *format) {
- va_start(va, format);
- args = _Py_VaBuildValue_SizeT(format, va);
- va_end(va);
+ if (!format || !*format) {
+ return _PyObject_CallNoArg(callable);
}
- else
- args = PyTuple_New(0);
- return call_function_tail(callable, args);
+ va_start(va, format);
+ args = _Py_VaBuildValue_SizeT(format, va);
+ va_end(va);
+ if (args == NULL) {
+ return NULL;
+ }
+
+ result = call_function_tail(callable, args);
+ Py_DECREF(args);
+ return result;
}
static PyObject*
callmethod(PyObject* func, const char *format, va_list va, int is_size_t)
{
- PyObject *retval = NULL;
- PyObject *args;
+ PyObject *args, *result;
+
+ assert(func != NULL);
if (!PyCallable_Check(func)) {
type_error("attribute of type '%.200s' is not callable", func);
- goto exit;
+ return NULL;
}
- if (format && *format) {
- if (is_size_t)
- args = _Py_VaBuildValue_SizeT(format, va);
- else
- args = Py_VaBuildValue(format, va);
+ if (!format || !*format) {
+ return _PyObject_CallNoArg(func);
}
- else
- args = PyTuple_New(0);
- retval = call_function_tail(func, args);
-
- exit:
- /* args gets consumed in call_function_tail */
- Py_XDECREF(func);
+ if (is_size_t) {
+ args = _Py_VaBuildValue_SizeT(format, va);
+ }
+ else {
+ args = Py_VaBuildValue(format, va);
+ }
+ if (args == NULL) {
+ return NULL;
+ }
- return retval;
+ result = call_function_tail(func, args);
+ Py_DECREF(args);
+ return result;
}
PyObject *
@@ -2274,8 +2589,9 @@ PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
PyObject *func = NULL;
PyObject *retval = NULL;
- if (o == NULL || name == NULL)
+ if (o == NULL || name == NULL) {
return null_error();
+ }
func = PyObject_GetAttrString(o, name);
if (func == NULL)
@@ -2284,6 +2600,7 @@ PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
va_start(va, format);
retval = callmethod(func, format, va, 0);
va_end(va);
+ Py_DECREF(func);
return retval;
}
@@ -2295,8 +2612,9 @@ _PyObject_CallMethodId(PyObject *o, _Py_Identifier *name,
PyObject *func = NULL;
PyObject *retval = NULL;
- if (o == NULL || name == NULL)
+ if (o == NULL || name == NULL) {
return null_error();
+ }
func = _PyObject_GetAttrId(o, name);
if (func == NULL)
@@ -2305,6 +2623,7 @@ _PyObject_CallMethodId(PyObject *o, _Py_Identifier *name,
va_start(va, format);
retval = callmethod(func, format, va, 0);
va_end(va);
+ Py_DECREF(func);
return retval;
}
@@ -2316,8 +2635,9 @@ _PyObject_CallMethod_SizeT(PyObject *o, const char *name,
PyObject *func = NULL;
PyObject *retval;
- if (o == NULL || name == NULL)
+ if (o == NULL || name == NULL) {
return null_error();
+ }
func = PyObject_GetAttrString(o, name);
if (func == NULL)
@@ -2325,6 +2645,7 @@ _PyObject_CallMethod_SizeT(PyObject *o, const char *name,
va_start(va, format);
retval = callmethod(func, format, va, 1);
va_end(va);
+ Py_DECREF(func);
return retval;
}
@@ -2336,8 +2657,9 @@ _PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name,
PyObject *func = NULL;
PyObject *retval;
- if (o == NULL || name == NULL)
+ if (o == NULL || name == NULL) {
return null_error();
+ }
func = _PyObject_GetAttrId(o, name);
if (func == NULL) {
@@ -2346,39 +2668,63 @@ _PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name,
va_start(va, format);
retval = callmethod(func, format, va, 1);
va_end(va);
+ Py_DECREF(func);
return retval;
}
-static PyObject *
-objargs_mktuple(va_list va)
+static PyObject **
+objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size,
+ va_list va, Py_ssize_t *p_nargs)
{
- int i, n = 0;
+ Py_ssize_t i, n;
va_list countva;
- PyObject *result, *tmp;
+ PyObject **stack;
- Py_VA_COPY(countva, va);
+ /* Count the number of arguments */
+ va_copy(countva, va);
- while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
- ++n;
- result = PyTuple_New(n);
- if (result != NULL && n > 0) {
- for (i = 0; i < n; ++i) {
- tmp = (PyObject *)va_arg(va, PyObject *);
- PyTuple_SET_ITEM(result, i, tmp);
- Py_INCREF(tmp);
+ n = 0;
+ while (1) {
+ PyObject *arg = va_arg(countva, PyObject *);
+ if (arg == NULL) {
+ break;
}
+ n++;
}
- return result;
+ *p_nargs = n;
+
+ /* Copy arguments */
+ if (n <= small_stack_size) {
+ stack = small_stack;
+ }
+ else {
+ stack = PyMem_Malloc(n * sizeof(stack[0]));
+ if (stack == NULL) {
+ va_end(countva);
+ PyErr_NoMemory();
+ return NULL;
+ }
+ }
+
+ for (i = 0; i < n; ++i) {
+ stack[i] = va_arg(va, PyObject *);
+ }
+ va_end(countva);
+ return stack;
}
PyObject *
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
{
- PyObject *args, *tmp;
+ PyObject *small_stack[5];
+ PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
va_list vargs;
- if (callable == NULL || name == NULL)
+ if (callable == NULL || name == NULL) {
return null_error();
+ }
callable = PyObject_GetAttr(callable, name);
if (callable == NULL)
@@ -2386,28 +2732,36 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
/* count the args */
va_start(vargs, name);
- args = objargs_mktuple(vargs);
+ stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
+ vargs, &nargs);
va_end(vargs);
- if (args == NULL) {
+ if (stack == NULL) {
Py_DECREF(callable);
return NULL;
}
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+
+ result = _PyObject_FastCall(callable, stack, nargs);
Py_DECREF(callable);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
- return tmp;
+ return result;
}
PyObject *
_PyObject_CallMethodIdObjArgs(PyObject *callable,
struct _Py_Identifier *name, ...)
{
- PyObject *args, *tmp;
+ PyObject *small_stack[5];
+ PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
va_list vargs;
- if (callable == NULL || name == NULL)
+ if (callable == NULL || name == NULL) {
return null_error();
+ }
callable = _PyObject_GetAttrId(callable, name);
if (callable == NULL)
@@ -2415,38 +2769,51 @@ _PyObject_CallMethodIdObjArgs(PyObject *callable,
/* count the args */
va_start(vargs, name);
- args = objargs_mktuple(vargs);
+ stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
+ vargs, &nargs);
va_end(vargs);
- if (args == NULL) {
+ if (stack == NULL) {
Py_DECREF(callable);
return NULL;
}
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+
+ result = _PyObject_FastCall(callable, stack, nargs);
Py_DECREF(callable);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
- return tmp;
+ return result;
}
PyObject *
PyObject_CallFunctionObjArgs(PyObject *callable, ...)
{
- PyObject *args, *tmp;
+ PyObject *small_stack[5];
+ PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
va_list vargs;
- if (callable == NULL)
+ if (callable == NULL) {
return null_error();
+ }
/* count the args */
va_start(vargs, callable);
- args = objargs_mktuple(vargs);
+ stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
+ vargs, &nargs);
va_end(vargs);
- if (args == NULL)
+ if (stack == NULL) {
return NULL;
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+ }
+
+ result = _PyObject_FastCall(callable, stack, nargs);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
- return tmp;
+ return result;
}
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index 3fad6d80b5..a8d6980250 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -278,33 +278,6 @@ PyByteArray_Concat(PyObject *a, PyObject *b)
return (PyObject *)result;
}
-static PyObject *
-bytearray_format(PyByteArrayObject *self, PyObject *args)
-{
- PyObject *bytes_in, *bytes_out, *res;
- char *bytestring;
- Py_ssize_t bytesize;
-
- if (self == NULL || !PyByteArray_Check(self) || args == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
- bytestring = PyByteArray_AS_STRING(self);
- bytesize = PyByteArray_GET_SIZE(self);
- bytes_in = PyBytes_FromStringAndSize(bytestring, bytesize);
- if (bytes_in == NULL)
- return NULL;
- bytes_out = _PyBytes_Format(bytes_in, args);
- Py_DECREF(bytes_in);
- if (bytes_out == NULL)
- return NULL;
- res = PyByteArray_FromObject(bytes_out);
- Py_DECREF(bytes_out);
- if (res == NULL)
- return NULL;
- return res;
-}
-
/* Functions stuffed into the type object */
static Py_ssize_t
@@ -822,23 +795,25 @@ bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
}
/* Is it an int? */
- count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
- if (count == -1 && PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_OverflowError))
- return -1;
- PyErr_Clear();
- }
- else if (count < 0) {
- PyErr_SetString(PyExc_ValueError, "negative count");
- return -1;
- }
- else {
- if (count > 0) {
- if (PyByteArray_Resize((PyObject *)self, count))
+ if (PyIndex_Check(arg)) {
+ count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
+ if (count == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_OverflowError))
return -1;
- memset(PyByteArray_AS_STRING(self), 0, count);
+ PyErr_Clear(); /* fall through */
+ }
+ else {
+ if (count < 0) {
+ PyErr_SetString(PyExc_ValueError, "negative count");
+ return -1;
+ }
+ if (count > 0) {
+ if (PyByteArray_Resize((PyObject *)self, count))
+ return -1;
+ memset(PyByteArray_AS_STRING(self), 0, count);
+ }
+ return 0;
}
- return 0;
}
/* Use the buffer API */
@@ -1121,161 +1096,27 @@ bytearray_dealloc(PyByteArrayObject *self)
#include "stringlib/transmogrify.h"
-/* The following Py_LOCAL_INLINE and Py_LOCAL functions
-were copied from the old char* style string object. */
-
-/* helper macro to fixup start/end slice values */
-#define ADJUST_INDICES(start, end, len) \
- if (end > len) \
- end = len; \
- else if (end < 0) { \
- end += len; \
- if (end < 0) \
- end = 0; \
- } \
- if (start < 0) { \
- start += len; \
- if (start < 0) \
- start = 0; \
- }
-
-Py_LOCAL_INLINE(Py_ssize_t)
-bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir)
-{
- PyObject *subobj;
- char byte;
- Py_buffer subbuf;
- const char *sub;
- Py_ssize_t len, sub_len;
- Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
- Py_ssize_t res;
-
- if (!stringlib_parse_args_finds_byte("find/rfind/index/rindex",
- args, &subobj, &byte, &start, &end))
- return -2;
-
- if (subobj) {
- if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
- return -2;
-
- sub = subbuf.buf;
- sub_len = subbuf.len;
- }
- else {
- sub = &byte;
- sub_len = 1;
- }
- len = PyByteArray_GET_SIZE(self);
-
- ADJUST_INDICES(start, end, len);
- if (end - start < sub_len)
- res = -1;
- else if (sub_len == 1
-#ifndef HAVE_MEMRCHR
- && dir > 0
-#endif
- ) {
- unsigned char needle = *sub;
- int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH;
- res = stringlib_fastsearch_memchr_1char(
- PyByteArray_AS_STRING(self) + start, end - start,
- needle, needle, mode);
- if (res >= 0)
- res += start;
- }
- else {
- if (dir > 0)
- res = stringlib_find_slice(
- PyByteArray_AS_STRING(self), len,
- sub, sub_len, start, end);
- else
- res = stringlib_rfind_slice(
- PyByteArray_AS_STRING(self), len,
- sub, sub_len, start, end);
- }
-
- if (subobj)
- PyBuffer_Release(&subbuf);
-
- return res;
-}
-
-PyDoc_STRVAR(find__doc__,
-"B.find(sub[, start[, end]]) -> int\n\
-\n\
-Return the lowest index in B where subsection sub is found,\n\
-such that sub is contained within B[start,end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
static PyObject *
bytearray_find(PyByteArrayObject *self, PyObject *args)
{
- Py_ssize_t result = bytearray_find_internal(self, args, +1);
- if (result == -2)
- return NULL;
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_find(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
-PyDoc_STRVAR(count__doc__,
-"B.count(sub[, start[, end]]) -> int\n\
-\n\
-Return the number of non-overlapping occurrences of subsection sub in\n\
-bytes B[start:end]. Optional arguments start and end are interpreted\n\
-as in slice notation.");
-
static PyObject *
bytearray_count(PyByteArrayObject *self, PyObject *args)
{
- PyObject *sub_obj;
- const char *str = PyByteArray_AS_STRING(self), *sub;
- Py_ssize_t sub_len;
- char byte;
- Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
-
- Py_buffer vsub;
- PyObject *count_obj;
-
- if (!stringlib_parse_args_finds_byte("count", args, &sub_obj, &byte,
- &start, &end))
- return NULL;
-
- if (sub_obj) {
- if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
- return NULL;
-
- sub = vsub.buf;
- sub_len = vsub.len;
- }
- else {
- sub = &byte;
- sub_len = 1;
- }
-
- ADJUST_INDICES(start, end, PyByteArray_GET_SIZE(self));
-
- count_obj = PyLong_FromSsize_t(
- stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
- );
-
- if (sub_obj)
- PyBuffer_Release(&vsub);
-
- return count_obj;
+ return _Py_bytes_count(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
/*[clinic input]
bytearray.clear
- self: self(type="PyByteArrayObject *")
-
Remove all items from the bytearray.
[clinic start generated code]*/
static PyObject *
bytearray_clear_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=85c2fe6aede0956c input=e524fd330abcdc18]*/
+/*[clinic end generated code: output=85c2fe6aede0956c input=ed6edae9de447ac4]*/
{
if (PyByteArray_Resize((PyObject *)self, 0) < 0)
return NULL;
@@ -1285,253 +1126,72 @@ bytearray_clear_impl(PyByteArrayObject *self)
/*[clinic input]
bytearray.copy
- self: self(type="PyByteArrayObject *")
-
Return a copy of B.
[clinic start generated code]*/
static PyObject *
bytearray_copy_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=68cfbcfed484c132 input=6d5d2975aa0f33f3]*/
+/*[clinic end generated code: output=68cfbcfed484c132 input=6597b0c01bccaa9e]*/
{
return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING((PyObject *)self),
PyByteArray_GET_SIZE(self));
}
-PyDoc_STRVAR(index__doc__,
-"B.index(sub[, start[, end]]) -> int\n\
-\n\
-Like B.find() but raise ValueError when the subsection is not found.");
-
static PyObject *
bytearray_index(PyByteArrayObject *self, PyObject *args)
{
- Py_ssize_t result = bytearray_find_internal(self, args, +1);
- if (result == -2)
- return NULL;
- if (result == -1) {
- PyErr_SetString(PyExc_ValueError,
- "subsection not found");
- return NULL;
- }
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_index(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
-
-PyDoc_STRVAR(rfind__doc__,
-"B.rfind(sub[, start[, end]]) -> int\n\
-\n\
-Return the highest index in B where subsection sub is found,\n\
-such that sub is contained within B[start,end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
static PyObject *
bytearray_rfind(PyByteArrayObject *self, PyObject *args)
{
- Py_ssize_t result = bytearray_find_internal(self, args, -1);
- if (result == -2)
- return NULL;
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_rfind(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
-
-PyDoc_STRVAR(rindex__doc__,
-"B.rindex(sub[, start[, end]]) -> int\n\
-\n\
-Like B.rfind() but raise ValueError when the subsection is not found.");
-
static PyObject *
bytearray_rindex(PyByteArrayObject *self, PyObject *args)
{
- Py_ssize_t result = bytearray_find_internal(self, args, -1);
- if (result == -2)
- return NULL;
- if (result == -1) {
- PyErr_SetString(PyExc_ValueError,
- "subsection not found");
- return NULL;
- }
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_rindex(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
-
static int
bytearray_contains(PyObject *self, PyObject *arg)
{
- Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
- if (ival == -1 && PyErr_Occurred()) {
- Py_buffer varg;
- Py_ssize_t pos;
- PyErr_Clear();
- if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
- return -1;
- pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self),
- varg.buf, varg.len, 0);
- PyBuffer_Release(&varg);
- return pos >= 0;
- }
- if (ival < 0 || ival >= 256) {
- PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
- return -1;
- }
-
- return memchr(PyByteArray_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL;
+ return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg);
}
-
-/* Matches the end (direction >= 0) or start (direction < 0) of self
- * against substr, using the start and end arguments. Returns
- * -1 on error, 0 if not found and 1 if found.
- */
-Py_LOCAL(int)
-_bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start,
- Py_ssize_t end, int direction)
-{
- Py_ssize_t len = PyByteArray_GET_SIZE(self);
- const char* str;
- Py_buffer vsubstr;
- int rv = 0;
-
- str = PyByteArray_AS_STRING(self);
-
- if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0)
- return -1;
-
- ADJUST_INDICES(start, end, len);
-
- if (direction < 0) {
- /* startswith */
- if (start+vsubstr.len > len) {
- goto done;
- }
- } else {
- /* endswith */
- if (end-start < vsubstr.len || start > len) {
- goto done;
- }
-
- if (end-vsubstr.len > start)
- start = end - vsubstr.len;
- }
- if (end-start >= vsubstr.len)
- rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len);
-
-done:
- PyBuffer_Release(&vsubstr);
- return rv;
-}
-
-
-PyDoc_STRVAR(startswith__doc__,
-"B.startswith(prefix[, start[, end]]) -> bool\n\
-\n\
-Return True if B starts with the specified prefix, False otherwise.\n\
-With optional start, test B beginning at that position.\n\
-With optional end, stop comparing B at that position.\n\
-prefix can also be a tuple of bytes to try.");
-
static PyObject *
bytearray_startswith(PyByteArrayObject *self, PyObject *args)
{
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *subobj;
- int result;
-
- if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- result = _bytearray_tailmatch(self,
- PyTuple_GET_ITEM(subobj, i),
- start, end, -1);
- if (result == -1)
- return NULL;
- else if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- result = _bytearray_tailmatch(self, subobj, start, end, -1);
- if (result == -1) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError, "startswith first arg must be bytes "
- "or a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
- return NULL;
- }
- else
- return PyBool_FromLong(result);
+ return _Py_bytes_startswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
-PyDoc_STRVAR(endswith__doc__,
-"B.endswith(suffix[, start[, end]]) -> bool\n\
-\n\
-Return True if B ends with the specified suffix, False otherwise.\n\
-With optional start, test B beginning at that position.\n\
-With optional end, stop comparing B at that position.\n\
-suffix can also be a tuple of bytes to try.");
-
static PyObject *
bytearray_endswith(PyByteArrayObject *self, PyObject *args)
{
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *subobj;
- int result;
-
- if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- result = _bytearray_tailmatch(self,
- PyTuple_GET_ITEM(subobj, i),
- start, end, +1);
- if (result == -1)
- return NULL;
- else if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- result = _bytearray_tailmatch(self, subobj, start, end, +1);
- if (result == -1) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError, "endswith first arg must be bytes or "
- "a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
- return NULL;
- }
- else
- return PyBool_FromLong(result);
+ return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
}
/*[clinic input]
bytearray.translate
- self: self(type="PyByteArrayObject *")
table: object
Translation table, which must be a bytes object of length 256.
- [
- deletechars: object
- ]
/
+ delete as deletechars: object(c_default="NULL") = b''
Return a copy with each character mapped by the given translation table.
-All characters occurring in the optional argument deletechars are removed.
+All characters occurring in the optional argument delete are removed.
The remaining characters are mapped through the given translation table.
[clinic start generated code]*/
static PyObject *
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
- int group_right_1, PyObject *deletechars)
-/*[clinic end generated code: output=2bebc86a9a1ff083 input=b749ad85f4860824]*/
+ PyObject *deletechars)
+/*[clinic end generated code: output=b6a8f01c2a74e446 input=cfff956d4d127a9b]*/
{
char *input, *output;
const char *table_chars;
@@ -1574,7 +1234,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
result = PyByteArray_FromStringAndSize((char *)NULL, inlen);
if (result == NULL)
goto done;
- output_start = output = PyByteArray_AsString(result);
+ output_start = output = PyByteArray_AS_STRING(result);
input = PyByteArray_AS_STRING(input_obj);
if (vdel.len == 0 && table_chars != NULL) {
@@ -1600,8 +1260,7 @@ bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
for (i = inlen; --i >= 0; ) {
c = Py_CHARMASK(*input++);
if (trans_table[c] != -1)
- if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)
- continue;
+ *output++ = (char)trans_table[c];
}
/* Fix the size of the resulting string */
if (inlen > 0)
@@ -1644,493 +1303,6 @@ bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)
}
-/* find and count characters and substrings */
-
-#define findchar(target, target_len, c) \
- ((char *)memchr((const void *)(target), c, target_len))
-
-
-/* Bytes ops must return a string, create a copy */
-Py_LOCAL(PyByteArrayObject *)
-return_self(PyByteArrayObject *self)
-{
- /* always return a new bytearray */
- return (PyByteArrayObject *)PyByteArray_FromStringAndSize(
- PyByteArray_AS_STRING(self),
- PyByteArray_GET_SIZE(self));
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount)
-{
- Py_ssize_t count=0;
- const char *start=target;
- const char *end=target+target_len;
-
- while ( (start=findchar(start, end-start, c)) != NULL ) {
- count++;
- if (count >= maxcount)
- break;
- start += 1;
- }
- return count;
-}
-
-
-/* Algorithms for different cases of string replacement */
-
-/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
-Py_LOCAL(PyByteArrayObject *)
-replace_interleave(PyByteArrayObject *self,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, i;
- PyByteArrayObject *result;
-
- self_len = PyByteArray_GET_SIZE(self);
-
- /* 1 at the end plus 1 after every character;
- count = min(maxcount, self_len + 1) */
- if (maxcount <= self_len)
- count = maxcount;
- else
- /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */
- count = self_len + 1;
-
- /* Check for overflow */
- /* result_len = count * to_len + self_len; */
- assert(count > 0);
- if (to_len > (PY_SSIZE_T_MAX - self_len) / count) {
- PyErr_SetString(PyExc_OverflowError,
- "replace string is too long");
- return NULL;
- }
- result_len = count * to_len + self_len;
-
- if (! (result = (PyByteArrayObject *)
- PyByteArray_FromStringAndSize(NULL, result_len)) )
- return NULL;
-
- self_s = PyByteArray_AS_STRING(self);
- result_s = PyByteArray_AS_STRING(result);
-
- /* TODO: special case single character, which doesn't need memcpy */
-
- /* Lay the first one down (guaranteed this will occur) */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- count -= 1;
-
- for (i=0; i<count; i++) {
- *result_s++ = *self_s++;
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- }
-
- /* Copy the rest of the original string */
- Py_MEMCPY(result_s, self_s, self_len-i);
-
- return result;
-}
-
-/* Special case for deleting a single character */
-/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
-Py_LOCAL(PyByteArrayObject *)
-replace_delete_single_character(PyByteArrayObject *self,
- char from_c, Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count;
- PyByteArrayObject *result;
-
- self_len = PyByteArray_GET_SIZE(self);
- self_s = PyByteArray_AS_STRING(self);
-
- count = countchar(self_s, self_len, from_c, maxcount);
- if (count == 0) {
- return return_self(self);
- }
-
- result_len = self_len - count; /* from_len == 1 */
- assert(result_len>=0);
-
- if ( (result = (PyByteArrayObject *)
- PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyByteArray_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- start = next+1;
- }
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
-
-Py_LOCAL(PyByteArrayObject *)
-replace_delete_substring(PyByteArrayObject *self,
- const char *from_s, Py_ssize_t from_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset;
- PyByteArrayObject *result;
-
- self_len = PyByteArray_GET_SIZE(self);
- self_s = PyByteArray_AS_STRING(self);
-
- count = stringlib_count(self_s, self_len,
- from_s, from_len,
- maxcount);
-
- if (count == 0) {
- /* no matches */
- return return_self(self);
- }
-
- result_len = self_len - (count * from_len);
- assert (result_len>=0);
-
- if ( (result = (PyByteArrayObject *)
- PyByteArray_FromStringAndSize(NULL, result_len)) == NULL )
- return NULL;
-
- result_s = PyByteArray_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- offset = stringlib_find(start, end-start,
- from_s, from_len,
- 0);
- if (offset == -1)
- break;
- next = start + offset;
-
- Py_MEMCPY(result_s, start, next-start);
-
- result_s += (next-start);
- start = next+from_len;
- }
- Py_MEMCPY(result_s, start, end-start);
- return result;
-}
-
-/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
-Py_LOCAL(PyByteArrayObject *)
-replace_single_character_in_place(PyByteArrayObject *self,
- char from_c, char to_c,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s, *start, *end, *next;
- Py_ssize_t self_len;
- PyByteArrayObject *result;
-
- /* The result string will be the same size */
- self_s = PyByteArray_AS_STRING(self);
- self_len = PyByteArray_GET_SIZE(self);
-
- next = findchar(self_s, self_len, from_c);
-
- if (next == NULL) {
- /* No matches; return the original bytes */
- return return_self(self);
- }
-
- /* Need to make a new bytes */
- result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, self_len);
- if (result == NULL)
- return NULL;
- result_s = PyByteArray_AS_STRING(result);
- Py_MEMCPY(result_s, self_s, self_len);
-
- /* change everything in-place, starting with this one */
- start = result_s + (next-self_s);
- *start = to_c;
- start++;
- end = result_s + self_len;
-
- while (--maxcount > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
- *next = to_c;
- start = next+1;
- }
-
- return result;
-}
-
-/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyByteArrayObject *)
-replace_substring_in_place(PyByteArrayObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *result_s, *start, *end;
- char *self_s;
- Py_ssize_t self_len, offset;
- PyByteArrayObject *result;
-
- /* The result bytes will be the same size */
-
- self_s = PyByteArray_AS_STRING(self);
- self_len = PyByteArray_GET_SIZE(self);
-
- offset = stringlib_find(self_s, self_len,
- from_s, from_len,
- 0);
- if (offset == -1) {
- /* No matches; return the original bytes */
- return return_self(self);
- }
-
- /* Need to make a new bytes */
- result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, self_len);
- if (result == NULL)
- return NULL;
- result_s = PyByteArray_AS_STRING(result);
- Py_MEMCPY(result_s, self_s, self_len);
-
- /* change everything in-place, starting with this one */
- start = result_s + offset;
- Py_MEMCPY(start, to_s, from_len);
- start += from_len;
- end = result_s + self_len;
-
- while ( --maxcount > 0) {
- offset = stringlib_find(start, end-start,
- from_s, from_len,
- 0);
- if (offset==-1)
- break;
- Py_MEMCPY(start+offset, to_s, from_len);
- start += offset+from_len;
- }
-
- return result;
-}
-
-/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyByteArrayObject *)
-replace_single_character(PyByteArrayObject *self,
- char from_c,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count;
- PyByteArrayObject *result;
-
- self_s = PyByteArray_AS_STRING(self);
- self_len = PyByteArray_GET_SIZE(self);
-
- count = countchar(self_s, self_len, from_c, maxcount);
- if (count == 0) {
- /* no matches, return unchanged */
- return return_self(self);
- }
-
- /* use the difference between current and new, hence the "-1" */
- /* result_len = self_len + count * (to_len-1) */
- assert(count > 0);
- if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) {
- PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
- return NULL;
- }
- result_len = self_len + count * (to_len - 1);
-
- if ( (result = (PyByteArrayObject *)
- PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyByteArray_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
-
- if (next == start) {
- /* replace with the 'to' */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start += 1;
- } else {
- /* copy the unchanged old then the 'to' */
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start = next+1;
- }
- }
- /* Copy the remainder of the remaining bytes */
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyByteArrayObject *)
-replace_substring(PyByteArrayObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset;
- PyByteArrayObject *result;
-
- self_s = PyByteArray_AS_STRING(self);
- self_len = PyByteArray_GET_SIZE(self);
-
- count = stringlib_count(self_s, self_len,
- from_s, from_len,
- maxcount);
-
- if (count == 0) {
- /* no matches, return unchanged */
- return return_self(self);
- }
-
- /* Check for overflow */
- /* result_len = self_len + count * (to_len-from_len) */
- assert(count > 0);
- if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) {
- PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
- return NULL;
- }
- result_len = self_len + count * (to_len - from_len);
-
- if ( (result = (PyByteArrayObject *)
- PyByteArray_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyByteArray_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- offset = stringlib_find(start, end-start,
- from_s, from_len,
- 0);
- if (offset == -1)
- break;
- next = start+offset;
- if (next == start) {
- /* replace with the 'to' */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start += from_len;
- } else {
- /* copy the unchanged old then the 'to' */
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start = next+from_len;
- }
- }
- /* Copy the remainder of the remaining bytes */
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-
-Py_LOCAL(PyByteArrayObject *)
-replace(PyByteArrayObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- if (maxcount < 0) {
- maxcount = PY_SSIZE_T_MAX;
- } else if (maxcount == 0 || PyByteArray_GET_SIZE(self) == 0) {
- /* nothing to do; return the original bytes */
- return return_self(self);
- }
-
- if (maxcount == 0 ||
- (from_len == 0 && to_len == 0)) {
- /* nothing to do; return the original bytes */
- return return_self(self);
- }
-
- /* Handle zero-length special cases */
-
- if (from_len == 0) {
- /* insert the 'to' bytes everywhere. */
- /* >>> "Python".replace("", ".") */
- /* '.P.y.t.h.o.n.' */
- return replace_interleave(self, to_s, to_len, maxcount);
- }
-
- /* Except for "".replace("", "A") == "A" there is no way beyond this */
- /* point for an empty self bytes to generate a non-empty bytes */
- /* Special case so the remaining code always gets a non-empty bytes */
- if (PyByteArray_GET_SIZE(self) == 0) {
- return return_self(self);
- }
-
- if (to_len == 0) {
- /* delete all occurrences of 'from' bytes */
- if (from_len == 1) {
- return replace_delete_single_character(
- self, from_s[0], maxcount);
- } else {
- return replace_delete_substring(self, from_s, from_len, maxcount);
- }
- }
-
- /* Handle special case where both bytes have the same length */
-
- if (from_len == to_len) {
- if (from_len == 1) {
- return replace_single_character_in_place(
- self,
- from_s[0],
- to_s[0],
- maxcount);
- } else {
- return replace_substring_in_place(
- self, from_s, from_len, to_s, to_len, maxcount);
- }
- }
-
- /* Otherwise use the more generic algorithms */
- if (from_len == 1) {
- return replace_single_character(self, from_s[0],
- to_s, to_len, maxcount);
- } else {
- /* len('from')>=2, len('to')>=1 */
- return replace_substring(self, from_s, from_len, to_s, to_len, maxcount);
- }
-}
-
-
/*[clinic input]
bytearray.replace
@@ -2152,9 +1324,9 @@ bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
Py_buffer *new, Py_ssize_t count)
/*[clinic end generated code: output=d39884c4dc59412a input=aa379d988637c7fb]*/
{
- return (PyObject *)replace((PyByteArrayObject *) self,
- old->buf, old->len,
- new->buf, new->len, count);
+ return stringlib_replace((PyObject *)self,
+ (const char *)old->buf, old->len,
+ (const char *)new->buf, new->len, count);
}
/*[clinic input]
@@ -2202,7 +1374,6 @@ bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
/*[clinic input]
bytearray.partition
- self: self(type="PyByteArrayObject *")
sep: object
/
@@ -2218,7 +1389,7 @@ bytearray object and two empty bytearray objects.
static PyObject *
bytearray_partition(PyByteArrayObject *self, PyObject *sep)
-/*[clinic end generated code: output=45d2525ddd35f957 input=7d7fe37b1696d506]*/
+/*[clinic end generated code: output=45d2525ddd35f957 input=86f89223892b70b5]*/
{
PyObject *bytesep, *result;
@@ -2240,7 +1411,6 @@ bytearray_partition(PyByteArrayObject *self, PyObject *sep)
/*[clinic input]
bytearray.rpartition
- self: self(type="PyByteArrayObject *")
sep: object
/
@@ -2256,7 +1426,7 @@ objects and the original bytearray object.
static PyObject *
bytearray_rpartition(PyByteArrayObject *self, PyObject *sep)
-/*[clinic end generated code: output=440de3c9426115e8 input=9b8cd540c1b75853]*/
+/*[clinic end generated code: output=440de3c9426115e8 input=5f4094f2de87c8f3]*/
{
PyObject *bytesep, *result;
@@ -2314,14 +1484,12 @@ bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
/*[clinic input]
bytearray.reverse
- self: self(type="PyByteArrayObject *")
-
Reverse the order of the values in B in place.
[clinic start generated code]*/
static PyObject *
bytearray_reverse_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=9f7616f29ab309d3 input=7933a499b8597bd1]*/
+/*[clinic end generated code: output=9f7616f29ab309d3 input=543356319fc78557]*/
{
char swap, *head, *tail;
Py_ssize_t i, j, n = Py_SIZE(self);
@@ -2350,7 +1518,6 @@ class bytesvalue_converter(CConverter):
/*[clinic input]
bytearray.insert
- self: self(type="PyByteArrayObject *")
index: Py_ssize_t
The index where the value is to be inserted.
item: bytesvalue
@@ -2362,7 +1529,7 @@ Insert a single item into the bytearray before the given index.
static PyObject *
bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
-/*[clinic end generated code: output=76c775a70e7b07b7 input=833766836ba30e1e]*/
+/*[clinic end generated code: output=76c775a70e7b07b7 input=b2b5d07e9de6c070]*/
{
Py_ssize_t n = Py_SIZE(self);
char *buf;
@@ -2392,7 +1559,6 @@ bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item)
/*[clinic input]
bytearray.append
- self: self(type="PyByteArrayObject *")
item: bytesvalue
The item to be appended.
/
@@ -2402,7 +1568,7 @@ Append a single item to the end of the bytearray.
static PyObject *
bytearray_append_impl(PyByteArrayObject *self, int item)
-/*[clinic end generated code: output=a154e19ed1886cb6 input=ae56ea87380407cc]*/
+/*[clinic end generated code: output=a154e19ed1886cb6 input=20d6bec3d1340593]*/
{
Py_ssize_t n = Py_SIZE(self);
@@ -2422,7 +1588,6 @@ bytearray_append_impl(PyByteArrayObject *self, int item)
/*[clinic input]
bytearray.extend
- self: self(type="PyByteArrayObject *")
iterable_of_ints: object
The iterable of items to append.
/
@@ -2432,7 +1597,7 @@ Append all the items from the iterator or sequence to the end of the bytearray.
static PyObject *
bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
-/*[clinic end generated code: output=98155dbe249170b1 input=ce83a5d75b70d850]*/
+/*[clinic end generated code: output=98155dbe249170b1 input=c617b3a93249ba28]*/
{
PyObject *it, *item, *bytearray_obj;
Py_ssize_t buf_size = 0, len = 0;
@@ -2517,7 +1682,6 @@ bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
/*[clinic input]
bytearray.pop
- self: self(type="PyByteArrayObject *")
index: Py_ssize_t = -1
The index from where to remove the item.
-1 (the default value) means remove the last item.
@@ -2530,7 +1694,7 @@ If no index argument is given, will pop the last item.
static PyObject *
bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index)
-/*[clinic end generated code: output=e0ccd401f8021da8 input=0797e6c0ca9d5a85]*/
+/*[clinic end generated code: output=e0ccd401f8021da8 input=3591df2d06c0d237]*/
{
int value;
Py_ssize_t n = Py_SIZE(self);
@@ -2562,7 +1726,6 @@ bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index)
/*[clinic input]
bytearray.remove
- self: self(type="PyByteArrayObject *")
value: bytesvalue
The value to remove.
/
@@ -2572,20 +1735,20 @@ Remove the first occurrence of a value in the bytearray.
static PyObject *
bytearray_remove_impl(PyByteArrayObject *self, int value)
-/*[clinic end generated code: output=d659e37866709c13 input=47560b11fd856c24]*/
+/*[clinic end generated code: output=d659e37866709c13 input=121831240cd51ddf]*/
{
- Py_ssize_t n = Py_SIZE(self);
+ Py_ssize_t where, n = Py_SIZE(self);
char *buf = PyByteArray_AS_STRING(self);
- char *where = memchr(buf, value, n);
- if (!where) {
+ where = stringlib_find_char(buf, n, value);
+ if (where < 0) {
PyErr_SetString(PyExc_ValueError, "value not found in bytearray");
return NULL;
}
if (!_canresize(self))
return NULL;
- memmove(where, where + 1, buf + n - where);
+ memmove(buf + where, buf + where + 1, n - where);
if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
return NULL;
@@ -2595,8 +1758,8 @@ bytearray_remove_impl(PyByteArrayObject *self, int value)
/* XXX These two helpers could be optimized if argsize == 1 */
static Py_ssize_t
-lstrip_helper(char *myptr, Py_ssize_t mysize,
- void *argptr, Py_ssize_t argsize)
+lstrip_helper(const char *myptr, Py_ssize_t mysize,
+ const void *argptr, Py_ssize_t argsize)
{
Py_ssize_t i = 0;
while (i < mysize && memchr(argptr, (unsigned char) myptr[i], argsize))
@@ -2605,8 +1768,8 @@ lstrip_helper(char *myptr, Py_ssize_t mysize,
}
static Py_ssize_t
-rstrip_helper(char *myptr, Py_ssize_t mysize,
- void *argptr, Py_ssize_t argsize)
+rstrip_helper(const char *myptr, Py_ssize_t mysize,
+ const void *argptr, Py_ssize_t argsize)
{
Py_ssize_t i = mysize - 1;
while (i >= 0 && memchr(argptr, (unsigned char) myptr[i], argsize))
@@ -2807,27 +1970,10 @@ bytearray_splitlines_impl(PyByteArrayObject *self, int keepends)
);
}
-static int
-hex_digit_to_int(Py_UCS4 c)
-{
- if (c >= 128)
- return -1;
- if (Py_ISDIGIT(c))
- return c - '0';
- else {
- if (Py_ISUPPER(c))
- c = Py_TOLOWER(c);
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- }
- return -1;
-}
-
/*[clinic input]
@classmethod
bytearray.fromhex
- cls: self(type="PyObject*")
string: unicode
/
@@ -2838,51 +1984,15 @@ Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef')
[clinic start generated code]*/
static PyObject *
-bytearray_fromhex_impl(PyObject*cls, PyObject *string)
-/*[clinic end generated code: output=df3da60129b3700c input=907bbd2d34d9367a]*/
+bytearray_fromhex_impl(PyTypeObject *type, PyObject *string)
+/*[clinic end generated code: output=8f0f0b6d30fb3ba0 input=f033a16d1fb21f48]*/
{
- PyObject *newbytes;
- char *buf;
- Py_ssize_t hexlen, byteslen, i, j;
- int top, bot;
- void *data;
- unsigned int kind;
-
- assert(PyUnicode_Check(string));
- if (PyUnicode_READY(string))
- return NULL;
- kind = PyUnicode_KIND(string);
- data = PyUnicode_DATA(string);
- hexlen = PyUnicode_GET_LENGTH(string);
-
- byteslen = hexlen/2; /* This overestimates if there are spaces */
- newbytes = PyByteArray_FromStringAndSize(NULL, byteslen);
- if (!newbytes)
- return NULL;
- buf = PyByteArray_AS_STRING(newbytes);
- for (i = j = 0; i < hexlen; i += 2) {
- /* skip over spaces in the input */
- while (PyUnicode_READ(kind, data, i) == ' ')
- i++;
- if (i >= hexlen)
- break;
- top = hex_digit_to_int(PyUnicode_READ(kind, data, i));
- bot = hex_digit_to_int(PyUnicode_READ(kind, data, i+1));
- if (top == -1 || bot == -1) {
- PyErr_Format(PyExc_ValueError,
- "non-hexadecimal number found in "
- "fromhex() arg at position %zd", i);
- goto error;
- }
- buf[j++] = (top << 4) + bot;
+ PyObject *result = _PyBytes_FromHex(string, type == &PyByteArray_Type);
+ if (type != &PyByteArray_Type && result != NULL) {
+ Py_SETREF(result, PyObject_CallFunctionObjArgs((PyObject *)type,
+ result, NULL));
}
- if (PyByteArray_Resize(newbytes, j) < 0)
- goto error;
- return newbytes;
-
- error:
- Py_DECREF(newbytes);
- return NULL;
+ return result;
}
PyDoc_STRVAR(hex__doc__,
@@ -2937,14 +2047,12 @@ _common_reduce(PyByteArrayObject *self, int proto)
/*[clinic input]
bytearray.__reduce__ as bytearray_reduce
- self: self(type="PyByteArrayObject *")
-
Return state information for pickling.
[clinic start generated code]*/
static PyObject *
bytearray_reduce_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=52bf304086464cab input=fbb07de4d102a03a]*/
+/*[clinic end generated code: output=52bf304086464cab input=44b5737ada62dd3f]*/
{
return _common_reduce(self, 2);
}
@@ -2952,7 +2060,6 @@ bytearray_reduce_impl(PyByteArrayObject *self)
/*[clinic input]
bytearray.__reduce_ex__ as bytearray_reduce_ex
- self: self(type="PyByteArrayObject *")
proto: int = 0
/
@@ -2961,7 +2068,7 @@ Return state information for pickling.
static PyObject *
bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto)
-/*[clinic end generated code: output=52eac33377197520 input=0e091a42ca6dbd91]*/
+/*[clinic end generated code: output=52eac33377197520 input=f129bc1a1aa151ee]*/
{
return _common_reduce(self, proto);
}
@@ -2969,14 +2076,12 @@ bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto)
/*[clinic input]
bytearray.__sizeof__ as bytearray_sizeof
- self: self(type="PyByteArrayObject *")
-
Returns the size of the bytearray object in memory, in bytes.
[clinic start generated code]*/
static PyObject *
bytearray_sizeof_impl(PyByteArrayObject *self)
-/*[clinic end generated code: output=738abdd17951c427 input=6b23d305362b462b]*/
+/*[clinic end generated code: output=738abdd17951c427 input=e27320fd98a4bc5a]*/
{
Py_ssize_t res;
@@ -3017,19 +2122,22 @@ bytearray_methods[] = {
BYTEARRAY_APPEND_METHODDEF
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
_Py_capitalize__doc__},
- {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
+ {"center", (PyCFunction)stringlib_center, METH_VARARGS, _Py_center__doc__},
BYTEARRAY_CLEAR_METHODDEF
BYTEARRAY_COPY_METHODDEF
- {"count", (PyCFunction)bytearray_count, METH_VARARGS, count__doc__},
+ {"count", (PyCFunction)bytearray_count, METH_VARARGS,
+ _Py_count__doc__},
BYTEARRAY_DECODE_METHODDEF
- {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, endswith__doc__},
+ {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS,
+ _Py_endswith__doc__},
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
- expandtabs__doc__},
+ _Py_expandtabs__doc__},
BYTEARRAY_EXTEND_METHODDEF
- {"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__},
+ {"find", (PyCFunction)bytearray_find, METH_VARARGS,
+ _Py_find__doc__},
BYTEARRAY_FROMHEX_METHODDEF
{"hex", (PyCFunction)bytearray_hex, METH_NOARGS, hex__doc__},
- {"index", (PyCFunction)bytearray_index, METH_VARARGS, index__doc__},
+ {"index", (PyCFunction)bytearray_index, METH_VARARGS, _Py_index__doc__},
BYTEARRAY_INSERT_METHODDEF
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
_Py_isalnum__doc__},
@@ -3046,7 +2154,7 @@ bytearray_methods[] = {
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
_Py_isupper__doc__},
BYTEARRAY_JOIN_METHODDEF
- {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
+ {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, _Py_ljust__doc__},
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
BYTEARRAY_LSTRIP_METHODDEF
BYTEARRAY_MAKETRANS_METHODDEF
@@ -3055,23 +2163,23 @@ bytearray_methods[] = {
BYTEARRAY_REMOVE_METHODDEF
BYTEARRAY_REPLACE_METHODDEF
BYTEARRAY_REVERSE_METHODDEF
- {"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, rfind__doc__},
- {"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, rindex__doc__},
- {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
+ {"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
+ {"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
+ {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
BYTEARRAY_RPARTITION_METHODDEF
BYTEARRAY_RSPLIT_METHODDEF
BYTEARRAY_RSTRIP_METHODDEF
BYTEARRAY_SPLIT_METHODDEF
BYTEARRAY_SPLITLINES_METHODDEF
{"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS ,
- startswith__doc__},
+ _Py_startswith__doc__},
BYTEARRAY_STRIP_METHODDEF
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
BYTEARRAY_TRANSLATE_METHODDEF
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
- {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
+ {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, _Py_zfill__doc__},
{NULL}
};
@@ -3080,7 +2188,7 @@ bytearray_mod(PyObject *v, PyObject *w)
{
if (!PyByteArray_Check(v))
Py_RETURN_NOTIMPLEMENTED;
- return bytearray_format((PyByteArrayObject *)v, w);
+ return _PyBytes_FormatEx(PyByteArray_AS_STRING(v), PyByteArray_GET_SIZE(v), w, 1);
}
static PyNumberMethods bytearray_as_number = {
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index a29991584a..d5c4fe6346 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -1,3 +1,4 @@
+#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "bytes_methods.h"
@@ -277,7 +278,7 @@ Return a titlecased version of B, i.e. ASCII words start with uppercase\n\
characters, all remaining cased characters have lowercase.");
void
-_Py_bytes_title(char *result, char *s, Py_ssize_t len)
+_Py_bytes_title(char *result, const char *s, Py_ssize_t len)
{
Py_ssize_t i;
int previous_is_cased = 0;
@@ -306,7 +307,7 @@ Return a copy of B with only its first character capitalized (ASCII)\n\
and the rest lower-cased.");
void
-_Py_bytes_capitalize(char *result, char *s, Py_ssize_t len)
+_Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len)
{
Py_ssize_t i;
@@ -336,7 +337,7 @@ Return a copy of B with uppercase ASCII characters converted\n\
to lowercase ASCII and vice versa.");
void
-_Py_bytes_swapcase(char *result, char *s, Py_ssize_t len)
+_Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len)
{
Py_ssize_t i;
@@ -387,3 +388,427 @@ _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
return res;
}
+
+#define FASTSEARCH fastsearch
+#define STRINGLIB(F) stringlib_##F
+#define STRINGLIB_CHAR char
+#define STRINGLIB_SIZEOF_CHAR 1
+
+#include "stringlib/fastsearch.h"
+#include "stringlib/count.h"
+#include "stringlib/find.h"
+
+/*
+Wraps stringlib_parse_args_finds() and additionally checks whether the
+first argument is an integer in range(0, 256).
+
+If this is the case, writes the integer value to the byte parameter
+and sets subobj to NULL. Otherwise, sets the first argument to subobj
+and doesn't touch byte. The other parameters are similar to those of
+stringlib_parse_args_finds().
+*/
+
+Py_LOCAL_INLINE(int)
+parse_args_finds_byte(const char *function_name, PyObject *args,
+ PyObject **subobj, char *byte,
+ Py_ssize_t *start, Py_ssize_t *end)
+{
+ PyObject *tmp_subobj;
+ Py_ssize_t ival;
+ PyObject *err;
+
+ if(!stringlib_parse_args_finds(function_name, args, &tmp_subobj,
+ start, end))
+ return 0;
+
+ if (!PyNumber_Check(tmp_subobj)) {
+ *subobj = tmp_subobj;
+ return 1;
+ }
+
+ ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
+ if (ival == -1) {
+ err = PyErr_Occurred();
+ if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
+ PyErr_Clear();
+ *subobj = tmp_subobj;
+ return 1;
+ }
+ }
+
+ if (ival < 0 || ival > 255) {
+ PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
+ return 0;
+ }
+
+ *subobj = NULL;
+ *byte = (char)ival;
+ return 1;
+}
+
+/* helper macro to fixup start/end slice values */
+#define ADJUST_INDICES(start, end, len) \
+ if (end > len) \
+ end = len; \
+ else if (end < 0) { \
+ end += len; \
+ if (end < 0) \
+ end = 0; \
+ } \
+ if (start < 0) { \
+ start += len; \
+ if (start < 0) \
+ start = 0; \
+ }
+
+Py_LOCAL_INLINE(Py_ssize_t)
+find_internal(const char *str, Py_ssize_t len,
+ const char *function_name, PyObject *args, int dir)
+{
+ PyObject *subobj;
+ char byte;
+ Py_buffer subbuf;
+ const char *sub;
+ Py_ssize_t sub_len;
+ Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
+ Py_ssize_t res;
+
+ if (!parse_args_finds_byte(function_name, args,
+ &subobj, &byte, &start, &end))
+ return -2;
+
+ if (subobj) {
+ if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
+ return -2;
+
+ sub = subbuf.buf;
+ sub_len = subbuf.len;
+ }
+ else {
+ sub = &byte;
+ sub_len = 1;
+ }
+
+ ADJUST_INDICES(start, end, len);
+ if (end - start < sub_len)
+ res = -1;
+ else if (sub_len == 1) {
+ if (dir > 0)
+ res = stringlib_find_char(
+ str + start, end - start,
+ *sub);
+ else
+ res = stringlib_rfind_char(
+ str + start, end - start,
+ *sub);
+ if (res >= 0)
+ res += start;
+ }
+ else {
+ if (dir > 0)
+ res = stringlib_find_slice(
+ str, len,
+ sub, sub_len, start, end);
+ else
+ res = stringlib_rfind_slice(
+ str, len,
+ sub, sub_len, start, end);
+ }
+
+ if (subobj)
+ PyBuffer_Release(&subbuf);
+
+ return res;
+}
+
+PyDoc_STRVAR_shared(_Py_find__doc__,
+"B.find(sub[, start[, end]]) -> int\n\
+\n\
+Return the lowest index in B where subsection sub is found,\n\
+such that sub is contained within B[start,end]. Optional\n\
+arguments start and end are interpreted as in slice notation.\n\
+\n\
+Return -1 on failure.");
+
+PyObject *
+_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args)
+{
+ Py_ssize_t result = find_internal(str, len, "find", args, +1);
+ if (result == -2)
+ return NULL;
+ return PyLong_FromSsize_t(result);
+}
+
+PyDoc_STRVAR_shared(_Py_index__doc__,
+"B.index(sub[, start[, end]]) -> int\n\
+\n\
+Like B.find() but raise ValueError when the subsection is not found.");
+
+PyObject *
+_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args)
+{
+ Py_ssize_t result = find_internal(str, len, "index", args, +1);
+ if (result == -2)
+ return NULL;
+ if (result == -1) {
+ PyErr_SetString(PyExc_ValueError,
+ "subsection not found");
+ return NULL;
+ }
+ return PyLong_FromSsize_t(result);
+}
+
+PyDoc_STRVAR_shared(_Py_rfind__doc__,
+"B.rfind(sub[, start[, end]]) -> int\n\
+\n\
+Return the highest index in B where subsection sub is found,\n\
+such that sub is contained within B[start,end]. Optional\n\
+arguments start and end are interpreted as in slice notation.\n\
+\n\
+Return -1 on failure.");
+
+PyObject *
+_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args)
+{
+ Py_ssize_t result = find_internal(str, len, "rfind", args, -1);
+ if (result == -2)
+ return NULL;
+ return PyLong_FromSsize_t(result);
+}
+
+PyDoc_STRVAR_shared(_Py_rindex__doc__,
+"B.rindex(sub[, start[, end]]) -> int\n\
+\n\
+Like B.rfind() but raise ValueError when the subsection is not found.");
+
+PyObject *
+_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args)
+{
+ Py_ssize_t result = find_internal(str, len, "rindex", args, -1);
+ if (result == -2)
+ return NULL;
+ if (result == -1) {
+ PyErr_SetString(PyExc_ValueError,
+ "subsection not found");
+ return NULL;
+ }
+ return PyLong_FromSsize_t(result);
+}
+
+PyDoc_STRVAR_shared(_Py_count__doc__,
+"B.count(sub[, start[, end]]) -> int\n\
+\n\
+Return the number of non-overlapping occurrences of subsection sub in\n\
+bytes B[start:end]. Optional arguments start and end are interpreted\n\
+as in slice notation.");
+
+PyObject *
+_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args)
+{
+ PyObject *sub_obj;
+ const char *sub;
+ Py_ssize_t sub_len;
+ char byte;
+ Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
+
+ Py_buffer vsub;
+ PyObject *count_obj;
+
+ if (!parse_args_finds_byte("count", args,
+ &sub_obj, &byte, &start, &end))
+ return NULL;
+
+ if (sub_obj) {
+ if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
+ return NULL;
+
+ sub = vsub.buf;
+ sub_len = vsub.len;
+ }
+ else {
+ sub = &byte;
+ sub_len = 1;
+ }
+
+ ADJUST_INDICES(start, end, len);
+
+ count_obj = PyLong_FromSsize_t(
+ stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
+ );
+
+ if (sub_obj)
+ PyBuffer_Release(&vsub);
+
+ return count_obj;
+}
+
+int
+_Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg)
+{
+ Py_ssize_t ival = PyNumber_AsSsize_t(arg, NULL);
+ if (ival == -1 && PyErr_Occurred()) {
+ Py_buffer varg;
+ Py_ssize_t pos;
+ PyErr_Clear();
+ if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
+ return -1;
+ pos = stringlib_find(str, len,
+ varg.buf, varg.len, 0);
+ PyBuffer_Release(&varg);
+ return pos >= 0;
+ }
+ if (ival < 0 || ival >= 256) {
+ PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
+ return -1;
+ }
+
+ return memchr(str, (int) ival, len) != NULL;
+}
+
+
+/* Matches the end (direction >= 0) or start (direction < 0) of the buffer
+ * against substr, using the start and end arguments. Returns
+ * -1 on error, 0 if not found and 1 if found.
+ */
+static int
+tailmatch(const char *str, Py_ssize_t len, PyObject *substr,
+ Py_ssize_t start, Py_ssize_t end, int direction)
+{
+ Py_buffer sub_view = {NULL, NULL};
+ const char *sub;
+ Py_ssize_t slen;
+
+ if (PyBytes_Check(substr)) {
+ sub = PyBytes_AS_STRING(substr);
+ slen = PyBytes_GET_SIZE(substr);
+ }
+ else {
+ if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
+ return -1;
+ sub = sub_view.buf;
+ slen = sub_view.len;
+ }
+
+ ADJUST_INDICES(start, end, len);
+
+ if (direction < 0) {
+ /* startswith */
+ if (start + slen > len)
+ goto notfound;
+ } else {
+ /* endswith */
+ if (end - start < slen || start > len)
+ goto notfound;
+
+ if (end - slen > start)
+ start = end - slen;
+ }
+ if (end - start < slen)
+ goto notfound;
+ if (memcmp(str + start, sub, slen) != 0)
+ goto notfound;
+
+ PyBuffer_Release(&sub_view);
+ return 1;
+
+notfound:
+ PyBuffer_Release(&sub_view);
+ return 0;
+}
+
+static PyObject *
+_Py_bytes_tailmatch(const char *str, Py_ssize_t len,
+ const char *function_name, PyObject *args,
+ int direction)
+{
+ Py_ssize_t start = 0;
+ Py_ssize_t end = PY_SSIZE_T_MAX;
+ PyObject *subobj;
+ int result;
+
+ if (!stringlib_parse_args_finds(function_name, args, &subobj, &start, &end))
+ return NULL;
+ if (PyTuple_Check(subobj)) {
+ Py_ssize_t i;
+ for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
+ result = tailmatch(str, len, PyTuple_GET_ITEM(subobj, i),
+ start, end, direction);
+ if (result == -1)
+ return NULL;
+ else if (result) {
+ Py_RETURN_TRUE;
+ }
+ }
+ Py_RETURN_FALSE;
+ }
+ result = tailmatch(str, len, subobj, start, end, direction);
+ if (result == -1) {
+ if (PyErr_ExceptionMatches(PyExc_TypeError))
+ PyErr_Format(PyExc_TypeError,
+ "%s first arg must be bytes or a tuple of bytes, "
+ "not %s",
+ function_name, Py_TYPE(subobj)->tp_name);
+ return NULL;
+ }
+ else
+ return PyBool_FromLong(result);
+}
+
+PyDoc_STRVAR_shared(_Py_startswith__doc__,
+"B.startswith(prefix[, start[, end]]) -> bool\n\
+\n\
+Return True if B starts with the specified prefix, False otherwise.\n\
+With optional start, test B beginning at that position.\n\
+With optional end, stop comparing B at that position.\n\
+prefix can also be a tuple of bytes to try.");
+
+PyObject *
+_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args)
+{
+ return _Py_bytes_tailmatch(str, len, "startswith", args, -1);
+}
+
+PyDoc_STRVAR_shared(_Py_endswith__doc__,
+"B.endswith(suffix[, start[, end]]) -> bool\n\
+\n\
+Return True if B ends with the specified suffix, False otherwise.\n\
+With optional start, test B beginning at that position.\n\
+With optional end, stop comparing B at that position.\n\
+suffix can also be a tuple of bytes to try.");
+
+PyObject *
+_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args)
+{
+ return _Py_bytes_tailmatch(str, len, "endswith", args, +1);
+}
+
+PyDoc_STRVAR_shared(_Py_expandtabs__doc__,
+"B.expandtabs(tabsize=8) -> copy of B\n\
+\n\
+Return a copy of B where all tab characters are expanded using spaces.\n\
+If tabsize is not given, a tab size of 8 characters is assumed.");
+
+PyDoc_STRVAR_shared(_Py_ljust__doc__,
+"B.ljust(width[, fillchar]) -> copy of B\n"
+"\n"
+"Return B left justified in a string of length width. Padding is\n"
+"done using the specified fill character (default is a space).");
+
+PyDoc_STRVAR_shared(_Py_rjust__doc__,
+"B.rjust(width[, fillchar]) -> copy of B\n"
+"\n"
+"Return B right justified in a string of length width. Padding is\n"
+"done using the specified fill character (default is a space)");
+
+PyDoc_STRVAR_shared(_Py_center__doc__,
+"B.center(width[, fillchar]) -> copy of B\n"
+"\n"
+"Return B centered in a string of length width. Padding is\n"
+"done using the specified fill character (default is a space).");
+
+PyDoc_STRVAR_shared(_Py_zfill__doc__,
+"B.zfill(width) -> copy of B\n"
+"\n"
+"Pad a numeric string B with zeros on the left, to fill a field\n"
+"of the specified width. B is never truncated.");
+
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 673bb00b98..5d48440960 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -9,9 +9,9 @@
#include <stddef.h>
/*[clinic input]
-class bytes "PyBytesObject*" "&PyBytes_Type"
+class bytes "PyBytesObject *" "&PyBytes_Type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7a238f965d64892b]*/
#include "clinic/bytesobject.c.h"
@@ -30,6 +30,10 @@ static PyBytesObject *nullstring;
*/
#define PyBytesObject_SIZE (offsetof(PyBytesObject, ob_sval) + 1)
+/* Forward declaration */
+Py_LOCAL_INLINE(Py_ssize_t) _PyBytesWriter_GetSize(_PyBytesWriter *writer,
+ char *str);
+
/*
For PyBytes_FromString(), the parameter `str' points to a null-terminated
string containing exactly `size' bytes.
@@ -116,7 +120,7 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
if (str == NULL)
return (PyObject *) op;
- Py_MEMCPY(op->ob_sval, str, size);
+ memcpy(op->ob_sval, str, size);
/* share short strings */
if (size == 1) {
characters[*str & UCHAR_MAX] = op;
@@ -159,7 +163,7 @@ PyBytes_FromString(const char *str)
return PyErr_NoMemory();
(void)PyObject_INIT_VAR(op, &PyBytes_Type, size);
op->ob_shash = -1;
- Py_MEMCPY(op->ob_sval, str, size+1);
+ memcpy(op->ob_sval, str, size+1);
/* share short strings */
if (size == 0) {
nullstring = op;
@@ -174,190 +178,184 @@ PyBytes_FromString(const char *str)
PyObject *
PyBytes_FromFormatV(const char *format, va_list vargs)
{
- va_list count;
- Py_ssize_t n = 0;
- const char* f;
char *s;
- PyObject* string;
+ const char *f;
+ const char *p;
+ Py_ssize_t prec;
+ int longflag;
+ int size_tflag;
+ /* Longest 64-bit formatted numbers:
+ - "18446744073709551615\0" (21 bytes)
+ - "-9223372036854775808\0" (21 bytes)
+ Decimal takes the most space (it isn't enough for octal.)
+
+ Longest 64-bit pointer representation:
+ "0xffffffffffffffff\0" (19 bytes). */
+ char buffer[21];
+ _PyBytesWriter writer;
+
+ _PyBytesWriter_Init(&writer);
+
+ s = _PyBytesWriter_Alloc(&writer, strlen(format));
+ if (s == NULL)
+ return NULL;
+ writer.overallocate = 1;
+
+#define WRITE_BYTES(str) \
+ do { \
+ s = _PyBytesWriter_WriteBytes(&writer, s, (str), strlen(str)); \
+ if (s == NULL) \
+ goto error; \
+ } while (0)
- Py_VA_COPY(count, vargs);
- /* step 1: figure out how large a buffer we need */
for (f = format; *f; f++) {
- if (*f == '%') {
- const char* p = f;
- while (*++f && *f != '%' && !Py_ISALPHA(*f))
- ;
-
- /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since
- * they don't affect the amount of space we reserve.
- */
- if ((*f == 'l' || *f == 'z') &&
- (f[1] == 'd' || f[1] == 'u'))
- ++f;
-
- switch (*f) {
- case 'c':
- {
- int c = va_arg(count, int);
- if (c < 0 || c > 255) {
- PyErr_SetString(PyExc_OverflowError,
- "PyBytes_FromFormatV(): %c format "
- "expects an integer in range [0; 255]");
- return NULL;
- }
- n++;
- break;
+ if (*f != '%') {
+ *s++ = *f;
+ continue;
+ }
+
+ p = f++;
+
+ /* ignore the width (ex: 10 in "%10s") */
+ while (Py_ISDIGIT(*f))
+ f++;
+
+ /* parse the precision (ex: 10 in "%.10s") */
+ prec = 0;
+ if (*f == '.') {
+ f++;
+ for (; Py_ISDIGIT(*f); f++) {
+ prec = (prec * 10) + (*f - '0');
}
- case '%':
- n++;
- break;
- case 'd': case 'u': case 'i': case 'x':
- (void) va_arg(count, int);
- /* 20 bytes is enough to hold a 64-bit
- integer. Decimal takes the most space.
- This isn't enough for octal. */
- n += 20;
- break;
- case 's':
- s = va_arg(count, char*);
- n += strlen(s);
- break;
- case 'p':
- (void) va_arg(count, int);
- /* maximum 64-bit pointer representation:
- * 0xffffffffffffffff
- * so 19 characters is enough.
- * XXX I count 18 -- what's the extra for?
- */
- n += 19;
- break;
- default:
- /* if we stumble upon an unknown
- formatting code, copy the rest of
- the format string to the output
- string. (we cannot just skip the
- code, since there's no way to know
- what's in the argument list) */
- n += strlen(p);
- goto expand;
+ }
+
+ while (*f && *f != '%' && !Py_ISALPHA(*f))
+ f++;
+
+ /* handle the long flag ('l'), but only for %ld and %lu.
+ others can be added when necessary. */
+ longflag = 0;
+ if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {
+ longflag = 1;
+ ++f;
+ }
+
+ /* handle the size_t flag ('z'). */
+ size_tflag = 0;
+ if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {
+ size_tflag = 1;
+ ++f;
+ }
+
+ /* subtract bytes preallocated for the format string
+ (ex: 2 for "%s") */
+ writer.min_size -= (f - p + 1);
+
+ switch (*f) {
+ case 'c':
+ {
+ int c = va_arg(vargs, int);
+ if (c < 0 || c > 255) {
+ PyErr_SetString(PyExc_OverflowError,
+ "PyBytes_FromFormatV(): %c format "
+ "expects an integer in range [0; 255]");
+ goto error;
}
- } else
- n++;
- }
- expand:
- /* step 2: fill the buffer */
- /* Since we've analyzed how much space we need for the worst case,
- use sprintf directly instead of the slower PyOS_snprintf. */
- string = PyBytes_FromStringAndSize(NULL, n);
- if (!string)
- return NULL;
+ writer.min_size++;
+ *s++ = (unsigned char)c;
+ break;
+ }
- s = PyBytes_AsString(string);
+ case 'd':
+ if (longflag)
+ sprintf(buffer, "%ld", va_arg(vargs, long));
+ else if (size_tflag)
+ sprintf(buffer, "%" PY_FORMAT_SIZE_T "d",
+ va_arg(vargs, Py_ssize_t));
+ else
+ sprintf(buffer, "%d", va_arg(vargs, int));
+ assert(strlen(buffer) < sizeof(buffer));
+ WRITE_BYTES(buffer);
+ break;
- for (f = format; *f; f++) {
- if (*f == '%') {
- const char* p = f++;
+ case 'u':
+ if (longflag)
+ sprintf(buffer, "%lu",
+ va_arg(vargs, unsigned long));
+ else if (size_tflag)
+ sprintf(buffer, "%" PY_FORMAT_SIZE_T "u",
+ va_arg(vargs, size_t));
+ else
+ sprintf(buffer, "%u",
+ va_arg(vargs, unsigned int));
+ assert(strlen(buffer) < sizeof(buffer));
+ WRITE_BYTES(buffer);
+ break;
+
+ case 'i':
+ sprintf(buffer, "%i", va_arg(vargs, int));
+ assert(strlen(buffer) < sizeof(buffer));
+ WRITE_BYTES(buffer);
+ break;
+
+ case 'x':
+ sprintf(buffer, "%x", va_arg(vargs, int));
+ assert(strlen(buffer) < sizeof(buffer));
+ WRITE_BYTES(buffer);
+ break;
+
+ case 's':
+ {
Py_ssize_t i;
- int longflag = 0;
- int size_tflag = 0;
- /* parse the width.precision part (we're only
- interested in the precision value, if any) */
- n = 0;
- while (Py_ISDIGIT(*f))
- n = (n*10) + *f++ - '0';
- if (*f == '.') {
- f++;
- n = 0;
- while (Py_ISDIGIT(*f))
- n = (n*10) + *f++ - '0';
- }
- while (*f && *f != '%' && !Py_ISALPHA(*f))
- f++;
- /* handle the long flag, but only for %ld and %lu.
- others can be added when necessary. */
- if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {
- longflag = 1;
- ++f;
- }
- /* handle the size_t flag. */
- if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {
- size_tflag = 1;
- ++f;
- }
- switch (*f) {
- case 'c':
- {
- int c = va_arg(vargs, int);
- /* c has been checked for overflow in the first step */
- *s++ = (unsigned char)c;
- break;
+ p = va_arg(vargs, const char*);
+ i = strlen(p);
+ if (prec > 0 && i > prec)
+ i = prec;
+ s = _PyBytesWriter_WriteBytes(&writer, s, p, i);
+ if (s == NULL)
+ goto error;
+ break;
+ }
+
+ case 'p':
+ sprintf(buffer, "%p", va_arg(vargs, void*));
+ assert(strlen(buffer) < sizeof(buffer));
+ /* %p is ill-defined: ensure leading 0x. */
+ if (buffer[1] == 'X')
+ buffer[1] = 'x';
+ else if (buffer[1] != 'x') {
+ memmove(buffer+2, buffer, strlen(buffer)+1);
+ buffer[0] = '0';
+ buffer[1] = 'x';
}
- case 'd':
- if (longflag)
- sprintf(s, "%ld", va_arg(vargs, long));
- else if (size_tflag)
- sprintf(s, "%" PY_FORMAT_SIZE_T "d",
- va_arg(vargs, Py_ssize_t));
- else
- sprintf(s, "%d", va_arg(vargs, int));
- s += strlen(s);
- break;
- case 'u':
- if (longflag)
- sprintf(s, "%lu",
- va_arg(vargs, unsigned long));
- else if (size_tflag)
- sprintf(s, "%" PY_FORMAT_SIZE_T "u",
- va_arg(vargs, size_t));
- else
- sprintf(s, "%u",
- va_arg(vargs, unsigned int));
- s += strlen(s);
- break;
- case 'i':
- sprintf(s, "%i", va_arg(vargs, int));
- s += strlen(s);
- break;
- case 'x':
- sprintf(s, "%x", va_arg(vargs, int));
- s += strlen(s);
- break;
- case 's':
- p = va_arg(vargs, char*);
- i = strlen(p);
- if (n > 0 && i > n)
- i = n;
- Py_MEMCPY(s, p, i);
- s += i;
- break;
- case 'p':
- sprintf(s, "%p", va_arg(vargs, void*));
- /* %p is ill-defined: ensure leading 0x. */
- if (s[1] == 'X')
- s[1] = 'x';
- else if (s[1] != 'x') {
- memmove(s+2, s, strlen(s)+1);
- s[0] = '0';
- s[1] = 'x';
- }
- s += strlen(s);
- break;
- case '%':
- *s++ = '%';
- break;
- default:
- strcpy(s, p);
- s += strlen(s);
- goto end;
+ WRITE_BYTES(buffer);
+ break;
+
+ case '%':
+ writer.min_size++;
+ *s++ = '%';
+ break;
+
+ default:
+ if (*f == 0) {
+ /* fix min_size if we reached the end of the format string */
+ writer.min_size++;
}
- } else
- *s++ = *f;
+
+ /* invalid format string: copy unformatted string and exit */
+ WRITE_BYTES(p);
+ return _PyBytesWriter_Finish(&writer, s);
+ }
}
- end:
- _PyBytes_Resize(&string, s - PyBytes_AS_STRING(string));
- return string;
+#undef WRITE_BYTES
+
+ return _PyBytesWriter_Finish(&writer, s);
+
+ error:
+ _PyBytesWriter_Dealloc(&writer);
+ return NULL;
}
PyObject *
@@ -409,12 +407,14 @@ getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
/* Returns a new reference to a PyBytes object, or NULL on failure. */
-static PyObject *
-formatfloat(PyObject *v, int flags, int prec, int type)
+static char*
+formatfloat(PyObject *v, int flags, int prec, int type,
+ PyObject **p_result, _PyBytesWriter *writer, char *str)
{
char *p;
PyObject *result;
double x;
+ size_t len;
x = PyFloat_AsDouble(v);
if (x == -1.0 && PyErr_Occurred()) {
@@ -431,9 +431,22 @@ formatfloat(PyObject *v, int flags, int prec, int type)
if (p == NULL)
return NULL;
- result = PyBytes_FromStringAndSize(p, strlen(p));
+
+ len = strlen(p);
+ if (writer != NULL) {
+ str = _PyBytesWriter_Prepare(writer, str, len);
+ if (str == NULL)
+ return NULL;
+ memcpy(str, p, len);
+ PyMem_Free(p);
+ str += len;
+ return str;
+ }
+
+ result = PyBytes_FromStringAndSize(p, len);
PyMem_Free(p);
- return result;
+ *p_result = result;
+ return str;
}
static PyObject *
@@ -473,11 +486,11 @@ formatlong(PyObject *v, int flags, int prec, int type)
static int
byte_converter(PyObject *arg, char *p)
{
- if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) {
+ if (PyBytes_Check(arg) && PyBytes_GET_SIZE(arg) == 1) {
*p = PyBytes_AS_STRING(arg)[0];
return 1;
}
- else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) {
+ else if (PyByteArray_Check(arg) && PyByteArray_GET_SIZE(arg) == 1) {
*p = PyByteArray_AS_STRING(arg)[0];
return 1;
}
@@ -557,36 +570,36 @@ format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen)
return NULL;
}
-/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
-
- FORMATBUFLEN is the length of the buffer in which the ints &
- chars are formatted. XXX This is a magic number. Each formatting
- routine does bounds checking to ensure no overflow, but a better
- solution may be to malloc a buffer of appropriate size for each
- format. For now, the current solution is sufficient.
-*/
-#define FORMATBUFLEN (size_t)120
+/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
PyObject *
-_PyBytes_Format(PyObject *format, PyObject *args)
+_PyBytes_FormatEx(const char *format, Py_ssize_t format_len,
+ PyObject *args, int use_bytearray)
{
- char *fmt, *res;
+ const char *fmt;
+ char *res;
Py_ssize_t arglen, argidx;
- Py_ssize_t reslen, rescnt, fmtcnt;
+ Py_ssize_t fmtcnt;
int args_owned = 0;
- PyObject *result;
PyObject *dict = NULL;
- if (format == NULL || !PyBytes_Check(format) || args == NULL) {
+ _PyBytesWriter writer;
+
+ if (args == NULL) {
PyErr_BadInternalCall();
return NULL;
}
- fmt = PyBytes_AS_STRING(format);
- fmtcnt = PyBytes_GET_SIZE(format);
- reslen = rescnt = fmtcnt + 100;
- result = PyBytes_FromStringAndSize((char *)NULL, reslen);
- if (result == NULL)
+ fmt = format;
+ fmtcnt = format_len;
+
+ _PyBytesWriter_Init(&writer);
+ writer.use_bytearray = use_bytearray;
+
+ res = _PyBytesWriter_Alloc(&writer, fmtcnt);
+ if (res == NULL)
return NULL;
- res = PyBytes_AsString(result);
+ if (!use_bytearray)
+ writer.overallocate = 1;
+
if (PyTuple_Check(args)) {
arglen = PyTuple_GET_SIZE(args);
argidx = 0;
@@ -600,18 +613,23 @@ _PyBytes_Format(PyObject *format, PyObject *args)
!PyByteArray_Check(args)) {
dict = args;
}
+
while (--fmtcnt >= 0) {
if (*fmt != '%') {
- if (--rescnt < 0) {
- rescnt = fmtcnt + 100;
- reslen += rescnt;
- if (_PyBytes_Resize(&result, reslen))
- return NULL;
- res = PyBytes_AS_STRING(result)
- + reslen - rescnt;
- --rescnt;
- }
- *res++ = *fmt++;
+ Py_ssize_t len;
+ char *pos;
+
+ pos = strchr(fmt + 1, '%');
+ if (pos != NULL)
+ len = pos - fmt;
+ else
+ len = format_len - (fmt - format);
+ assert(len != 0);
+
+ memcpy(res, fmt, len);
+ res += len;
+ fmt += len;
+ fmtcnt -= (len - 1);
}
else {
/* Got a format specifier */
@@ -626,10 +644,14 @@ _PyBytes_Format(PyObject *format, PyObject *args)
int sign;
Py_ssize_t len = 0;
char onechar; /* For byte_converter() */
+ Py_ssize_t alloc;
+#ifdef Py_DEBUG
+ char *before;
+#endif
fmt++;
if (*fmt == '(') {
- char *keystart;
+ const char *keystart;
Py_ssize_t keylen;
PyObject *key;
int pcount = 1;
@@ -673,6 +695,8 @@ _PyBytes_Format(PyObject *format, PyObject *args)
arglen = -1;
argidx = -2;
}
+
+ /* Parse flags. Example: "%+i" => flags=F_SIGN. */
while (--fmtcnt >= 0) {
switch (c = *fmt++) {
case '-': flags |= F_LJUST; continue;
@@ -683,6 +707,8 @@ _PyBytes_Format(PyObject *format, PyObject *args)
}
break;
}
+
+ /* Parse width. Example: "%10s" => width=10 */
if (c == '*') {
v = getnextarg(args, arglen, &argidx);
if (v == NULL)
@@ -717,6 +743,8 @@ _PyBytes_Format(PyObject *format, PyObject *args)
width = width*10 + (c - '0');
}
}
+
+ /* Parse precision. Example: "%.3f" => prec=3 */
if (c == '.') {
prec = 0;
if (--fmtcnt >= 0)
@@ -771,13 +799,19 @@ _PyBytes_Format(PyObject *format, PyObject *args)
if (v == NULL)
goto error;
}
+
+ if (fmtcnt < 0) {
+ /* last writer: disable writer overallocation */
+ writer.overallocate = 0;
+ }
+
sign = 0;
fill = ' ';
switch (c) {
case '%':
- pbuf = "%";
- len = 1;
- break;
+ *res++ = '%';
+ continue;
+
case 'r':
// %r is only for 2/3 code; 3 only code should use %a
case 'a':
@@ -790,6 +824,7 @@ _PyBytes_Format(PyObject *format, PyObject *args)
if (prec >= 0 && len > prec)
len = prec;
break;
+
case 's':
// %s is only for 2/3 code; 3 only code should use %b
case 'b':
@@ -799,12 +834,49 @@ _PyBytes_Format(PyObject *format, PyObject *args)
if (prec >= 0 && len > prec)
len = prec;
break;
+
case 'i':
case 'd':
case 'u':
case 'o':
case 'x':
case 'X':
+ if (PyLong_CheckExact(v)
+ && width == -1 && prec == -1
+ && !(flags & (F_SIGN | F_BLANK))
+ && c != 'X')
+ {
+ /* Fast path */
+ int alternate = flags & F_ALT;
+ int base;
+
+ switch(c)
+ {
+ default:
+ assert(0 && "'type' not in [diuoxX]");
+ case 'd':
+ case 'i':
+ case 'u':
+ base = 10;
+ break;
+ case 'o':
+ base = 8;
+ break;
+ case 'x':
+ case 'X':
+ base = 16;
+ break;
+ }
+
+ /* Fast path */
+ writer.min_size -= 2; /* size preallocated for "%d" */
+ res = _PyLong_FormatBytesWriter(&writer, res,
+ v, base, alternate);
+ if (res == NULL)
+ goto error;
+ continue;
+ }
+
temp = formatlong(v, flags, prec, c);
if (!temp)
goto error;
@@ -815,14 +887,25 @@ _PyBytes_Format(PyObject *format, PyObject *args)
if (flags & F_ZERO)
fill = '0';
break;
+
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
- temp = formatfloat(v, flags, prec, c);
- if (temp == NULL)
+ if (width == -1 && prec == -1
+ && !(flags & (F_SIGN | F_BLANK)))
+ {
+ /* Fast path */
+ writer.min_size -= 2; /* size preallocated for "%f" */
+ res = formatfloat(v, flags, prec, c, NULL, &writer, res);
+ if (res == NULL)
+ goto error;
+ continue;
+ }
+
+ if (!formatfloat(v, flags, prec, c, &temp, NULL, res))
goto error;
pbuf = PyBytes_AS_STRING(temp);
len = PyBytes_GET_SIZE(temp);
@@ -830,21 +913,28 @@ _PyBytes_Format(PyObject *format, PyObject *args)
if (flags & F_ZERO)
fill = '0';
break;
+
case 'c':
pbuf = &onechar;
len = byte_converter(v, &onechar);
if (!len)
goto error;
+ if (width == -1) {
+ /* Fast path */
+ *res++ = onechar;
+ continue;
+ }
break;
+
default:
PyErr_Format(PyExc_ValueError,
"unsupported format character '%c' (0x%x) "
"at index %zd",
c, c,
- (Py_ssize_t)(fmt - 1 -
- PyBytes_AsString(format)));
+ (Py_ssize_t)(fmt - 1 - format));
goto error;
}
+
if (sign) {
if (*pbuf == '-' || *pbuf == '+') {
sign = *pbuf++;
@@ -859,29 +949,31 @@ _PyBytes_Format(PyObject *format, PyObject *args)
}
if (width < len)
width = len;
- if (rescnt - (sign != 0) < width) {
- reslen -= rescnt;
- rescnt = width + fmtcnt + 100;
- reslen += rescnt;
- if (reslen < 0) {
- Py_DECREF(result);
- Py_XDECREF(temp);
- return PyErr_NoMemory();
- }
- if (_PyBytes_Resize(&result, reslen)) {
- Py_XDECREF(temp);
- return NULL;
- }
- res = PyBytes_AS_STRING(result)
- + reslen - rescnt;
+
+ alloc = width;
+ if (sign != 0 && len == width)
+ alloc++;
+ /* 2: size preallocated for %s */
+ if (alloc > 2) {
+ res = _PyBytesWriter_Prepare(&writer, res, alloc - 2);
+ if (res == NULL)
+ goto error;
}
+#ifdef Py_DEBUG
+ before = res;
+#endif
+
+ /* Write the sign if needed */
if (sign) {
if (fill != ' ')
*res++ = sign;
- rescnt--;
if (width > len)
width--;
}
+
+ /* Write the numeric prefix for "x", "X" and "o" formats
+ if the alternate form is used.
+ For example, write "0x" for the "%#x" format. */
if ((flags & F_ALT) && (c == 'o' || c == 'x' || c == 'X')) {
assert(pbuf[0] == '0');
assert(pbuf[1] == c);
@@ -889,18 +981,21 @@ _PyBytes_Format(PyObject *format, PyObject *args)
*res++ = *pbuf++;
*res++ = *pbuf++;
}
- rescnt -= 2;
width -= 2;
if (width < 0)
width = 0;
len -= 2;
}
+
+ /* Pad left with the fill character if needed */
if (width > len && !(flags & F_LJUST)) {
- do {
- --rescnt;
- *res++ = fill;
- } while (--width > len);
+ memset(res, fill, width - len);
+ res += (width - len);
+ width = len;
}
+
+ /* If padding with spaces: write sign if needed and/or numeric
+ prefix if the alternate form is used */
if (fill == ' ') {
if (sign)
*res++ = sign;
@@ -911,13 +1006,17 @@ _PyBytes_Format(PyObject *format, PyObject *args)
*res++ = *pbuf++;
}
}
- Py_MEMCPY(res, pbuf, len);
+
+ /* Copy bytes */
+ memcpy(res, pbuf, len);
res += len;
- rescnt -= len;
- while (--width >= len) {
- --rescnt;
- *res++ = ' ';
+
+ /* Pad right with the fill character if needed */
+ if (width > len) {
+ memset(res, ' ', width - len);
+ res += (width - len);
}
+
if (dict && (argidx < arglen) && c != '%') {
PyErr_SetString(PyExc_TypeError,
"not all arguments converted during bytes formatting");
@@ -925,22 +1024,31 @@ _PyBytes_Format(PyObject *format, PyObject *args)
goto error;
}
Py_XDECREF(temp);
+
+#ifdef Py_DEBUG
+ /* check that we computed the exact size for this write */
+ assert((res - before) == alloc);
+#endif
} /* '%' */
+
+ /* If overallocation was disabled, ensure that it was the last
+ write. Otherwise, we missed an optimization */
+ assert(writer.overallocate || fmtcnt < 0 || use_bytearray);
} /* until end */
+
if (argidx < arglen && !dict) {
PyErr_SetString(PyExc_TypeError,
"not all arguments converted during bytes formatting");
goto error;
}
+
if (args_owned) {
Py_DECREF(args);
}
- if (_PyBytes_Resize(&result, reslen - rescnt))
- return NULL;
- return result;
+ return _PyBytesWriter_Finish(&writer, res);
error:
- Py_DECREF(result);
+ _PyBytesWriter_Dealloc(&writer);
if (args_owned) {
Py_DECREF(args);
}
@@ -960,61 +1068,88 @@ bytes_dealloc(PyObject *op)
the string is UTF-8 encoded and should be re-encoded in the
specified encoding. */
-PyObject *PyBytes_DecodeEscape(const char *s,
+static char *
+_PyBytes_DecodeEscapeRecode(const char **s, const char *end,
+ const char *errors, const char *recode_encoding,
+ _PyBytesWriter *writer, char *p)
+{
+ PyObject *u, *w;
+ const char* t;
+
+ t = *s;
+ /* Decode non-ASCII bytes as UTF-8. */
+ while (t < end && (*t & 0x80))
+ t++;
+ u = PyUnicode_DecodeUTF8(*s, t - *s, errors);
+ if (u == NULL)
+ return NULL;
+
+ /* Recode them in target encoding. */
+ w = PyUnicode_AsEncodedString(u, recode_encoding, errors);
+ Py_DECREF(u);
+ if (w == NULL)
+ return NULL;
+ assert(PyBytes_Check(w));
+
+ /* Append bytes to output buffer. */
+ writer->min_size--; /* subtract 1 preallocated byte */
+ p = _PyBytesWriter_WriteBytes(writer, p,
+ PyBytes_AS_STRING(w),
+ PyBytes_GET_SIZE(w));
+ Py_DECREF(w);
+ if (p == NULL)
+ return NULL;
+
+ *s = t;
+ return p;
+}
+
+PyObject *_PyBytes_DecodeEscape(const char *s,
Py_ssize_t len,
const char *errors,
Py_ssize_t unicode,
- const char *recode_encoding)
+ const char *recode_encoding,
+ const char **first_invalid_escape)
{
int c;
- char *p, *buf;
+ char *p;
const char *end;
- PyObject *v;
- Py_ssize_t newlen = recode_encoding ? 4*len:len;
- v = PyBytes_FromStringAndSize((char *)NULL, newlen);
- if (v == NULL)
+ _PyBytesWriter writer;
+
+ _PyBytesWriter_Init(&writer);
+
+ p = _PyBytesWriter_Alloc(&writer, len);
+ if (p == NULL)
return NULL;
- p = buf = PyBytes_AsString(v);
+ writer.overallocate = 1;
+
+ *first_invalid_escape = NULL;
+
end = s + len;
while (s < end) {
if (*s != '\\') {
non_esc:
- if (recode_encoding && (*s & 0x80)) {
- PyObject *u, *w;
- char *r;
- const char* t;
- Py_ssize_t rn;
- t = s;
- /* Decode non-ASCII bytes as UTF-8. */
- while (t < end && (*t & 0x80)) t++;
- u = PyUnicode_DecodeUTF8(s, t - s, errors);
- if(!u) goto failed;
-
- /* Recode them in target encoding. */
- w = PyUnicode_AsEncodedString(
- u, recode_encoding, errors);
- Py_DECREF(u);
- if (!w) goto failed;
-
- /* Append bytes to output buffer. */
- assert(PyBytes_Check(w));
- r = PyBytes_AS_STRING(w);
- rn = PyBytes_GET_SIZE(w);
- Py_MEMCPY(p, r, rn);
- p += rn;
- Py_DECREF(w);
- s = t;
- } else {
+ if (!(recode_encoding && (*s & 0x80))) {
*p++ = *s++;
}
+ else {
+ /* non-ASCII character and need to recode */
+ p = _PyBytes_DecodeEscapeRecode(&s, end,
+ errors, recode_encoding,
+ &writer, p);
+ if (p == NULL)
+ goto failed;
+ }
continue;
}
+
s++;
- if (s==end) {
+ if (s == end) {
PyErr_SetString(PyExc_ValueError,
"Trailing \\ in string");
goto failed;
}
+
switch (*s++) {
/* XXX This assumes ASCII! */
case '\n': break;
@@ -1039,28 +1174,18 @@ PyObject *PyBytes_DecodeEscape(const char *s,
*p++ = c;
break;
case 'x':
- if (s+1 < end && Py_ISXDIGIT(s[0]) && Py_ISXDIGIT(s[1])) {
- unsigned int x = 0;
- c = Py_CHARMASK(*s);
- s++;
- if (Py_ISDIGIT(c))
- x = c - '0';
- else if (Py_ISLOWER(c))
- x = 10 + c - 'a';
- else
- x = 10 + c - 'A';
- x = x << 4;
- c = Py_CHARMASK(*s);
- s++;
- if (Py_ISDIGIT(c))
- x += c - '0';
- else if (Py_ISLOWER(c))
- x += 10 + c - 'a';
- else
- x += 10 + c - 'A';
- *p++ = x;
- break;
+ if (s+1 < end) {
+ int digit1, digit2;
+ digit1 = _PyLong_DigitValue[Py_CHARMASK(s[0])];
+ digit2 = _PyLong_DigitValue[Py_CHARMASK(s[1])];
+ if (digit1 < 16 && digit2 < 16) {
+ *p++ = (unsigned char)((digit1 << 4) + digit2);
+ s += 2;
+ break;
+ }
}
+ /* invalid hexadecimal digits */
+
if (!errors || strcmp(errors, "strict") == 0) {
PyErr_Format(PyExc_ValueError,
"invalid \\x escape at position %d",
@@ -1082,21 +1207,49 @@ PyObject *PyBytes_DecodeEscape(const char *s,
if (s < end && Py_ISXDIGIT(s[0]))
s++; /* and a hexdigit */
break;
+
default:
+ if (*first_invalid_escape == NULL) {
+ *first_invalid_escape = s-1; /* Back up one char, since we've
+ already incremented s. */
+ }
*p++ = '\\';
s--;
goto non_esc; /* an arbitrary number of unescaped
UTF-8 bytes may follow. */
}
}
- if (p-buf < newlen)
- _PyBytes_Resize(&v, p - buf);
- return v;
+
+ return _PyBytesWriter_Finish(&writer, p);
+
failed:
- Py_DECREF(v);
+ _PyBytesWriter_Dealloc(&writer);
return NULL;
}
+PyObject *PyBytes_DecodeEscape(const char *s,
+ Py_ssize_t len,
+ const char *errors,
+ Py_ssize_t unicode,
+ const char *recode_encoding)
+{
+ const char* first_invalid_escape;
+ PyObject *result = _PyBytes_DecodeEscape(s, len, errors, unicode,
+ recode_encoding,
+ &first_invalid_escape);
+ if (result == NULL)
+ return NULL;
+ if (first_invalid_escape != NULL) {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "invalid escape sequence '\\%c'",
+ *first_invalid_escape) < 0) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ return result;
+
+}
/* -------------------------------------------------------------------- */
/* object api */
@@ -1348,12 +1501,12 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n)
}
i = 0;
if (i < size) {
- Py_MEMCPY(op->ob_sval, a->ob_sval, Py_SIZE(a));
+ memcpy(op->ob_sval, a->ob_sval, Py_SIZE(a));
i = Py_SIZE(a);
}
while (i < size) {
j = (i <= size-i) ? i : size-i;
- Py_MEMCPY(op->ob_sval+i, op->ob_sval, j);
+ memcpy(op->ob_sval+i, op->ob_sval, j);
i += j;
}
return (PyObject *) op;
@@ -1362,24 +1515,7 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n)
static int
bytes_contains(PyObject *self, PyObject *arg)
{
- Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError);
- if (ival == -1 && PyErr_Occurred()) {
- Py_buffer varg;
- Py_ssize_t pos;
- PyErr_Clear();
- if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0)
- return -1;
- pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self),
- varg.buf, varg.len, 0);
- PyBuffer_Release(&varg);
- return pos >= 0;
- }
- if (ival < 0 || ival >= 256) {
- PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
- return -1;
- }
-
- return memchr(PyBytes_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL;
+ return _Py_bytes_contains(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), arg);
}
static PyObject *
@@ -1392,7 +1528,7 @@ bytes_item(PyBytesObject *a, Py_ssize_t i)
return PyLong_FromLong((unsigned char)a->ob_sval[i]);
}
-Py_LOCAL(int)
+static int
bytes_compare_eq(PyBytesObject *a, PyBytesObject *b)
{
int cmp;
@@ -1626,8 +1762,8 @@ Return a list of the sections in the bytes, using sep as the delimiter.
[clinic start generated code]*/
static PyObject *
-bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
-/*[clinic end generated code: output=8bde44dacb36ef2e input=8b809b39074abbfa]*/
+bytes_split_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit)
+/*[clinic end generated code: output=52126b5844c1d8ef input=8b809b39074abbfa]*/
{
Py_ssize_t len = PyBytes_GET_SIZE(self), n;
const char *s = PyBytes_AS_STRING(self), *sub;
@@ -1651,7 +1787,6 @@ bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
/*[clinic input]
bytes.partition
- self: self(type="PyBytesObject *")
sep: Py_buffer
/
@@ -1667,7 +1802,7 @@ object and two empty bytes objects.
static PyObject *
bytes_partition_impl(PyBytesObject *self, Py_buffer *sep)
-/*[clinic end generated code: output=f532b392a17ff695 input=bc855dc63ca949de]*/
+/*[clinic end generated code: output=f532b392a17ff695 input=61cca95519406099]*/
{
return stringlib_partition(
(PyObject*) self,
@@ -1679,7 +1814,6 @@ bytes_partition_impl(PyBytesObject *self, Py_buffer *sep)
/*[clinic input]
bytes.rpartition
- self: self(type="PyBytesObject *")
sep: Py_buffer
/
@@ -1695,7 +1829,7 @@ objects and the original bytes object.
static PyObject *
bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep)
-/*[clinic end generated code: output=191b114cbb028e50 input=6588fff262a9170e]*/
+/*[clinic end generated code: output=191b114cbb028e50 input=67f689e63a62d478]*/
{
return stringlib_rpartition(
(PyObject*) self,
@@ -1713,8 +1847,8 @@ Splitting is done starting at the end of the bytes and working to the front.
[clinic start generated code]*/
static PyObject *
-bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit)
-/*[clinic end generated code: output=0b6570b977911d88 input=0f86c9f28f7d7b7b]*/
+bytes_rsplit_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit)
+/*[clinic end generated code: output=ba698d9ea01e1c8f input=0f86c9f28f7d7b7b]*/
{
Py_ssize_t len = PyBytes_GET_SIZE(self), n;
const char *s = PyBytes_AS_STRING(self), *sub;
@@ -1752,8 +1886,8 @@ Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'.
[clinic start generated code]*/
static PyObject *
-bytes_join(PyBytesObject*self, PyObject *iterable_of_bytes)
-/*[clinic end generated code: output=634aff14764ff997 input=7fe377b95bd549d2]*/
+bytes_join(PyBytesObject *self, PyObject *iterable_of_bytes)
+/*[clinic end generated code: output=a046f379f626f6f8 input=7fe377b95bd549d2]*/
{
return stringlib_bytes_join((PyObject*)self, iterable_of_bytes);
}
@@ -1766,158 +1900,30 @@ _PyBytes_Join(PyObject *sep, PyObject *x)
return bytes_join((PyBytesObject*)sep, x);
}
-/* helper macro to fixup start/end slice values */
-#define ADJUST_INDICES(start, end, len) \
- if (end > len) \
- end = len; \
- else if (end < 0) { \
- end += len; \
- if (end < 0) \
- end = 0; \
- } \
- if (start < 0) { \
- start += len; \
- if (start < 0) \
- start = 0; \
- }
-
-Py_LOCAL_INLINE(Py_ssize_t)
-bytes_find_internal(PyBytesObject *self, PyObject *args, int dir)
-{
- PyObject *subobj;
- char byte;
- Py_buffer subbuf;
- const char *sub;
- Py_ssize_t len, sub_len;
- Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
- Py_ssize_t res;
-
- if (!stringlib_parse_args_finds_byte("find/rfind/index/rindex",
- args, &subobj, &byte, &start, &end))
- return -2;
-
- if (subobj) {
- if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0)
- return -2;
-
- sub = subbuf.buf;
- sub_len = subbuf.len;
- }
- else {
- sub = &byte;
- sub_len = 1;
- }
- len = PyBytes_GET_SIZE(self);
-
- ADJUST_INDICES(start, end, len);
- if (end - start < sub_len)
- res = -1;
- else if (sub_len == 1
-#ifndef HAVE_MEMRCHR
- && dir > 0
-#endif
- ) {
- unsigned char needle = *sub;
- int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH;
- res = stringlib_fastsearch_memchr_1char(
- PyBytes_AS_STRING(self) + start, end - start,
- needle, needle, mode);
- if (res >= 0)
- res += start;
- }
- else {
- if (dir > 0)
- res = stringlib_find_slice(
- PyBytes_AS_STRING(self), len,
- sub, sub_len, start, end);
- else
- res = stringlib_rfind_slice(
- PyBytes_AS_STRING(self), len,
- sub, sub_len, start, end);
- }
-
- if (subobj)
- PyBuffer_Release(&subbuf);
-
- return res;
-}
-
-
-PyDoc_STRVAR(find__doc__,
-"B.find(sub[, start[, end]]) -> int\n\
-\n\
-Return the lowest index in B where substring sub is found,\n\
-such that sub is contained within B[start:end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
static PyObject *
bytes_find(PyBytesObject *self, PyObject *args)
{
- Py_ssize_t result = bytes_find_internal(self, args, +1);
- if (result == -2)
- return NULL;
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_find(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
-
-PyDoc_STRVAR(index__doc__,
-"B.index(sub[, start[, end]]) -> int\n\
-\n\
-Like B.find() but raise ValueError when the substring is not found.");
-
static PyObject *
bytes_index(PyBytesObject *self, PyObject *args)
{
- Py_ssize_t result = bytes_find_internal(self, args, +1);
- if (result == -2)
- return NULL;
- if (result == -1) {
- PyErr_SetString(PyExc_ValueError,
- "substring not found");
- return NULL;
- }
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_index(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
-PyDoc_STRVAR(rfind__doc__,
-"B.rfind(sub[, start[, end]]) -> int\n\
-\n\
-Return the highest index in B where substring sub is found,\n\
-such that sub is contained within B[start:end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
static PyObject *
bytes_rfind(PyBytesObject *self, PyObject *args)
{
- Py_ssize_t result = bytes_find_internal(self, args, -1);
- if (result == -2)
- return NULL;
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_rfind(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
-PyDoc_STRVAR(rindex__doc__,
-"B.rindex(sub[, start[, end]]) -> int\n\
-\n\
-Like B.rfind() but raise ValueError when the substring is not found.");
-
static PyObject *
bytes_rindex(PyBytesObject *self, PyObject *args)
{
- Py_ssize_t result = bytes_find_internal(self, args, -1);
- if (result == -2)
- return NULL;
- if (result == -1) {
- PyErr_SetString(PyExc_ValueError,
- "substring not found");
- return NULL;
- }
- return PyLong_FromSsize_t(result);
+ return _Py_bytes_rindex(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
@@ -2004,7 +2010,6 @@ do_argstrip(PyBytesObject *self, int striptype, PyObject *bytes)
/*[clinic input]
bytes.strip
- self: self(type="PyBytesObject *")
bytes: object = None
/
@@ -2015,7 +2020,7 @@ If the argument is omitted or None, strip leading and trailing ASCII whitespace.
static PyObject *
bytes_strip_impl(PyBytesObject *self, PyObject *bytes)
-/*[clinic end generated code: output=c7c228d3bd104a1b input=37daa5fad1395d95]*/
+/*[clinic end generated code: output=c7c228d3bd104a1b input=8a354640e4e0b3ef]*/
{
return do_argstrip(self, BOTHSTRIP, bytes);
}
@@ -2023,7 +2028,6 @@ bytes_strip_impl(PyBytesObject *self, PyObject *bytes)
/*[clinic input]
bytes.lstrip
- self: self(type="PyBytesObject *")
bytes: object = None
/
@@ -2034,7 +2038,7 @@ If the argument is omitted or None, strip leading ASCII whitespace.
static PyObject *
bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes)
-/*[clinic end generated code: output=28602e586f524e82 input=88811b09dfbc2988]*/
+/*[clinic end generated code: output=28602e586f524e82 input=9baff4398c3f6857]*/
{
return do_argstrip(self, LEFTSTRIP, bytes);
}
@@ -2042,7 +2046,6 @@ bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes)
/*[clinic input]
bytes.rstrip
- self: self(type="PyBytesObject *")
bytes: object = None
/
@@ -2053,81 +2056,37 @@ If the argument is omitted or None, strip trailing ASCII whitespace.
static PyObject *
bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes)
-/*[clinic end generated code: output=547e3815c95447da input=8f93c9cd361f0140]*/
+/*[clinic end generated code: output=547e3815c95447da input=b78af445c727e32b]*/
{
return do_argstrip(self, RIGHTSTRIP, bytes);
}
-PyDoc_STRVAR(count__doc__,
-"B.count(sub[, start[, end]]) -> int\n\
-\n\
-Return the number of non-overlapping occurrences of substring sub in\n\
-string B[start:end]. Optional arguments start and end are interpreted\n\
-as in slice notation.");
-
static PyObject *
bytes_count(PyBytesObject *self, PyObject *args)
{
- PyObject *sub_obj;
- const char *str = PyBytes_AS_STRING(self), *sub;
- Py_ssize_t sub_len;
- char byte;
- Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
-
- Py_buffer vsub;
- PyObject *count_obj;
-
- if (!stringlib_parse_args_finds_byte("count", args, &sub_obj, &byte,
- &start, &end))
- return NULL;
-
- if (sub_obj) {
- if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0)
- return NULL;
-
- sub = vsub.buf;
- sub_len = vsub.len;
- }
- else {
- sub = &byte;
- sub_len = 1;
- }
-
- ADJUST_INDICES(start, end, PyBytes_GET_SIZE(self));
-
- count_obj = PyLong_FromSsize_t(
- stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX)
- );
-
- if (sub_obj)
- PyBuffer_Release(&vsub);
-
- return count_obj;
+ return _Py_bytes_count(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
/*[clinic input]
bytes.translate
- self: self(type="PyBytesObject *")
table: object
Translation table, which must be a bytes object of length 256.
- [
- deletechars: object
- ]
/
+ delete as deletechars: object(c_default="NULL") = b''
Return a copy with each character mapped by the given translation table.
-All characters occurring in the optional argument deletechars are removed.
+All characters occurring in the optional argument delete are removed.
The remaining characters are mapped through the given translation table.
[clinic start generated code]*/
static PyObject *
-bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
+bytes_translate_impl(PyBytesObject *self, PyObject *table,
PyObject *deletechars)
-/*[clinic end generated code: output=233df850eb50bf8d input=d8fa5519d7cc4be7]*/
+/*[clinic end generated code: output=43be3437f1956211 input=0ecdf159f654233c]*/
{
char *input, *output;
Py_buffer table_view = {NULL, NULL};
@@ -2188,7 +2147,7 @@ bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
PyBuffer_Release(&table_view);
return NULL;
}
- output_start = output = PyBytes_AsString(result);
+ output_start = output = PyBytes_AS_STRING(result);
input = PyBytes_AS_STRING(input_obj);
if (dellen == 0 && table_chars != NULL) {
@@ -2264,498 +2223,6 @@ bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to)
return _Py_bytes_maketrans(frm, to);
}
-/* find and count characters and substrings */
-
-#define findchar(target, target_len, c) \
- ((char *)memchr((const void *)(target), c, target_len))
-
-/* String ops must return a string. */
-/* If the object is subclass of string, create a copy */
-Py_LOCAL(PyBytesObject *)
-return_self(PyBytesObject *self)
-{
- if (PyBytes_CheckExact(self)) {
- Py_INCREF(self);
- return self;
- }
- return (PyBytesObject *)PyBytes_FromStringAndSize(
- PyBytes_AS_STRING(self),
- PyBytes_GET_SIZE(self));
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount)
-{
- Py_ssize_t count=0;
- const char *start=target;
- const char *end=target+target_len;
-
- while ( (start=findchar(start, end-start, c)) != NULL ) {
- count++;
- if (count >= maxcount)
- break;
- start += 1;
- }
- return count;
-}
-
-
-/* Algorithms for different cases of string replacement */
-
-/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
-Py_LOCAL(PyBytesObject *)
-replace_interleave(PyBytesObject *self,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, i;
- PyBytesObject *result;
-
- self_len = PyBytes_GET_SIZE(self);
-
- /* 1 at the end plus 1 after every character;
- count = min(maxcount, self_len + 1) */
- if (maxcount <= self_len)
- count = maxcount;
- else
- /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */
- count = self_len + 1;
-
- /* Check for overflow */
- /* result_len = count * to_len + self_len; */
- assert(count > 0);
- if (to_len > (PY_SSIZE_T_MAX - self_len) / count) {
- PyErr_SetString(PyExc_OverflowError,
- "replacement bytes are too long");
- return NULL;
- }
- result_len = count * to_len + self_len;
-
- if (! (result = (PyBytesObject *)
- PyBytes_FromStringAndSize(NULL, result_len)) )
- return NULL;
-
- self_s = PyBytes_AS_STRING(self);
- result_s = PyBytes_AS_STRING(result);
-
- /* TODO: special case single character, which doesn't need memcpy */
-
- /* Lay the first one down (guaranteed this will occur) */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- count -= 1;
-
- for (i=0; i<count; i++) {
- *result_s++ = *self_s++;
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- }
-
- /* Copy the rest of the original string */
- Py_MEMCPY(result_s, self_s, self_len-i);
-
- return result;
-}
-
-/* Special case for deleting a single character */
-/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
-Py_LOCAL(PyBytesObject *)
-replace_delete_single_character(PyBytesObject *self,
- char from_c, Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count;
- PyBytesObject *result;
-
- self_len = PyBytes_GET_SIZE(self);
- self_s = PyBytes_AS_STRING(self);
-
- count = countchar(self_s, self_len, from_c, maxcount);
- if (count == 0) {
- return return_self(self);
- }
-
- result_len = self_len - count; /* from_len == 1 */
- assert(result_len>=0);
-
- if ( (result = (PyBytesObject *)
- PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyBytes_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- start = next+1;
- }
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
-
-Py_LOCAL(PyBytesObject *)
-replace_delete_substring(PyBytesObject *self,
- const char *from_s, Py_ssize_t from_len,
- Py_ssize_t maxcount) {
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset;
- PyBytesObject *result;
-
- self_len = PyBytes_GET_SIZE(self);
- self_s = PyBytes_AS_STRING(self);
-
- count = stringlib_count(self_s, self_len,
- from_s, from_len,
- maxcount);
-
- if (count == 0) {
- /* no matches */
- return return_self(self);
- }
-
- result_len = self_len - (count * from_len);
- assert (result_len>=0);
-
- if ( (result = (PyBytesObject *)
- PyBytes_FromStringAndSize(NULL, result_len)) == NULL )
- return NULL;
-
- result_s = PyBytes_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- offset = stringlib_find(start, end-start,
- from_s, from_len,
- 0);
- if (offset == -1)
- break;
- next = start + offset;
-
- Py_MEMCPY(result_s, start, next-start);
-
- result_s += (next-start);
- start = next+from_len;
- }
- Py_MEMCPY(result_s, start, end-start);
- return result;
-}
-
-/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
-Py_LOCAL(PyBytesObject *)
-replace_single_character_in_place(PyBytesObject *self,
- char from_c, char to_c,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s, *start, *end, *next;
- Py_ssize_t self_len;
- PyBytesObject *result;
-
- /* The result string will be the same size */
- self_s = PyBytes_AS_STRING(self);
- self_len = PyBytes_GET_SIZE(self);
-
- next = findchar(self_s, self_len, from_c);
-
- if (next == NULL) {
- /* No matches; return the original string */
- return return_self(self);
- }
-
- /* Need to make a new string */
- result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len);
- if (result == NULL)
- return NULL;
- result_s = PyBytes_AS_STRING(result);
- Py_MEMCPY(result_s, self_s, self_len);
-
- /* change everything in-place, starting with this one */
- start = result_s + (next-self_s);
- *start = to_c;
- start++;
- end = result_s + self_len;
-
- while (--maxcount > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
- *next = to_c;
- start = next+1;
- }
-
- return result;
-}
-
-/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyBytesObject *)
-replace_substring_in_place(PyBytesObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *result_s, *start, *end;
- char *self_s;
- Py_ssize_t self_len, offset;
- PyBytesObject *result;
-
- /* The result string will be the same size */
-
- self_s = PyBytes_AS_STRING(self);
- self_len = PyBytes_GET_SIZE(self);
-
- offset = stringlib_find(self_s, self_len,
- from_s, from_len,
- 0);
- if (offset == -1) {
- /* No matches; return the original string */
- return return_self(self);
- }
-
- /* Need to make a new string */
- result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len);
- if (result == NULL)
- return NULL;
- result_s = PyBytes_AS_STRING(result);
- Py_MEMCPY(result_s, self_s, self_len);
-
- /* change everything in-place, starting with this one */
- start = result_s + offset;
- Py_MEMCPY(start, to_s, from_len);
- start += from_len;
- end = result_s + self_len;
-
- while ( --maxcount > 0) {
- offset = stringlib_find(start, end-start,
- from_s, from_len,
- 0);
- if (offset==-1)
- break;
- Py_MEMCPY(start+offset, to_s, from_len);
- start += offset+from_len;
- }
-
- return result;
-}
-
-/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyBytesObject *)
-replace_single_character(PyBytesObject *self,
- char from_c,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count;
- PyBytesObject *result;
-
- self_s = PyBytes_AS_STRING(self);
- self_len = PyBytes_GET_SIZE(self);
-
- count = countchar(self_s, self_len, from_c, maxcount);
- if (count == 0) {
- /* no matches, return unchanged */
- return return_self(self);
- }
-
- /* use the difference between current and new, hence the "-1" */
- /* result_len = self_len + count * (to_len-1) */
- assert(count > 0);
- if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) {
- PyErr_SetString(PyExc_OverflowError,
- "replacement bytes are too long");
- return NULL;
- }
- result_len = self_len + count * (to_len - 1);
-
- if ( (result = (PyBytesObject *)
- PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyBytes_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
-
- if (next == start) {
- /* replace with the 'to' */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start += 1;
- } else {
- /* copy the unchanged old then the 'to' */
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start = next+1;
- }
- }
- /* Copy the remainder of the remaining string */
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyBytesObject *)
-replace_substring(PyBytesObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount) {
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset;
- PyBytesObject *result;
-
- self_s = PyBytes_AS_STRING(self);
- self_len = PyBytes_GET_SIZE(self);
-
- count = stringlib_count(self_s, self_len,
- from_s, from_len,
- maxcount);
-
- if (count == 0) {
- /* no matches, return unchanged */
- return return_self(self);
- }
-
- /* Check for overflow */
- /* result_len = self_len + count * (to_len-from_len) */
- assert(count > 0);
- if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) {
- PyErr_SetString(PyExc_OverflowError,
- "replacement bytes are too long");
- return NULL;
- }
- result_len = self_len + count * (to_len-from_len);
-
- if ( (result = (PyBytesObject *)
- PyBytes_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyBytes_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- offset = stringlib_find(start, end-start,
- from_s, from_len,
- 0);
- if (offset == -1)
- break;
- next = start+offset;
- if (next == start) {
- /* replace with the 'to' */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start += from_len;
- } else {
- /* copy the unchanged old then the 'to' */
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start = next+from_len;
- }
- }
- /* Copy the remainder of the remaining string */
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-
-Py_LOCAL(PyBytesObject *)
-replace(PyBytesObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- if (maxcount < 0) {
- maxcount = PY_SSIZE_T_MAX;
- } else if (maxcount == 0 || PyBytes_GET_SIZE(self) == 0) {
- /* nothing to do; return the original string */
- return return_self(self);
- }
-
- if (maxcount == 0 ||
- (from_len == 0 && to_len == 0)) {
- /* nothing to do; return the original string */
- return return_self(self);
- }
-
- /* Handle zero-length special cases */
-
- if (from_len == 0) {
- /* insert the 'to' string everywhere. */
- /* >>> "Python".replace("", ".") */
- /* '.P.y.t.h.o.n.' */
- return replace_interleave(self, to_s, to_len, maxcount);
- }
-
- /* Except for "".replace("", "A") == "A" there is no way beyond this */
- /* point for an empty self string to generate a non-empty string */
- /* Special case so the remaining code always gets a non-empty string */
- if (PyBytes_GET_SIZE(self) == 0) {
- return return_self(self);
- }
-
- if (to_len == 0) {
- /* delete all occurrences of 'from' string */
- if (from_len == 1) {
- return replace_delete_single_character(
- self, from_s[0], maxcount);
- } else {
- return replace_delete_substring(self, from_s,
- from_len, maxcount);
- }
- }
-
- /* Handle special case where both strings have the same length */
-
- if (from_len == to_len) {
- if (from_len == 1) {
- return replace_single_character_in_place(
- self,
- from_s[0],
- to_s[0],
- maxcount);
- } else {
- return replace_substring_in_place(
- self, from_s, from_len, to_s, to_len,
- maxcount);
- }
- }
-
- /* Otherwise use the more generic algorithms */
- if (from_len == 1) {
- return replace_single_character(self, from_s[0],
- to_s, to_len, maxcount);
- } else {
- /* len('from')>=2, len('to')>=1 */
- return replace_substring(self, from_s, from_len, to_s, to_len,
- maxcount);
- }
-}
-
/*[clinic input]
bytes.replace
@@ -2774,156 +2241,28 @@ replaced.
[clinic start generated code]*/
static PyObject *
-bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new,
+bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
Py_ssize_t count)
-/*[clinic end generated code: output=403dc9d7a83c5a1d input=b2fbbf0bf04de8e5]*/
+/*[clinic end generated code: output=994fa588b6b9c104 input=b2fbbf0bf04de8e5]*/
{
- return (PyObject *)replace((PyBytesObject *) self,
- (const char *)old->buf, old->len,
- (const char *)new->buf, new->len, count);
+ return stringlib_replace((PyObject *)self,
+ (const char *)old->buf, old->len,
+ (const char *)new->buf, new->len, count);
}
/** End DALKE **/
-/* Matches the end (direction >= 0) or start (direction < 0) of self
- * against substr, using the start and end arguments. Returns
- * -1 on error, 0 if not found and 1 if found.
- */
-Py_LOCAL(int)
-_bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start,
- Py_ssize_t end, int direction)
-{
- Py_ssize_t len = PyBytes_GET_SIZE(self);
- Py_ssize_t slen;
- Py_buffer sub_view = {NULL, NULL};
- const char* sub;
- const char* str;
-
- if (PyBytes_Check(substr)) {
- sub = PyBytes_AS_STRING(substr);
- slen = PyBytes_GET_SIZE(substr);
- }
- else {
- if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0)
- return -1;
- sub = sub_view.buf;
- slen = sub_view.len;
- }
- str = PyBytes_AS_STRING(self);
-
- ADJUST_INDICES(start, end, len);
-
- if (direction < 0) {
- /* startswith */
- if (start+slen > len)
- goto notfound;
- } else {
- /* endswith */
- if (end-start < slen || start > len)
- goto notfound;
-
- if (end-slen > start)
- start = end - slen;
- }
- if (end-start < slen)
- goto notfound;
- if (memcmp(str+start, sub, slen) != 0)
- goto notfound;
-
- PyBuffer_Release(&sub_view);
- return 1;
-
-notfound:
- PyBuffer_Release(&sub_view);
- return 0;
-}
-
-
-PyDoc_STRVAR(startswith__doc__,
-"B.startswith(prefix[, start[, end]]) -> bool\n\
-\n\
-Return True if B starts with the specified prefix, False otherwise.\n\
-With optional start, test B beginning at that position.\n\
-With optional end, stop comparing B at that position.\n\
-prefix can also be a tuple of bytes to try.");
static PyObject *
bytes_startswith(PyBytesObject *self, PyObject *args)
{
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *subobj;
- int result;
-
- if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- result = _bytes_tailmatch(self,
- PyTuple_GET_ITEM(subobj, i),
- start, end, -1);
- if (result == -1)
- return NULL;
- else if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- result = _bytes_tailmatch(self, subobj, start, end, -1);
- if (result == -1) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError, "startswith first arg must be bytes "
- "or a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
- return NULL;
- }
- else
- return PyBool_FromLong(result);
+ return _Py_bytes_startswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
-
-PyDoc_STRVAR(endswith__doc__,
-"B.endswith(suffix[, start[, end]]) -> bool\n\
-\n\
-Return True if B ends with the specified suffix, False otherwise.\n\
-With optional start, test B beginning at that position.\n\
-With optional end, stop comparing B at that position.\n\
-suffix can also be a tuple of bytes to try.");
-
static PyObject *
bytes_endswith(PyBytesObject *self, PyObject *args)
{
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *subobj;
- int result;
-
- if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- result = _bytes_tailmatch(self,
- PyTuple_GET_ITEM(subobj, i),
- start, end, +1);
- if (result == -1)
- return NULL;
- else if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- result = _bytes_tailmatch(self, subobj, start, end, +1);
- if (result == -1) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError, "endswith first arg must be bytes or "
- "a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name);
- return NULL;
- }
- else
- return PyBool_FromLong(result);
+ return _Py_bytes_endswith(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), args);
}
@@ -2943,9 +2282,9 @@ Decode the bytes using the codec registered for encoding.
[clinic start generated code]*/
static PyObject *
-bytes_decode_impl(PyBytesObject*self, const char *encoding,
+bytes_decode_impl(PyBytesObject *self, const char *encoding,
const char *errors)
-/*[clinic end generated code: output=2d2016ff8e0bb176 input=958174769d2a40ca]*/
+/*[clinic end generated code: output=5649a53dde27b314 input=958174769d2a40ca]*/
{
return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors);
}
@@ -2963,8 +2302,8 @@ true.
[clinic start generated code]*/
static PyObject *
-bytes_splitlines_impl(PyBytesObject*self, int keepends)
-/*[clinic end generated code: output=995c3598f7833cad input=7f4aac67144f9944]*/
+bytes_splitlines_impl(PyBytesObject *self, int keepends)
+/*[clinic end generated code: output=3484149a5d880ffb input=7f4aac67144f9944]*/
{
return stringlib_splitlines(
(PyObject*) self, PyBytes_AS_STRING(self),
@@ -2972,22 +2311,6 @@ bytes_splitlines_impl(PyBytesObject*self, int keepends)
);
}
-static int
-hex_digit_to_int(Py_UCS4 c)
-{
- if (c >= 128)
- return -1;
- if (Py_ISDIGIT(c))
- return c - '0';
- else {
- if (Py_ISUPPER(c))
- c = Py_TOLOWER(c);
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- }
- return -1;
-}
-
/*[clinic input]
@classmethod
bytes.fromhex
@@ -3005,47 +2328,88 @@ static PyObject *
bytes_fromhex_impl(PyTypeObject *type, PyObject *string)
/*[clinic end generated code: output=0973acc63661bb2e input=bf4d1c361670acd3]*/
{
- PyObject *newstring;
+ PyObject *result = _PyBytes_FromHex(string, 0);
+ if (type != &PyBytes_Type && result != NULL) {
+ Py_SETREF(result, PyObject_CallFunctionObjArgs((PyObject *)type,
+ result, NULL));
+ }
+ return result;
+}
+
+PyObject*
+_PyBytes_FromHex(PyObject *string, int use_bytearray)
+{
char *buf;
- Py_ssize_t hexlen, byteslen, i, j;
- int top, bot;
- void *data;
- unsigned int kind;
+ Py_ssize_t hexlen, invalid_char;
+ unsigned int top, bot;
+ Py_UCS1 *str, *end;
+ _PyBytesWriter writer;
+
+ _PyBytesWriter_Init(&writer);
+ writer.use_bytearray = use_bytearray;
assert(PyUnicode_Check(string));
if (PyUnicode_READY(string))
return NULL;
- kind = PyUnicode_KIND(string);
- data = PyUnicode_DATA(string);
hexlen = PyUnicode_GET_LENGTH(string);
- byteslen = hexlen/2; /* This overestimates if there are spaces */
- newstring = PyBytes_FromStringAndSize(NULL, byteslen);
- if (!newstring)
+ if (!PyUnicode_IS_ASCII(string)) {
+ void *data = PyUnicode_DATA(string);
+ unsigned int kind = PyUnicode_KIND(string);
+ Py_ssize_t i;
+
+ /* search for the first non-ASCII character */
+ for (i = 0; i < hexlen; i++) {
+ if (PyUnicode_READ(kind, data, i) >= 128)
+ break;
+ }
+ invalid_char = i;
+ goto error;
+ }
+
+ assert(PyUnicode_KIND(string) == PyUnicode_1BYTE_KIND);
+ str = PyUnicode_1BYTE_DATA(string);
+
+ /* This overestimates if there are spaces */
+ buf = _PyBytesWriter_Alloc(&writer, hexlen / 2);
+ if (buf == NULL)
return NULL;
- buf = PyBytes_AS_STRING(newstring);
- for (i = j = 0; i < hexlen; i += 2) {
+
+ end = str + hexlen;
+ while (str < end) {
/* skip over spaces in the input */
- while (PyUnicode_READ(kind, data, i) == ' ')
- i++;
- if (i >= hexlen)
- break;
- top = hex_digit_to_int(PyUnicode_READ(kind, data, i));
- bot = hex_digit_to_int(PyUnicode_READ(kind, data, i+1));
- if (top == -1 || bot == -1) {
- PyErr_Format(PyExc_ValueError,
- "non-hexadecimal number found in "
- "fromhex() arg at position %zd", i);
+ if (*str == ' ') {
+ do {
+ str++;
+ } while (*str == ' ');
+ if (str >= end)
+ break;
+ }
+
+ top = _PyLong_DigitValue[*str];
+ if (top >= 16) {
+ invalid_char = str - PyUnicode_1BYTE_DATA(string);
+ goto error;
+ }
+ str++;
+
+ bot = _PyLong_DigitValue[*str];
+ if (bot >= 16) {
+ invalid_char = str - PyUnicode_1BYTE_DATA(string);
goto error;
}
- buf[j++] = (top << 4) + bot;
+ str++;
+
+ *buf++ = (unsigned char)((top << 4) + bot);
}
- if (j != byteslen && _PyBytes_Resize(&newstring, j) < 0)
- goto error;
- return newstring;
+
+ return _PyBytesWriter_Finish(&writer, buf);
error:
- Py_XDECREF(newstring);
+ PyErr_Format(PyExc_ValueError,
+ "non-hexadecimal number found in "
+ "fromhex() arg at position %zd", invalid_char);
+ _PyBytesWriter_Dealloc(&writer);
return NULL;
}
@@ -3075,17 +2439,20 @@ bytes_methods[] = {
{"__getnewargs__", (PyCFunction)bytes_getnewargs, METH_NOARGS},
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
_Py_capitalize__doc__},
- {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__},
- {"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__},
+ {"center", (PyCFunction)stringlib_center, METH_VARARGS,
+ _Py_center__doc__},
+ {"count", (PyCFunction)bytes_count, METH_VARARGS,
+ _Py_count__doc__},
BYTES_DECODE_METHODDEF
{"endswith", (PyCFunction)bytes_endswith, METH_VARARGS,
- endswith__doc__},
+ _Py_endswith__doc__},
{"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS,
- expandtabs__doc__},
- {"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__},
+ _Py_expandtabs__doc__},
+ {"find", (PyCFunction)bytes_find, METH_VARARGS,
+ _Py_find__doc__},
BYTES_FROMHEX_METHODDEF
{"hex", (PyCFunction)bytes_hex, METH_NOARGS, hex__doc__},
- {"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__},
+ {"index", (PyCFunction)bytes_index, METH_VARARGS, _Py_index__doc__},
{"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS,
_Py_isalnum__doc__},
{"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS,
@@ -3101,38 +2468,40 @@ bytes_methods[] = {
{"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS,
_Py_isupper__doc__},
BYTES_JOIN_METHODDEF
- {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__},
+ {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, _Py_ljust__doc__},
{"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__},
BYTES_LSTRIP_METHODDEF
BYTES_MAKETRANS_METHODDEF
BYTES_PARTITION_METHODDEF
BYTES_REPLACE_METHODDEF
- {"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, rfind__doc__},
- {"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, rindex__doc__},
- {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__},
+ {"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
+ {"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
+ {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, _Py_rjust__doc__},
BYTES_RPARTITION_METHODDEF
BYTES_RSPLIT_METHODDEF
BYTES_RSTRIP_METHODDEF
BYTES_SPLIT_METHODDEF
BYTES_SPLITLINES_METHODDEF
{"startswith", (PyCFunction)bytes_startswith, METH_VARARGS,
- startswith__doc__},
+ _Py_startswith__doc__},
BYTES_STRIP_METHODDEF
{"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS,
_Py_swapcase__doc__},
{"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__},
BYTES_TRANSLATE_METHODDEF
{"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__},
- {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__},
+ {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, _Py_zfill__doc__},
{NULL, NULL} /* sentinel */
};
static PyObject *
-bytes_mod(PyObject *v, PyObject *w)
+bytes_mod(PyObject *self, PyObject *arg)
{
- if (!PyBytes_Check(v))
+ if (!PyBytes_Check(self)) {
Py_RETURN_NOTIMPLEMENTED;
- return _PyBytes_Format(v, w);
+ }
+ return _PyBytes_FormatEx(PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self),
+ arg, 0);
}
static PyNumberMethods bytes_as_number = {
@@ -3221,128 +2590,115 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
/* Is it an integer? */
- size = PyNumber_AsSsize_t(x, PyExc_OverflowError);
- if (size == -1 && PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_OverflowError))
- return NULL;
- PyErr_Clear();
- }
- else if (size < 0) {
- PyErr_SetString(PyExc_ValueError, "negative count");
- return NULL;
- }
- else {
- new = _PyBytes_FromSize(size, 1);
- if (new == NULL)
- return NULL;
- return new;
+ if (PyIndex_Check(x)) {
+ size = PyNumber_AsSsize_t(x, PyExc_OverflowError);
+ if (size == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_OverflowError))
+ return NULL;
+ PyErr_Clear(); /* fall through */
+ }
+ else {
+ if (size < 0) {
+ PyErr_SetString(PyExc_ValueError, "negative count");
+ return NULL;
+ }
+ new = _PyBytes_FromSize(size, 1);
+ if (new == NULL)
+ return NULL;
+ return new;
+ }
}
return PyBytes_FromObject(x);
}
-PyObject *
-PyBytes_FromObject(PyObject *x)
+static PyObject*
+_PyBytes_FromBuffer(PyObject *x)
{
- PyObject *new, *it;
- Py_ssize_t i, size;
+ PyObject *new;
+ Py_buffer view;
- if (x == NULL) {
- PyErr_BadInternalCall();
+ if (PyObject_GetBuffer(x, &view, PyBUF_FULL_RO) < 0)
return NULL;
- }
- if (PyBytes_CheckExact(x)) {
- Py_INCREF(x);
- return x;
- }
+ new = PyBytes_FromStringAndSize(NULL, view.len);
+ if (!new)
+ goto fail;
+ if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
+ &view, view.len, 'C') < 0)
+ goto fail;
+ PyBuffer_Release(&view);
+ return new;
- /* Use the modern buffer interface */
- if (PyObject_CheckBuffer(x)) {
- Py_buffer view;
- if (PyObject_GetBuffer(x, &view, PyBUF_FULL_RO) < 0)
- return NULL;
- new = PyBytes_FromStringAndSize(NULL, view.len);
- if (!new)
- goto fail;
- if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval,
- &view, view.len, 'C') < 0)
- goto fail;
- PyBuffer_Release(&view);
- return new;
- fail:
- Py_XDECREF(new);
- PyBuffer_Release(&view);
- return NULL;
- }
- if (PyUnicode_Check(x)) {
- PyErr_SetString(PyExc_TypeError,
- "cannot convert unicode object to bytes");
- return NULL;
- }
+fail:
+ Py_XDECREF(new);
+ PyBuffer_Release(&view);
+ return NULL;
+}
- if (PyList_CheckExact(x)) {
- new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
- if (new == NULL)
- return NULL;
- for (i = 0; i < Py_SIZE(x); i++) {
- Py_ssize_t value = PyNumber_AsSsize_t(
- PyList_GET_ITEM(x, i), PyExc_ValueError);
- if (value == -1 && PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (value < 0 || value >= 256) {
- PyErr_SetString(PyExc_ValueError,
- "bytes must be in range(0, 256)");
- Py_DECREF(new);
- return NULL;
- }
- ((PyBytesObject *)new)->ob_sval[i] = (char) value;
- }
- return new;
- }
- if (PyTuple_CheckExact(x)) {
- new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x));
- if (new == NULL)
- return NULL;
- for (i = 0; i < Py_SIZE(x); i++) {
- Py_ssize_t value = PyNumber_AsSsize_t(
- PyTuple_GET_ITEM(x, i), PyExc_ValueError);
- if (value == -1 && PyErr_Occurred()) {
- Py_DECREF(new);
- return NULL;
- }
- if (value < 0 || value >= 256) {
- PyErr_SetString(PyExc_ValueError,
- "bytes must be in range(0, 256)");
- Py_DECREF(new);
- return NULL;
- }
- ((PyBytesObject *)new)->ob_sval[i] = (char) value;
- }
- return new;
- }
+#define _PyBytes_FROM_LIST_BODY(x, GET_ITEM) \
+ do { \
+ PyObject *bytes; \
+ Py_ssize_t i; \
+ Py_ssize_t value; \
+ char *str; \
+ PyObject *item; \
+ \
+ bytes = PyBytes_FromStringAndSize(NULL, Py_SIZE(x)); \
+ if (bytes == NULL) \
+ return NULL; \
+ str = ((PyBytesObject *)bytes)->ob_sval; \
+ \
+ for (i = 0; i < Py_SIZE(x); i++) { \
+ item = GET_ITEM((x), i); \
+ value = PyNumber_AsSsize_t(item, NULL); \
+ if (value == -1 && PyErr_Occurred()) \
+ goto error; \
+ \
+ if (value < 0 || value >= 256) { \
+ PyErr_SetString(PyExc_ValueError, \
+ "bytes must be in range(0, 256)"); \
+ goto error; \
+ } \
+ *str++ = (char) value; \
+ } \
+ return bytes; \
+ \
+ error: \
+ Py_DECREF(bytes); \
+ return NULL; \
+ } while (0)
+
+static PyObject*
+_PyBytes_FromList(PyObject *x)
+{
+ _PyBytes_FROM_LIST_BODY(x, PyList_GET_ITEM);
+}
+
+static PyObject*
+_PyBytes_FromTuple(PyObject *x)
+{
+ _PyBytes_FROM_LIST_BODY(x, PyTuple_GET_ITEM);
+}
+
+static PyObject *
+_PyBytes_FromIterator(PyObject *it, PyObject *x)
+{
+ char *str;
+ Py_ssize_t i, size;
+ _PyBytesWriter writer;
/* For iterator version, create a string object and resize as needed */
size = PyObject_LengthHint(x, 64);
if (size == -1 && PyErr_Occurred())
return NULL;
- /* Allocate an extra byte to prevent PyBytes_FromStringAndSize() from
- returning a shared empty bytes string. This required because we
- want to call _PyBytes_Resize() the returned object, which we can
- only do on bytes objects with refcount == 1. */
- if (size == 0)
- size = 1;
- new = PyBytes_FromStringAndSize(NULL, size);
- if (new == NULL)
- return NULL;
- assert(Py_REFCNT(new) == 1);
- /* Get the iterator */
- it = PyObject_GetIter(x);
- if (it == NULL)
- goto error;
+ _PyBytesWriter_Init(&writer);
+ str = _PyBytesWriter_Alloc(&writer, size);
+ if (str == NULL)
+ return NULL;
+ writer.overallocate = 1;
+ size = writer.allocated;
/* Run the iterator to exhaustion */
for (i = 0; ; i++) {
@@ -3358,7 +2714,7 @@ PyBytes_FromObject(PyObject *x)
}
/* Interpret it as an int (__index__) */
- value = PyNumber_AsSsize_t(item, PyExc_ValueError);
+ value = PyNumber_AsSsize_t(item, NULL);
Py_DECREF(item);
if (value == -1 && PyErr_Occurred())
goto error;
@@ -3372,21 +2728,58 @@ PyBytes_FromObject(PyObject *x)
/* Append the byte */
if (i >= size) {
- size = 2 * size + 1;
- if (_PyBytes_Resize(&new, size) < 0)
- goto error;
+ str = _PyBytesWriter_Resize(&writer, str, size+1);
+ if (str == NULL)
+ return NULL;
+ size = writer.allocated;
}
- ((PyBytesObject *)new)->ob_sval[i] = (char) value;
+ *str++ = (char) value;
}
- _PyBytes_Resize(&new, i);
- /* Clean up and return success */
- Py_DECREF(it);
- return new;
+ return _PyBytesWriter_Finish(&writer, str);
error:
- Py_XDECREF(it);
- Py_XDECREF(new);
+ _PyBytesWriter_Dealloc(&writer);
+ return NULL;
+}
+
+PyObject *
+PyBytes_FromObject(PyObject *x)
+{
+ PyObject *it, *result;
+
+ if (x == NULL) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+
+ if (PyBytes_CheckExact(x)) {
+ Py_INCREF(x);
+ return x;
+ }
+
+ /* Use the modern buffer interface */
+ if (PyObject_CheckBuffer(x))
+ return _PyBytes_FromBuffer(x);
+
+ if (PyList_CheckExact(x))
+ return _PyBytes_FromList(x);
+
+ if (PyTuple_CheckExact(x))
+ return _PyBytes_FromTuple(x);
+
+ if (!PyUnicode_Check(x)) {
+ it = PyObject_GetIter(x);
+ if (it != NULL) {
+ result = _PyBytes_FromIterator(it, x);
+ Py_DECREF(it);
+ return result;
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "cannot convert '%.200s' object to bytes",
+ x->ob_type->tp_name);
return NULL;
}
@@ -3404,7 +2797,7 @@ bytes_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
n = PyBytes_GET_SIZE(tmp);
pnew = type->tp_alloc(type, n);
if (pnew != NULL) {
- Py_MEMCPY(PyBytes_AS_STRING(pnew),
+ memcpy(PyBytes_AS_STRING(pnew),
PyBytes_AS_STRING(tmp), n+1);
((PyBytesObject *)pnew)->ob_shash =
((PyBytesObject *)tmp)->ob_shash;
@@ -3746,3 +3139,282 @@ bytes_iter(PyObject *seq)
_PyObject_GC_TRACK(it);
return (PyObject *)it;
}
+
+
+/* _PyBytesWriter API */
+
+#ifdef MS_WINDOWS
+ /* On Windows, overallocate by 50% is the best factor */
+# define OVERALLOCATE_FACTOR 2
+#else
+ /* On Linux, overallocate by 25% is the best factor */
+# define OVERALLOCATE_FACTOR 4
+#endif
+
+void
+_PyBytesWriter_Init(_PyBytesWriter *writer)
+{
+ /* Set all attributes before small_buffer to 0 */
+ memset(writer, 0, offsetof(_PyBytesWriter, small_buffer));
+#ifdef Py_DEBUG
+ memset(writer->small_buffer, 0xCB, sizeof(writer->small_buffer));
+#endif
+}
+
+void
+_PyBytesWriter_Dealloc(_PyBytesWriter *writer)
+{
+ Py_CLEAR(writer->buffer);
+}
+
+Py_LOCAL_INLINE(char*)
+_PyBytesWriter_AsString(_PyBytesWriter *writer)
+{
+ if (writer->use_small_buffer) {
+ assert(writer->buffer == NULL);
+ return writer->small_buffer;
+ }
+ else if (writer->use_bytearray) {
+ assert(writer->buffer != NULL);
+ return PyByteArray_AS_STRING(writer->buffer);
+ }
+ else {
+ assert(writer->buffer != NULL);
+ return PyBytes_AS_STRING(writer->buffer);
+ }
+}
+
+Py_LOCAL_INLINE(Py_ssize_t)
+_PyBytesWriter_GetSize(_PyBytesWriter *writer, char *str)
+{
+ char *start = _PyBytesWriter_AsString(writer);
+ assert(str != NULL);
+ assert(str >= start);
+ assert(str - start <= writer->allocated);
+ return str - start;
+}
+
+Py_LOCAL_INLINE(void)
+_PyBytesWriter_CheckConsistency(_PyBytesWriter *writer, char *str)
+{
+#ifdef Py_DEBUG
+ char *start, *end;
+
+ if (writer->use_small_buffer) {
+ assert(writer->buffer == NULL);
+ }
+ else {
+ assert(writer->buffer != NULL);
+ if (writer->use_bytearray)
+ assert(PyByteArray_CheckExact(writer->buffer));
+ else
+ assert(PyBytes_CheckExact(writer->buffer));
+ assert(Py_REFCNT(writer->buffer) == 1);
+ }
+
+ if (writer->use_bytearray) {
+ /* bytearray has its own overallocation algorithm,
+ writer overallocation must be disabled */
+ assert(!writer->overallocate);
+ }
+
+ assert(0 <= writer->allocated);
+ assert(0 <= writer->min_size && writer->min_size <= writer->allocated);
+ /* the last byte must always be null */
+ start = _PyBytesWriter_AsString(writer);
+ assert(start[writer->allocated] == 0);
+
+ end = start + writer->allocated;
+ assert(str != NULL);
+ assert(start <= str && str <= end);
+#endif
+}
+
+void*
+_PyBytesWriter_Resize(_PyBytesWriter *writer, void *str, Py_ssize_t size)
+{
+ Py_ssize_t allocated, pos;
+
+ _PyBytesWriter_CheckConsistency(writer, str);
+ assert(writer->allocated < size);
+
+ allocated = size;
+ if (writer->overallocate
+ && allocated <= (PY_SSIZE_T_MAX - allocated / OVERALLOCATE_FACTOR)) {
+ /* overallocate to limit the number of realloc() */
+ allocated += allocated / OVERALLOCATE_FACTOR;
+ }
+
+ pos = _PyBytesWriter_GetSize(writer, str);
+ if (!writer->use_small_buffer) {
+ if (writer->use_bytearray) {
+ if (PyByteArray_Resize(writer->buffer, allocated))
+ goto error;
+ /* writer->allocated can be smaller than writer->buffer->ob_alloc,
+ but we cannot use ob_alloc because bytes may need to be moved
+ to use the whole buffer. bytearray uses an internal optimization
+ to avoid moving or copying bytes when bytes are removed at the
+ beginning (ex: del bytearray[:1]). */
+ }
+ else {
+ if (_PyBytes_Resize(&writer->buffer, allocated))
+ goto error;
+ }
+ }
+ else {
+ /* convert from stack buffer to bytes object buffer */
+ assert(writer->buffer == NULL);
+
+ if (writer->use_bytearray)
+ writer->buffer = PyByteArray_FromStringAndSize(NULL, allocated);
+ else
+ writer->buffer = PyBytes_FromStringAndSize(NULL, allocated);
+ if (writer->buffer == NULL)
+ goto error;
+
+ if (pos != 0) {
+ char *dest;
+ if (writer->use_bytearray)
+ dest = PyByteArray_AS_STRING(writer->buffer);
+ else
+ dest = PyBytes_AS_STRING(writer->buffer);
+ memcpy(dest,
+ writer->small_buffer,
+ pos);
+ }
+
+ writer->use_small_buffer = 0;
+#ifdef Py_DEBUG
+ memset(writer->small_buffer, 0xDB, sizeof(writer->small_buffer));
+#endif
+ }
+ writer->allocated = allocated;
+
+ str = _PyBytesWriter_AsString(writer) + pos;
+ _PyBytesWriter_CheckConsistency(writer, str);
+ return str;
+
+error:
+ _PyBytesWriter_Dealloc(writer);
+ return NULL;
+}
+
+void*
+_PyBytesWriter_Prepare(_PyBytesWriter *writer, void *str, Py_ssize_t size)
+{
+ Py_ssize_t new_min_size;
+
+ _PyBytesWriter_CheckConsistency(writer, str);
+ assert(size >= 0);
+
+ if (size == 0) {
+ /* nothing to do */
+ return str;
+ }
+
+ if (writer->min_size > PY_SSIZE_T_MAX - size) {
+ PyErr_NoMemory();
+ _PyBytesWriter_Dealloc(writer);
+ return NULL;
+ }
+ new_min_size = writer->min_size + size;
+
+ if (new_min_size > writer->allocated)
+ str = _PyBytesWriter_Resize(writer, str, new_min_size);
+
+ writer->min_size = new_min_size;
+ return str;
+}
+
+/* Allocate the buffer to write size bytes.
+ Return the pointer to the beginning of buffer data.
+ Raise an exception and return NULL on error. */
+void*
+_PyBytesWriter_Alloc(_PyBytesWriter *writer, Py_ssize_t size)
+{
+ /* ensure that _PyBytesWriter_Alloc() is only called once */
+ assert(writer->min_size == 0 && writer->buffer == NULL);
+ assert(size >= 0);
+
+ writer->use_small_buffer = 1;
+#ifdef Py_DEBUG
+ writer->allocated = sizeof(writer->small_buffer) - 1;
+ /* In debug mode, don't use the full small buffer because it is less
+ efficient than bytes and bytearray objects to detect buffer underflow
+ and buffer overflow. Use 10 bytes of the small buffer to test also
+ code using the smaller buffer in debug mode.
+
+ Don't modify the _PyBytesWriter structure (use a shorter small buffer)
+ in debug mode to also be able to detect stack overflow when running
+ tests in debug mode. The _PyBytesWriter is large (more than 512 bytes),
+ if Py_EnterRecursiveCall() is not used in deep C callback, we may hit a
+ stack overflow. */
+ writer->allocated = Py_MIN(writer->allocated, 10);
+ /* _PyBytesWriter_CheckConsistency() requires the last byte to be 0,
+ to detect buffer overflow */
+ writer->small_buffer[writer->allocated] = 0;
+#else
+ writer->allocated = sizeof(writer->small_buffer);
+#endif
+ return _PyBytesWriter_Prepare(writer, writer->small_buffer, size);
+}
+
+PyObject *
+_PyBytesWriter_Finish(_PyBytesWriter *writer, void *str)
+{
+ Py_ssize_t size;
+ PyObject *result;
+
+ _PyBytesWriter_CheckConsistency(writer, str);
+
+ size = _PyBytesWriter_GetSize(writer, str);
+ if (size == 0 && !writer->use_bytearray) {
+ Py_CLEAR(writer->buffer);
+ /* Get the empty byte string singleton */
+ result = PyBytes_FromStringAndSize(NULL, 0);
+ }
+ else if (writer->use_small_buffer) {
+ if (writer->use_bytearray) {
+ result = PyByteArray_FromStringAndSize(writer->small_buffer, size);
+ }
+ else {
+ result = PyBytes_FromStringAndSize(writer->small_buffer, size);
+ }
+ }
+ else {
+ result = writer->buffer;
+ writer->buffer = NULL;
+
+ if (size != writer->allocated) {
+ if (writer->use_bytearray) {
+ if (PyByteArray_Resize(result, size)) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ else {
+ if (_PyBytes_Resize(&result, size)) {
+ assert(result == NULL);
+ return NULL;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+void*
+_PyBytesWriter_WriteBytes(_PyBytesWriter *writer, void *ptr,
+ const void *bytes, Py_ssize_t size)
+{
+ char *str = (char *)ptr;
+
+ str = _PyBytesWriter_Prepare(writer, str, size);
+ if (str == NULL)
+ return NULL;
+
+ memcpy(str, bytes, size);
+ str += size;
+
+ return str;
+}
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 5e8ac59df2..b0ed023056 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -302,34 +302,19 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg)
}
static PyObject *
-method_call(PyObject *func, PyObject *arg, PyObject *kw)
+method_call(PyObject *method, PyObject *args, PyObject *kwargs)
{
- PyObject *self = PyMethod_GET_SELF(func);
- PyObject *result;
+ PyObject *self, *func;
- func = PyMethod_GET_FUNCTION(func);
+ self = PyMethod_GET_SELF(method);
if (self == NULL) {
PyErr_BadInternalCall();
return NULL;
}
- else {
- Py_ssize_t argcount = PyTuple_Size(arg);
- PyObject *newarg = PyTuple_New(argcount + 1);
- int i;
- if (newarg == NULL)
- return NULL;
- Py_INCREF(self);
- PyTuple_SET_ITEM(newarg, 0, self);
- for (i = 0; i < argcount; i++) {
- PyObject *v = PyTuple_GET_ITEM(arg, i);
- Py_XINCREF(v);
- PyTuple_SET_ITEM(newarg, i+1, v);
- }
- arg = newarg;
- }
- result = PyObject_Call((PyObject *)func, arg, kw);
- Py_DECREF(arg);
- return result;
+
+ func = PyMethod_GET_FUNCTION(method);
+
+ return _PyObject_Call_Prepend(func, self, args, kwargs);
}
static PyObject *
diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h
index e87a22127c..c75acb75cf 100644
--- a/Objects/clinic/bytearrayobject.c.h
+++ b/Objects/clinic/bytearrayobject.c.h
@@ -39,45 +39,38 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
}
PyDoc_STRVAR(bytearray_translate__doc__,
-"translate(table, [deletechars])\n"
+"translate($self, table, /, delete=b\'\')\n"
+"--\n"
+"\n"
"Return a copy with each character mapped by the given translation table.\n"
"\n"
" table\n"
" Translation table, which must be a bytes object of length 256.\n"
"\n"
-"All characters occurring in the optional argument deletechars are removed.\n"
+"All characters occurring in the optional argument delete are removed.\n"
"The remaining characters are mapped through the given translation table.");
#define BYTEARRAY_TRANSLATE_METHODDEF \
- {"translate", (PyCFunction)bytearray_translate, METH_VARARGS, bytearray_translate__doc__},
+ {"translate", (PyCFunction)bytearray_translate, METH_FASTCALL, bytearray_translate__doc__},
static PyObject *
bytearray_translate_impl(PyByteArrayObject *self, PyObject *table,
- int group_right_1, PyObject *deletechars);
+ PyObject *deletechars);
static PyObject *
-bytearray_translate(PyByteArrayObject *self, PyObject *args)
+bytearray_translate(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"", "delete", NULL};
+ static _PyArg_Parser _parser = {"O|O:translate", _keywords, 0};
PyObject *table;
- int group_right_1 = 0;
PyObject *deletechars = NULL;
- switch (PyTuple_GET_SIZE(args)) {
- case 1:
- if (!PyArg_ParseTuple(args, "O:translate", &table))
- goto exit;
- break;
- case 2:
- if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars))
- goto exit;
- group_right_1 = 1;
- break;
- default:
- PyErr_SetString(PyExc_TypeError, "bytearray.translate requires 1 to 2 arguments");
- goto exit;
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &table, &deletechars)) {
+ goto exit;
}
- return_value = bytearray_translate_impl(self, table, group_right_1, deletechars);
+ return_value = bytearray_translate_impl(self, table, deletechars);
exit:
return return_value;
@@ -108,17 +101,20 @@ bytearray_maketrans(void *null, PyObject *args)
Py_buffer to = {NULL, NULL};
if (!PyArg_ParseTuple(args, "y*y*:maketrans",
- &frm, &to))
+ &frm, &to)) {
goto exit;
+ }
return_value = bytearray_maketrans_impl(&frm, &to);
exit:
/* Cleanup for frm */
- if (frm.obj)
+ if (frm.obj) {
PyBuffer_Release(&frm);
+ }
/* Cleanup for to */
- if (to.obj)
+ if (to.obj) {
PyBuffer_Release(&to);
+ }
return return_value;
}
@@ -152,17 +148,20 @@ bytearray_replace(PyByteArrayObject *self, PyObject *args)
Py_ssize_t count = -1;
if (!PyArg_ParseTuple(args, "y*y*|n:replace",
- &old, &new, &count))
+ &old, &new, &count)) {
goto exit;
+ }
return_value = bytearray_replace_impl(self, &old, &new, count);
exit:
/* Cleanup for old */
- if (old.obj)
+ if (old.obj) {
PyBuffer_Release(&old);
+ }
/* Cleanup for new */
- if (new.obj)
+ if (new.obj) {
PyBuffer_Release(&new);
+ }
return return_value;
}
@@ -182,23 +181,25 @@ PyDoc_STRVAR(bytearray_split__doc__,
" -1 (the default value) means no limit.");
#define BYTEARRAY_SPLIT_METHODDEF \
- {"split", (PyCFunction)bytearray_split, METH_VARARGS|METH_KEYWORDS, bytearray_split__doc__},
+ {"split", (PyCFunction)bytearray_split, METH_FASTCALL, bytearray_split__doc__},
static PyObject *
bytearray_split_impl(PyByteArrayObject *self, PyObject *sep,
Py_ssize_t maxsplit);
static PyObject *
-bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
+bytearray_split(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"sep", "maxsplit", NULL};
+ static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+ static _PyArg_Parser _parser = {"|On:split", _keywords, 0};
PyObject *sep = Py_None;
Py_ssize_t maxsplit = -1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:split", _keywords,
- &sep, &maxsplit))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &sep, &maxsplit)) {
goto exit;
+ }
return_value = bytearray_split_impl(self, sep, maxsplit);
exit:
@@ -254,23 +255,25 @@ PyDoc_STRVAR(bytearray_rsplit__doc__,
"Splitting is done starting at the end of the bytearray and working to the front.");
#define BYTEARRAY_RSPLIT_METHODDEF \
- {"rsplit", (PyCFunction)bytearray_rsplit, METH_VARARGS|METH_KEYWORDS, bytearray_rsplit__doc__},
+ {"rsplit", (PyCFunction)bytearray_rsplit, METH_FASTCALL, bytearray_rsplit__doc__},
static PyObject *
bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep,
Py_ssize_t maxsplit);
static PyObject *
-bytearray_rsplit(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
+bytearray_rsplit(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"sep", "maxsplit", NULL};
+ static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+ static _PyArg_Parser _parser = {"|On:rsplit", _keywords, 0};
PyObject *sep = Py_None;
Py_ssize_t maxsplit = -1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:rsplit", _keywords,
- &sep, &maxsplit))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &sep, &maxsplit)) {
goto exit;
+ }
return_value = bytearray_rsplit_impl(self, sep, maxsplit);
exit:
@@ -320,8 +323,9 @@ bytearray_insert(PyByteArrayObject *self, PyObject *args)
int item;
if (!PyArg_ParseTuple(args, "nO&:insert",
- &index, _getbytevalue, &item))
+ &index, _getbytevalue, &item)) {
goto exit;
+ }
return_value = bytearray_insert_impl(self, index, item);
exit:
@@ -349,8 +353,9 @@ bytearray_append(PyByteArrayObject *self, PyObject *arg)
PyObject *return_value = NULL;
int item;
- if (!PyArg_Parse(arg, "O&:append", _getbytevalue, &item))
+ if (!PyArg_Parse(arg, "O&:append", _getbytevalue, &item)) {
goto exit;
+ }
return_value = bytearray_append_impl(self, item);
exit:
@@ -394,8 +399,9 @@ bytearray_pop(PyByteArrayObject *self, PyObject *args)
Py_ssize_t index = -1;
if (!PyArg_ParseTuple(args, "|n:pop",
- &index))
+ &index)) {
goto exit;
+ }
return_value = bytearray_pop_impl(self, index);
exit:
@@ -423,8 +429,9 @@ bytearray_remove(PyByteArrayObject *self, PyObject *arg)
PyObject *return_value = NULL;
int value;
- if (!PyArg_Parse(arg, "O&:remove", _getbytevalue, &value))
+ if (!PyArg_Parse(arg, "O&:remove", _getbytevalue, &value)) {
goto exit;
+ }
return_value = bytearray_remove_impl(self, value);
exit:
@@ -453,8 +460,9 @@ bytearray_strip(PyByteArrayObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "strip",
0, 1,
- &bytes))
+ &bytes)) {
goto exit;
+ }
return_value = bytearray_strip_impl(self, bytes);
exit:
@@ -483,8 +491,9 @@ bytearray_lstrip(PyByteArrayObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "lstrip",
0, 1,
- &bytes))
+ &bytes)) {
goto exit;
+ }
return_value = bytearray_lstrip_impl(self, bytes);
exit:
@@ -513,8 +522,9 @@ bytearray_rstrip(PyByteArrayObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "rstrip",
0, 1,
- &bytes))
+ &bytes)) {
goto exit;
+ }
return_value = bytearray_rstrip_impl(self, bytes);
exit:
@@ -537,23 +547,25 @@ PyDoc_STRVAR(bytearray_decode__doc__,
" can handle UnicodeDecodeErrors.");
#define BYTEARRAY_DECODE_METHODDEF \
- {"decode", (PyCFunction)bytearray_decode, METH_VARARGS|METH_KEYWORDS, bytearray_decode__doc__},
+ {"decode", (PyCFunction)bytearray_decode, METH_FASTCALL, bytearray_decode__doc__},
static PyObject *
bytearray_decode_impl(PyByteArrayObject *self, const char *encoding,
const char *errors);
static PyObject *
-bytearray_decode(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
+bytearray_decode(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"encoding", "errors", NULL};
+ static const char * const _keywords[] = {"encoding", "errors", NULL};
+ static _PyArg_Parser _parser = {"|ss:decode", _keywords, 0};
const char *encoding = NULL;
const char *errors = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", _keywords,
- &encoding, &errors))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &encoding, &errors)) {
goto exit;
+ }
return_value = bytearray_decode_impl(self, encoding, errors);
exit:
@@ -583,21 +595,23 @@ PyDoc_STRVAR(bytearray_splitlines__doc__,
"true.");
#define BYTEARRAY_SPLITLINES_METHODDEF \
- {"splitlines", (PyCFunction)bytearray_splitlines, METH_VARARGS|METH_KEYWORDS, bytearray_splitlines__doc__},
+ {"splitlines", (PyCFunction)bytearray_splitlines, METH_FASTCALL, bytearray_splitlines__doc__},
static PyObject *
bytearray_splitlines_impl(PyByteArrayObject *self, int keepends);
static PyObject *
-bytearray_splitlines(PyByteArrayObject *self, PyObject *args, PyObject *kwargs)
+bytearray_splitlines(PyByteArrayObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"keepends", NULL};
+ static const char * const _keywords[] = {"keepends", NULL};
+ static _PyArg_Parser _parser = {"|i:splitlines", _keywords, 0};
int keepends = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:splitlines", _keywords,
- &keepends))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &keepends)) {
goto exit;
+ }
return_value = bytearray_splitlines_impl(self, keepends);
exit:
@@ -617,17 +631,18 @@ PyDoc_STRVAR(bytearray_fromhex__doc__,
{"fromhex", (PyCFunction)bytearray_fromhex, METH_O|METH_CLASS, bytearray_fromhex__doc__},
static PyObject *
-bytearray_fromhex_impl(PyObject*cls, PyObject *string);
+bytearray_fromhex_impl(PyTypeObject *type, PyObject *string);
static PyObject *
-bytearray_fromhex(PyTypeObject *cls, PyObject *arg)
+bytearray_fromhex(PyTypeObject *type, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *string;
- if (!PyArg_Parse(arg, "U:fromhex", &string))
+ if (!PyArg_Parse(arg, "U:fromhex", &string)) {
goto exit;
- return_value = bytearray_fromhex_impl((PyObject*)cls, string);
+ }
+ return_value = bytearray_fromhex_impl(type, string);
exit:
return return_value;
@@ -670,8 +685,9 @@ bytearray_reduce_ex(PyByteArrayObject *self, PyObject *args)
int proto = 0;
if (!PyArg_ParseTuple(args, "|i:__reduce_ex__",
- &proto))
+ &proto)) {
goto exit;
+ }
return_value = bytearray_reduce_ex_impl(self, proto);
exit:
@@ -695,4 +711,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl(self);
}
-/*[clinic end generated code: output=966c15ff22c5e243 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=225342a680391b9c input=a9049054013a1b77]*/
diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h
index 5a1a5e91a6..a11ebd2774 100644
--- a/Objects/clinic/bytesobject.c.h
+++ b/Objects/clinic/bytesobject.c.h
@@ -17,22 +17,24 @@ PyDoc_STRVAR(bytes_split__doc__,
" -1 (the default value) means no limit.");
#define BYTES_SPLIT_METHODDEF \
- {"split", (PyCFunction)bytes_split, METH_VARARGS|METH_KEYWORDS, bytes_split__doc__},
+ {"split", (PyCFunction)bytes_split, METH_FASTCALL, bytes_split__doc__},
static PyObject *
-bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit);
+bytes_split_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit);
static PyObject *
-bytes_split(PyBytesObject*self, PyObject *args, PyObject *kwargs)
+bytes_split(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"sep", "maxsplit", NULL};
+ static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+ static _PyArg_Parser _parser = {"|On:split", _keywords, 0};
PyObject *sep = Py_None;
Py_ssize_t maxsplit = -1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:split", _keywords,
- &sep, &maxsplit))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &sep, &maxsplit)) {
goto exit;
+ }
return_value = bytes_split_impl(self, sep, maxsplit);
exit:
@@ -64,14 +66,16 @@ bytes_partition(PyBytesObject *self, PyObject *arg)
PyObject *return_value = NULL;
Py_buffer sep = {NULL, NULL};
- if (!PyArg_Parse(arg, "y*:partition", &sep))
+ if (!PyArg_Parse(arg, "y*:partition", &sep)) {
goto exit;
+ }
return_value = bytes_partition_impl(self, &sep);
exit:
/* Cleanup for sep */
- if (sep.obj)
+ if (sep.obj) {
PyBuffer_Release(&sep);
+ }
return return_value;
}
@@ -101,14 +105,16 @@ bytes_rpartition(PyBytesObject *self, PyObject *arg)
PyObject *return_value = NULL;
Py_buffer sep = {NULL, NULL};
- if (!PyArg_Parse(arg, "y*:rpartition", &sep))
+ if (!PyArg_Parse(arg, "y*:rpartition", &sep)) {
goto exit;
+ }
return_value = bytes_rpartition_impl(self, &sep);
exit:
/* Cleanup for sep */
- if (sep.obj)
+ if (sep.obj) {
PyBuffer_Release(&sep);
+ }
return return_value;
}
@@ -130,22 +136,24 @@ PyDoc_STRVAR(bytes_rsplit__doc__,
"Splitting is done starting at the end of the bytes and working to the front.");
#define BYTES_RSPLIT_METHODDEF \
- {"rsplit", (PyCFunction)bytes_rsplit, METH_VARARGS|METH_KEYWORDS, bytes_rsplit__doc__},
+ {"rsplit", (PyCFunction)bytes_rsplit, METH_FASTCALL, bytes_rsplit__doc__},
static PyObject *
-bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit);
+bytes_rsplit_impl(PyBytesObject *self, PyObject *sep, Py_ssize_t maxsplit);
static PyObject *
-bytes_rsplit(PyBytesObject*self, PyObject *args, PyObject *kwargs)
+bytes_rsplit(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"sep", "maxsplit", NULL};
+ static const char * const _keywords[] = {"sep", "maxsplit", NULL};
+ static _PyArg_Parser _parser = {"|On:rsplit", _keywords, 0};
PyObject *sep = Py_None;
Py_ssize_t maxsplit = -1;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:rsplit", _keywords,
- &sep, &maxsplit))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &sep, &maxsplit)) {
goto exit;
+ }
return_value = bytes_rsplit_impl(self, sep, maxsplit);
exit:
@@ -189,8 +197,9 @@ bytes_strip(PyBytesObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "strip",
0, 1,
- &bytes))
+ &bytes)) {
goto exit;
+ }
return_value = bytes_strip_impl(self, bytes);
exit:
@@ -219,8 +228,9 @@ bytes_lstrip(PyBytesObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "lstrip",
0, 1,
- &bytes))
+ &bytes)) {
goto exit;
+ }
return_value = bytes_lstrip_impl(self, bytes);
exit:
@@ -249,8 +259,9 @@ bytes_rstrip(PyBytesObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "rstrip",
0, 1,
- &bytes))
+ &bytes)) {
goto exit;
+ }
return_value = bytes_rstrip_impl(self, bytes);
exit:
@@ -258,45 +269,38 @@ exit:
}
PyDoc_STRVAR(bytes_translate__doc__,
-"translate(table, [deletechars])\n"
+"translate($self, table, /, delete=b\'\')\n"
+"--\n"
+"\n"
"Return a copy with each character mapped by the given translation table.\n"
"\n"
" table\n"
" Translation table, which must be a bytes object of length 256.\n"
"\n"
-"All characters occurring in the optional argument deletechars are removed.\n"
+"All characters occurring in the optional argument delete are removed.\n"
"The remaining characters are mapped through the given translation table.");
#define BYTES_TRANSLATE_METHODDEF \
- {"translate", (PyCFunction)bytes_translate, METH_VARARGS, bytes_translate__doc__},
+ {"translate", (PyCFunction)bytes_translate, METH_FASTCALL, bytes_translate__doc__},
static PyObject *
-bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1,
+bytes_translate_impl(PyBytesObject *self, PyObject *table,
PyObject *deletechars);
static PyObject *
-bytes_translate(PyBytesObject *self, PyObject *args)
+bytes_translate(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"", "delete", NULL};
+ static _PyArg_Parser _parser = {"O|O:translate", _keywords, 0};
PyObject *table;
- int group_right_1 = 0;
PyObject *deletechars = NULL;
- switch (PyTuple_GET_SIZE(args)) {
- case 1:
- if (!PyArg_ParseTuple(args, "O:translate", &table))
- goto exit;
- break;
- case 2:
- if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars))
- goto exit;
- group_right_1 = 1;
- break;
- default:
- PyErr_SetString(PyExc_TypeError, "bytes.translate requires 1 to 2 arguments");
- goto exit;
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &table, &deletechars)) {
+ goto exit;
}
- return_value = bytes_translate_impl(self, table, group_right_1, deletechars);
+ return_value = bytes_translate_impl(self, table, deletechars);
exit:
return return_value;
@@ -327,17 +331,20 @@ bytes_maketrans(void *null, PyObject *args)
Py_buffer to = {NULL, NULL};
if (!PyArg_ParseTuple(args, "y*y*:maketrans",
- &frm, &to))
+ &frm, &to)) {
goto exit;
+ }
return_value = bytes_maketrans_impl(&frm, &to);
exit:
/* Cleanup for frm */
- if (frm.obj)
+ if (frm.obj) {
PyBuffer_Release(&frm);
+ }
/* Cleanup for to */
- if (to.obj)
+ if (to.obj) {
PyBuffer_Release(&to);
+ }
return return_value;
}
@@ -359,11 +366,11 @@ PyDoc_STRVAR(bytes_replace__doc__,
{"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__},
static PyObject *
-bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new,
+bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
Py_ssize_t count);
static PyObject *
-bytes_replace(PyBytesObject*self, PyObject *args)
+bytes_replace(PyBytesObject *self, PyObject *args)
{
PyObject *return_value = NULL;
Py_buffer old = {NULL, NULL};
@@ -371,17 +378,20 @@ bytes_replace(PyBytesObject*self, PyObject *args)
Py_ssize_t count = -1;
if (!PyArg_ParseTuple(args, "y*y*|n:replace",
- &old, &new, &count))
+ &old, &new, &count)) {
goto exit;
+ }
return_value = bytes_replace_impl(self, &old, &new, count);
exit:
/* Cleanup for old */
- if (old.obj)
+ if (old.obj) {
PyBuffer_Release(&old);
+ }
/* Cleanup for new */
- if (new.obj)
+ if (new.obj) {
PyBuffer_Release(&new);
+ }
return return_value;
}
@@ -402,23 +412,25 @@ PyDoc_STRVAR(bytes_decode__doc__,
" can handle UnicodeDecodeErrors.");
#define BYTES_DECODE_METHODDEF \
- {"decode", (PyCFunction)bytes_decode, METH_VARARGS|METH_KEYWORDS, bytes_decode__doc__},
+ {"decode", (PyCFunction)bytes_decode, METH_FASTCALL, bytes_decode__doc__},
static PyObject *
-bytes_decode_impl(PyBytesObject*self, const char *encoding,
+bytes_decode_impl(PyBytesObject *self, const char *encoding,
const char *errors);
static PyObject *
-bytes_decode(PyBytesObject*self, PyObject *args, PyObject *kwargs)
+bytes_decode(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"encoding", "errors", NULL};
+ static const char * const _keywords[] = {"encoding", "errors", NULL};
+ static _PyArg_Parser _parser = {"|ss:decode", _keywords, 0};
const char *encoding = NULL;
const char *errors = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", _keywords,
- &encoding, &errors))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &encoding, &errors)) {
goto exit;
+ }
return_value = bytes_decode_impl(self, encoding, errors);
exit:
@@ -435,21 +447,23 @@ PyDoc_STRVAR(bytes_splitlines__doc__,
"true.");
#define BYTES_SPLITLINES_METHODDEF \
- {"splitlines", (PyCFunction)bytes_splitlines, METH_VARARGS|METH_KEYWORDS, bytes_splitlines__doc__},
+ {"splitlines", (PyCFunction)bytes_splitlines, METH_FASTCALL, bytes_splitlines__doc__},
static PyObject *
-bytes_splitlines_impl(PyBytesObject*self, int keepends);
+bytes_splitlines_impl(PyBytesObject *self, int keepends);
static PyObject *
-bytes_splitlines(PyBytesObject*self, PyObject *args, PyObject *kwargs)
+bytes_splitlines(PyBytesObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static char *_keywords[] = {"keepends", NULL};
+ static const char * const _keywords[] = {"keepends", NULL};
+ static _PyArg_Parser _parser = {"|i:splitlines", _keywords, 0};
int keepends = 0;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:splitlines", _keywords,
- &keepends))
+ if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
+ &keepends)) {
goto exit;
+ }
return_value = bytes_splitlines_impl(self, keepends);
exit:
@@ -477,11 +491,12 @@ bytes_fromhex(PyTypeObject *type, PyObject *arg)
PyObject *return_value = NULL;
PyObject *string;
- if (!PyArg_Parse(arg, "U:fromhex", &string))
+ if (!PyArg_Parse(arg, "U:fromhex", &string)) {
goto exit;
+ }
return_value = bytes_fromhex_impl(type, string);
exit:
return return_value;
}
-/*[clinic end generated code: output=bd0ce8f25d7e18f4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=2dc3c93cfd2dc440 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/dictobject.c.h b/Objects/clinic/dictobject.c.h
index 5288b9a8b3..d0cdfc3eda 100644
--- a/Objects/clinic/dictobject.c.h
+++ b/Objects/clinic/dictobject.c.h
@@ -23,8 +23,9 @@ dict_fromkeys(PyTypeObject *type, PyObject *args)
if (!PyArg_UnpackTuple(args, "fromkeys",
1, 2,
- &iterable, &value))
+ &iterable, &value)) {
goto exit;
+ }
return_value = dict_fromkeys_impl(type, iterable, value);
exit:
@@ -39,4 +40,4 @@ PyDoc_STRVAR(dict___contains____doc__,
#define DICT___CONTAINS___METHODDEF \
{"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__},
-/*[clinic end generated code: output=fe74d676332fdba6 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=926326109e3d9839 input=a9049054013a1b77]*/
diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h
index d42a70002a..891e90c312 100644
--- a/Objects/clinic/unicodeobject.c.h
+++ b/Objects/clinic/unicodeobject.c.h
@@ -31,11 +31,12 @@ unicode_maketrans(void *null, PyObject *args)
PyObject *z = NULL;
if (!PyArg_ParseTuple(args, "O|UU:maketrans",
- &x, &y, &z))
+ &x, &y, &z)) {
goto exit;
+ }
return_value = unicode_maketrans_impl(x, y, z);
exit:
return return_value;
}
-/*[clinic end generated code: output=94affdff5b2daff5 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4a86dd108d92d104 input=a9049054013a1b77]*/
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 2f1bef2cd1..0d8a675f9f 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -1,3 +1,5 @@
+#include <stdbool.h>
+
#include "Python.h"
#include "code.h"
#include "structmember.h"
@@ -5,6 +7,12 @@
#define NAME_CHARS \
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
+/* Holder for co_extra information */
+typedef struct {
+ Py_ssize_t ce_size;
+ void **ce_extras;
+} _PyCodeObjectExtra;
+
/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
static int
@@ -136,7 +144,7 @@ PyCode_New(int argcount, int kwonlyargcount,
Py_ssize_t total_args = argcount + kwonlyargcount +
((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars;
- int used_cell2arg = 0;
+ bool used_cell2arg = false;
cell2arg = PyMem_MALLOC(alloc_size);
if (cell2arg == NULL)
return NULL;
@@ -149,7 +157,7 @@ PyCode_New(int argcount, int kwonlyargcount,
PyObject *arg = PyTuple_GET_ITEM(varnames, j);
if (!PyUnicode_Compare(cell, arg)) {
cell2arg[i] = j;
- used_cell2arg = 1;
+ used_cell2arg = true;
break;
}
}
@@ -192,6 +200,7 @@ PyCode_New(int argcount, int kwonlyargcount,
co->co_lnotab = lnotab;
co->co_zombieframe = NULL;
co->co_weakreflist = NULL;
+ co->co_extra = NULL;
return co;
}
@@ -401,6 +410,21 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
static void
code_dealloc(PyCodeObject *co)
{
+ if (co->co_extra != NULL) {
+ PyThreadState *tstate = PyThreadState_Get();
+ _PyCodeObjectExtra *co_extra = co->co_extra;
+
+ for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
+ freefunc free_extra = tstate->co_extra_freefuncs[i];
+
+ if (free_extra != NULL) {
+ free_extra(co_extra->ce_extras[i]);
+ }
+ }
+
+ PyMem_FREE(co->co_extra);
+ }
+
Py_XDECREF(co->co_code);
Py_XDECREF(co->co_consts);
Py_XDECREF(co->co_names);
@@ -734,7 +758,8 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq)
addr += *p++;
if (addr > addrq)
break;
- line += *p++;
+ line += (signed char)*p;
+ p++;
}
return line;
}
@@ -769,17 +794,19 @@ _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
if (addr + *p > lasti)
break;
addr += *p++;
- if (*p)
+ if ((signed char)*p)
bounds->ap_lower = addr;
- line += *p++;
+ line += (signed char)*p;
+ p++;
--size;
}
if (size > 0) {
while (--size >= 0) {
addr += *p++;
- if (*p++)
+ if ((signed char)*p)
break;
+ p++;
}
bounds->ap_upper = addr;
}
@@ -789,3 +816,80 @@ _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
return line;
}
+
+
+int
+_PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
+{
+ assert(*extra == NULL);
+
+ if (!PyCode_Check(code)) {
+ PyErr_BadInternalCall();
+ return -1;
+ }
+
+ PyCodeObject *o = (PyCodeObject*) code;
+ _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra;
+
+
+ if (co_extra == NULL || co_extra->ce_size <= index) {
+ return 0;
+ }
+
+ *extra = co_extra->ce_extras[index];
+ return 0;
+}
+
+
+int
+_PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
+{
+ PyThreadState *tstate = PyThreadState_Get();
+
+ if (!PyCode_Check(code) || index < 0 ||
+ index >= tstate->co_extra_user_count) {
+ PyErr_BadInternalCall();
+ return -1;
+ }
+
+ PyCodeObject *o = (PyCodeObject*) code;
+ _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra;
+
+ if (co_extra == NULL) {
+ o->co_extra = (_PyCodeObjectExtra*) PyMem_Malloc(
+ sizeof(_PyCodeObjectExtra));
+ if (o->co_extra == NULL) {
+ return -1;
+ }
+ co_extra = (_PyCodeObjectExtra *) o->co_extra;
+
+ co_extra->ce_extras = PyMem_Malloc(
+ tstate->co_extra_user_count * sizeof(void*));
+ if (co_extra->ce_extras == NULL) {
+ return -1;
+ }
+
+ co_extra->ce_size = tstate->co_extra_user_count;
+
+ for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
+ co_extra->ce_extras[i] = NULL;
+ }
+ }
+ else if (co_extra->ce_size <= index) {
+ co_extra->ce_extras = PyMem_Realloc(
+ co_extra->ce_extras, tstate->co_extra_user_count * sizeof(void*));
+
+ if (co_extra->ce_extras == NULL) {
+ return -1;
+ }
+
+ co_extra->ce_size = tstate->co_extra_user_count;
+
+ for (Py_ssize_t i = co_extra->ce_size; i < co_extra->ce_size; i++) {
+ co_extra->ce_extras[i] = NULL;
+ }
+ }
+
+ co_extra->ce_extras[index] = extra;
+ return 0;
+}
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index d82c5eb9f1..31e12784cc 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -759,29 +759,12 @@ static PyMemberDef complex_members[] = {
};
static PyObject *
-complex_subtype_from_string(PyTypeObject *type, PyObject *v)
+complex_from_string_inner(const char *s, Py_ssize_t len, void *type)
{
- const char *s, *start;
- char *end;
double x=0.0, y=0.0, z;
int got_bracket=0;
- PyObject *s_buffer = NULL;
- Py_ssize_t len;
-
- if (PyUnicode_Check(v)) {
- s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v);
- if (s_buffer == NULL)
- return NULL;
- s = PyUnicode_AsUTF8AndSize(s_buffer, &len);
- if (s == NULL)
- goto error;
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "complex() argument must be a string or a number, not '%.200s'",
- Py_TYPE(v)->tp_name);
- return NULL;
- }
+ const char *start;
+ char *end;
/* position on first nonblank */
start = s;
@@ -822,7 +805,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (PyErr_ExceptionMatches(PyExc_ValueError))
PyErr_Clear();
else
- goto error;
+ return NULL;
}
if (end != s) {
/* all 4 forms starting with <float> land here */
@@ -835,7 +818,7 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (PyErr_ExceptionMatches(PyExc_ValueError))
PyErr_Clear();
else
- goto error;
+ return NULL;
}
if (end != s)
/* <float><signed-float>j */
@@ -890,18 +873,46 @@ complex_subtype_from_string(PyTypeObject *type, PyObject *v)
if (s-start != len)
goto parse_error;
- Py_XDECREF(s_buffer);
- return complex_subtype_from_doubles(type, x, y);
+ return complex_subtype_from_doubles((PyTypeObject *)type, x, y);
parse_error:
PyErr_SetString(PyExc_ValueError,
"complex() arg is a malformed string");
- error:
- Py_XDECREF(s_buffer);
return NULL;
}
static PyObject *
+complex_subtype_from_string(PyTypeObject *type, PyObject *v)
+{
+ const char *s;
+ PyObject *s_buffer = NULL, *result = NULL;
+ Py_ssize_t len;
+
+ if (PyUnicode_Check(v)) {
+ s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v);
+ if (s_buffer == NULL) {
+ return NULL;
+ }
+ s = PyUnicode_AsUTF8AndSize(s_buffer, &len);
+ if (s == NULL) {
+ goto exit;
+ }
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "complex() argument must be a string or a number, not '%.200s'",
+ Py_TYPE(v)->tp_name);
+ return NULL;
+ }
+
+ result = _Py_string_to_number_with_underscores(s, len, "complex", v, type,
+ complex_from_string_inner);
+ exit:
+ Py_DECREF(s_buffer);
+ return result;
+}
+
+static PyObject *
complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *r, *i, *tmp;
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index da68e3be26..076e741481 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -22,7 +22,7 @@ descr_name(PyDescrObject *descr)
}
static PyObject *
-descr_repr(PyDescrObject *descr, char *format)
+descr_repr(PyDescrObject *descr, const char *format)
{
PyObject *name = NULL;
if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
@@ -213,7 +213,7 @@ static PyObject *
methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
{
Py_ssize_t argc;
- PyObject *self, *func, *result;
+ PyObject *self, *func, *result, **stack;
/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
@@ -242,13 +242,8 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
func = PyCFunction_NewEx(descr->d_method, self, NULL);
if (func == NULL)
return NULL;
- args = PyTuple_GetSlice(args, 1, argc);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObjectWithKeywords(func, args, kwds);
- Py_DECREF(args);
+ stack = &PyTuple_GET_ITEM(args, 1);
+ result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
Py_DECREF(func);
return result;
}
@@ -258,7 +253,7 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds)
{
Py_ssize_t argc;
- PyObject *self, *func, *result;
+ PyObject *self, *func, *result, **stack;
/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
@@ -295,14 +290,9 @@ classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
func = PyCFunction_NewEx(descr->d_method, self, NULL);
if (func == NULL)
return NULL;
- args = PyTuple_GetSlice(args, 1, argc);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObjectWithKeywords(func, args, kwds);
+ stack = &PyTuple_GET_ITEM(args, 1);
+ result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
Py_DECREF(func);
- Py_DECREF(args);
return result;
}
@@ -310,7 +300,7 @@ static PyObject *
wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
{
Py_ssize_t argc;
- PyObject *self, *func, *result;
+ PyObject *self, *func, *result, **stack;
/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
@@ -339,13 +329,9 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
func = PyWrapper_New((PyObject *)descr, self);
if (func == NULL)
return NULL;
- args = PyTuple_GetSlice(args, 1, argc);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObjectWithKeywords(func, args, kwds);
- Py_DECREF(args);
+
+ stack = &PyTuple_GET_ITEM(args, 1);
+ result = _PyObject_FastCallDict(func, stack, argc - 1, kwds);
Py_DECREF(func);
return result;
}
@@ -1033,7 +1019,7 @@ wrapper_dealloc(wrapperobject *wp)
static PyObject *
wrapper_richcompare(PyObject *a, PyObject *b, int op)
{
- Py_intptr_t result;
+ intptr_t result;
PyObject *v;
PyWrapperDescrObject *a_descr, *b_descr;
diff --git a/Objects/dict-common.h b/Objects/dict-common.h
index 2912eb94ea..ce9edabd89 100644
--- a/Objects/dict-common.h
+++ b/Objects/dict-common.h
@@ -8,15 +8,69 @@ typedef struct {
PyObject *me_value; /* This field is only meaningful for combined tables */
} PyDictKeyEntry;
-typedef PyDictKeyEntry *(*dict_lookup_func)
-(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr);
+/* dict_lookup_func() returns index of entry which can be used like DK_ENTRIES(dk)[index].
+ * -1 when no entry found, -3 when compare raises error.
+ */
+typedef Py_ssize_t (*dict_lookup_func)
+(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr,
+ Py_ssize_t *hashpos);
+#define DKIX_EMPTY (-1)
+#define DKIX_DUMMY (-2) /* Used internally */
+#define DKIX_ERROR (-3)
+
+/* See dictobject.c for actual layout of DictKeysObject */
struct _dictkeysobject {
Py_ssize_t dk_refcnt;
+
+ /* Size of the hash table (dk_indices). It must be a power of 2. */
Py_ssize_t dk_size;
+
+ /* Function to lookup in the hash table (dk_indices):
+
+ - lookdict(): general-purpose, and may return DKIX_ERROR if (and
+ only if) a comparison raises an exception.
+
+ - lookdict_unicode(): specialized to Unicode string keys, comparison of
+ which can never raise an exception; that function can never return
+ DKIX_ERROR.
+
+ - lookdict_unicode_nodummy(): similar to lookdict_unicode() but further
+ specialized for Unicode string keys that cannot be the <dummy> value.
+
+ - lookdict_split(): Version of lookdict() for split tables. */
dict_lookup_func dk_lookup;
+
+ /* Number of usable entries in dk_entries. */
Py_ssize_t dk_usable;
- PyDictKeyEntry dk_entries[1];
+
+ /* Number of used entries in dk_entries. */
+ Py_ssize_t dk_nentries;
+
+ /* Actual hash table of dk_size entries. It holds indices in dk_entries,
+ or DKIX_EMPTY(-1) or DKIX_DUMMY(-2).
+
+ Indices must be: 0 <= indice < USABLE_FRACTION(dk_size).
+
+ The size in bytes of an indice depends on dk_size:
+
+ - 1 byte if dk_size <= 0xff (char*)
+ - 2 bytes if dk_size <= 0xffff (int16_t*)
+ - 4 bytes if dk_size <= 0xffffffff (int32_t*)
+ - 8 bytes otherwise (int64_t*)
+
+ Dynamically sized, 8 is minimum. */
+ union {
+ int8_t as_1[8];
+ int16_t as_2[4];
+ int32_t as_4[2];
+#if SIZEOF_VOID_P > 4
+ int64_t as_8[1];
+#endif
+ } dk_indices;
+
+ /* "PyDictKeyEntry dk_entries[dk_usable];" array follows:
+ see the DK_ENTRIES() macro */
};
#endif
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 11c086ffb4..a7b403bcec 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1,4 +1,3 @@
-
/* Dictionary object implementation using a hash table */
/* The distribution includes a separate file, Objects/dictnotes.txt,
@@ -7,68 +6,112 @@
tuning dictionaries, and several ideas for possible optimizations.
*/
+/* PyDictKeysObject
-/*
-There are four kinds of slots in the table:
+This implements the dictionary's hashtable.
-1. Unused. me_key == me_value == NULL
- Does not hold an active (key, value) pair now and never did. Unused can
- transition to Active upon key insertion. This is the only case in which
- me_key is NULL, and is each slot's initial state.
+As of Python 3.6, this is compact and ordered. Basic idea is described here.
+https://morepypy.blogspot.com/2015/01/faster-more-memory-efficient-and-more.html
-2. Active. me_key != NULL and me_key != dummy and me_value != NULL
- Holds an active (key, value) pair. Active can transition to Dummy or
- Pending upon key deletion (for combined and split tables respectively).
- This is the only case in which me_value != NULL.
+layout:
-3. Dummy. me_key == dummy and me_value == NULL
- Previously held an active (key, value) pair, but that was deleted and an
- active pair has not yet overwritten the slot. Dummy can transition to
- Active upon key insertion. Dummy slots cannot be made Unused again
- (cannot have me_key set to NULL), else the probe sequence in case of
- collision would have no way to know they were once active.
++---------------+
+| dk_refcnt |
+| dk_size |
+| dk_lookup |
+| dk_usable |
+| dk_nentries |
++---------------+
+| dk_indices |
+| |
++---------------+
+| dk_entries |
+| |
++---------------+
-4. Pending. Not yet inserted or deleted from a split-table.
- key != NULL, key != dummy and value == NULL
+dk_indices is actual hashtable. It holds index in entries, or DKIX_EMPTY(-1)
+or DKIX_DUMMY(-2).
+Size of indices is dk_size. Type of each index in indices is vary on dk_size:
+* int8 for dk_size <= 128
+* int16 for 256 <= dk_size <= 2**15
+* int32 for 2**16 <= dk_size <= 2**31
+* int64 for 2**32 <= dk_size
+
+dk_entries is array of PyDictKeyEntry. It's size is USABLE_FRACTION(dk_size).
+DK_ENTRIES(dk) can be used to get pointer to entries.
+
+NOTE: Since negative value is used for DKIX_EMPTY and DKIX_DUMMY, type of
+dk_indices entry is signed integer and int16 is used for table which
+dk_size == 256.
+*/
+
+
+/*
The DictObject can be in one of two forms.
+
Either:
A combined table:
ma_values == NULL, dk_refcnt == 1.
Values are stored in the me_value field of the PyDictKeysObject.
- Slot kind 4 is not allowed i.e.
- key != NULL, key != dummy and value == NULL is illegal.
Or:
A split table:
ma_values != NULL, dk_refcnt >= 1
Values are stored in the ma_values array.
- Only string (unicode) keys are allowed, no <dummy> keys are present.
+ Only string (unicode) keys are allowed.
+ All dicts sharing same key must have same insertion order.
+
+There are four kinds of slots in the table (slot is index, and
+DK_ENTRIES(keys)[index] if index >= 0):
+
+1. Unused. index == DKIX_EMPTY
+ Does not hold an active (key, value) pair now and never did. Unused can
+ transition to Active upon key insertion. This is each slot's initial state.
+
+2. Active. index >= 0, me_key != NULL and me_value != NULL
+ Holds an active (key, value) pair. Active can transition to Dummy or
+ Pending upon key deletion (for combined and split tables respectively).
+ This is the only case in which me_value != NULL.
+
+3. Dummy. index == DKIX_DUMMY (combined only)
+ Previously held an active (key, value) pair, but that was deleted and an
+ active pair has not yet overwritten the slot. Dummy can transition to
+ Active upon key insertion. Dummy slots cannot be made Unused again
+ else the probe sequence in case of collision would have no way to know
+ they were once active.
-Note: .popitem() abuses the me_hash field of an Unused or Dummy slot to
-hold a search finger. The me_hash field of Unused or Dummy slots has no
-meaning otherwise. As a consequence of this popitem always converts the dict
-to the combined-table form.
+4. Pending. index >= 0, key != NULL, and value == NULL (split only)
+ Not yet inserted in split-table.
*/
-/* PyDict_MINSIZE_SPLIT is the minimum size of a split dictionary.
- * It must be a power of 2, and at least 4.
- * Resizing of split dictionaries is very rare, so the saving memory is more
- * important than the cost of resizing.
- */
-#define PyDict_MINSIZE_SPLIT 4
+/*
+Preserving insertion order
+
+It's simple for combined table. Since dk_entries is mostly append only, we can
+get insertion order by just iterating dk_entries.
-/* PyDict_MINSIZE_COMBINED is the starting size for any new, non-split dict.
+One exception is .popitem(). It removes last item in dk_entries and decrement
+dk_nentries to achieve amortized O(1). Since there are DKIX_DUMMY remains in
+dk_indices, we can't increment dk_usable even though dk_nentries is
+decremented.
+
+In split table, inserting into pending entry is allowed only for dk_entries[ix]
+where ix == mp->ma_used. Inserting into other index and deleting item cause
+converting the dict to the combined table.
+*/
+
+/* PyDict_MINSIZE is the starting size for any new dict.
* 8 allows dicts with no more than 5 active entries; experiments suggested
* this suffices for the majority of dicts (consisting mostly of usually-small
* dicts created to pass keyword arguments).
* Making this 8, rather than 4 reduces the number of resizes for most
* dictionaries, without any significant extra memory use.
*/
-#define PyDict_MINSIZE_COMBINED 8
+#define PyDict_MINSIZE 8
#include "Python.h"
#include "dict-common.h"
-#include "stringlib/eq.h"
+#include "stringlib/eq.h" /* to get unicode_eq() */
/*[clinic input]
class dict "PyDictObject *" "&PyDict_Type"
@@ -141,8 +184,8 @@ The other half of the strategy is to get the other bits of the hash code
into play. This is done by initializing a (unsigned) vrbl "perturb" to the
full hash code, and changing the recurrence to:
- j = (5*j) + 1 + perturb;
perturb >>= PERTURB_SHIFT;
+ j = (5*j) + 1 + perturb;
use j % 2**i as the next table index;
Now the probe sequence depends (eventually) on every bit in the hash code,
@@ -177,41 +220,38 @@ equally good collision statistics, needed less code & used less memory.
*/
-/* Object used as dummy key to fill deleted entries
- * This could be any unique object,
- * use a custom type in order to minimise coupling.
-*/
-static PyObject _dummy_struct;
-
-#define dummy (&_dummy_struct)
-
-#ifdef Py_REF_DEBUG
-PyObject *
-_PyDict_Dummy(void)
-{
- return dummy;
-}
-#endif
-
/* forward declarations */
-static PyDictKeyEntry *lookdict(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr);
-static PyDictKeyEntry *lookdict_unicode(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr);
-static PyDictKeyEntry *
+static Py_ssize_t lookdict(PyDictObject *mp, PyObject *key,
+ Py_hash_t hash, PyObject ***value_addr,
+ Py_ssize_t *hashpos);
+static Py_ssize_t lookdict_unicode(PyDictObject *mp, PyObject *key,
+ Py_hash_t hash, PyObject ***value_addr,
+ Py_ssize_t *hashpos);
+static Py_ssize_t
lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr);
-static PyDictKeyEntry *lookdict_split(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr);
+ Py_hash_t hash, PyObject ***value_addr,
+ Py_ssize_t *hashpos);
+static Py_ssize_t lookdict_split(PyDictObject *mp, PyObject *key,
+ Py_hash_t hash, PyObject ***value_addr,
+ Py_ssize_t *hashpos);
static int dictresize(PyDictObject *mp, Py_ssize_t minused);
-/* Dictionary reuse scheme to save calls to malloc, free, and memset */
+/*Global counter used to set ma_version_tag field of dictionary.
+ * It is incremented each time that a dictionary is created and each
+ * time that a dictionary is modified. */
+static uint64_t pydict_global_version = 0;
+
+#define DICT_NEXT_VERSION() (++pydict_global_version)
+
+/* Dictionary reuse scheme to save calls to malloc and free */
#ifndef PyDict_MAXFREELIST
#define PyDict_MAXFREELIST 80
#endif
static PyDictObject *free_list[PyDict_MAXFREELIST];
static int numfree = 0;
+static PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
+static int numfreekeys = 0;
#include "clinic/dictobject.c.h"
@@ -219,12 +259,15 @@ int
PyDict_ClearFreeList(void)
{
PyDictObject *op;
- int ret = numfree;
+ int ret = numfree + numfreekeys;
while (numfree) {
op = free_list[--numfree];
assert(PyDict_CheckExact(op));
PyObject_GC_Del(op);
}
+ while (numfreekeys) {
+ PyObject_FREE(keys_free_list[--numfreekeys]);
+ }
return ret;
}
@@ -243,40 +286,116 @@ PyDict_Fini(void)
PyDict_ClearFreeList();
}
+#define DK_SIZE(dk) ((dk)->dk_size)
+#if SIZEOF_VOID_P > 4
+#define DK_IXSIZE(dk) \
+ (DK_SIZE(dk) <= 0xff ? \
+ 1 : DK_SIZE(dk) <= 0xffff ? \
+ 2 : DK_SIZE(dk) <= 0xffffffff ? \
+ 4 : sizeof(int64_t))
+#else
+#define DK_IXSIZE(dk) \
+ (DK_SIZE(dk) <= 0xff ? \
+ 1 : DK_SIZE(dk) <= 0xffff ? \
+ 2 : sizeof(int32_t))
+#endif
+#define DK_ENTRIES(dk) \
+ ((PyDictKeyEntry*)(&(dk)->dk_indices.as_1[DK_SIZE(dk) * DK_IXSIZE(dk)]))
+
#define DK_DEBUG_INCREF _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA
#define DK_DEBUG_DECREF _Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA
#define DK_INCREF(dk) (DK_DEBUG_INCREF ++(dk)->dk_refcnt)
#define DK_DECREF(dk) if (DK_DEBUG_DECREF (--(dk)->dk_refcnt) == 0) free_keys_object(dk)
-#define DK_SIZE(dk) ((dk)->dk_size)
#define DK_MASK(dk) (((dk)->dk_size)-1)
#define IS_POWER_OF_2(x) (((x) & (x-1)) == 0)
+/* lookup indices. returns DKIX_EMPTY, DKIX_DUMMY, or ix >=0 */
+static inline Py_ssize_t
+dk_get_index(PyDictKeysObject *keys, Py_ssize_t i)
+{
+ Py_ssize_t s = DK_SIZE(keys);
+ Py_ssize_t ix;
+
+ if (s <= 0xff) {
+ int8_t *indices = keys->dk_indices.as_1;
+ ix = indices[i];
+ }
+ else if (s <= 0xffff) {
+ int16_t *indices = keys->dk_indices.as_2;
+ ix = indices[i];
+ }
+#if SIZEOF_VOID_P > 4
+ else if (s > 0xffffffff) {
+ int64_t *indices = keys->dk_indices.as_8;
+ ix = indices[i];
+ }
+#endif
+ else {
+ int32_t *indices = keys->dk_indices.as_4;
+ ix = indices[i];
+ }
+ assert(ix >= DKIX_DUMMY);
+ return ix;
+}
+
+/* write to indices. */
+static inline void
+dk_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix)
+{
+ Py_ssize_t s = DK_SIZE(keys);
+
+ assert(ix >= DKIX_DUMMY);
+
+ if (s <= 0xff) {
+ int8_t *indices = keys->dk_indices.as_1;
+ assert(ix <= 0x7f);
+ indices[i] = (char)ix;
+ }
+ else if (s <= 0xffff) {
+ int16_t *indices = keys->dk_indices.as_2;
+ assert(ix <= 0x7fff);
+ indices[i] = (int16_t)ix;
+ }
+#if SIZEOF_VOID_P > 4
+ else if (s > 0xffffffff) {
+ int64_t *indices = keys->dk_indices.as_8;
+ indices[i] = ix;
+ }
+#endif
+ else {
+ int32_t *indices = keys->dk_indices.as_4;
+ assert(ix <= 0x7fffffff);
+ indices[i] = (int32_t)ix;
+ }
+}
+
+
/* USABLE_FRACTION is the maximum dictionary load.
- * Currently set to (2n+1)/3. Increasing this ratio makes dictionaries more
- * dense resulting in more collisions. Decreasing it improves sparseness
- * at the expense of spreading entries over more cache lines and at the
- * cost of total memory consumed.
+ * Increasing this ratio makes dictionaries more dense resulting in more
+ * collisions. Decreasing it improves sparseness at the expense of spreading
+ * indices over more cache lines and at the cost of total memory consumed.
*
* USABLE_FRACTION must obey the following:
* (0 < USABLE_FRACTION(n) < n) for all n >= 2
*
- * USABLE_FRACTION should be very quick to calculate.
- * Fractions around 5/8 to 2/3 seem to work well in practice.
+ * USABLE_FRACTION should be quick to calculate.
+ * Fractions around 1/2 to 2/3 seem to work well in practice.
*/
+#define USABLE_FRACTION(n) (((n) << 1)/3)
-/* Use (2n+1)/3 rather than 2n+3 because: it makes no difference for
- * combined tables (the two fractions round to the same number n < ),
- * but 2*4/3 is 2 whereas (2*4+1)/3 is 3 which potentially saves quite
- * a lot of space for small, split tables */
-#define USABLE_FRACTION(n) ((((n) << 1)+1)/3)
+/* ESTIMATE_SIZE is reverse function of USABLE_FRACTION.
+ * This can be used to reserve enough size to insert n entries without
+ * resizing.
+ */
+#define ESTIMATE_SIZE(n) (((n)*3+1) >> 1)
-/* Alternative fraction that is otherwise close enough to (2n+1)/3 to make
+/* Alternative fraction that is otherwise close enough to 2n/3 to make
* little difference. 8 * 2/3 == 8 * 5/8 == 5. 16 * 2/3 == 16 * 5/8 == 10.
* 32 * 2/3 = 21, 32 * 5/8 = 20.
* Its advantage is that it is faster to compute on machines with slow division.
* #define USABLE_FRACTION(n) (((n) >> 1) + ((n) >> 2) - ((n) >> 3))
-*/
+ */
/* GROWTH_RATE. Growth rate upon hitting maximum load.
* Currently set to used*2 + capacity/2.
@@ -300,61 +419,155 @@ PyDict_Fini(void)
* (which cannot fail and thus can do no allocation).
*/
static PyDictKeysObject empty_keys_struct = {
- 2, /* dk_refcnt 1 for this struct, 1 for dummy_struct */
+ 1, /* dk_refcnt */
1, /* dk_size */
lookdict_split, /* dk_lookup */
0, /* dk_usable (immutable) */
- {
- { 0, 0, 0 } /* dk_entries (empty) */
- }
+ 0, /* dk_nentries */
+ .dk_indices = { .as_1 = {DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY,
+ DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY, DKIX_EMPTY}},
};
static PyObject *empty_values[1] = { NULL };
#define Py_EMPTY_KEYS &empty_keys_struct
+/* Uncomment to check the dict content in _PyDict_CheckConsistency() */
+/* #define DEBUG_PYDICT */
+
+
+#ifdef Py_DEBUG
+static int
+_PyDict_CheckConsistency(PyDictObject *mp)
+{
+ PyDictKeysObject *keys = mp->ma_keys;
+ int splitted = _PyDict_HasSplitTable(mp);
+ Py_ssize_t usable = USABLE_FRACTION(keys->dk_size);
+#ifdef DEBUG_PYDICT
+ PyDictKeyEntry *entries = DK_ENTRIES(keys);
+ Py_ssize_t i;
+#endif
+
+ assert(0 <= mp->ma_used && mp->ma_used <= usable);
+ assert(IS_POWER_OF_2(keys->dk_size));
+ assert(0 <= keys->dk_usable
+ && keys->dk_usable <= usable);
+ assert(0 <= keys->dk_nentries
+ && keys->dk_nentries <= usable);
+ assert(keys->dk_usable + keys->dk_nentries <= usable);
+
+ if (!splitted) {
+ /* combined table */
+ assert(keys->dk_refcnt == 1);
+ }
+
+#ifdef DEBUG_PYDICT
+ for (i=0; i < keys->dk_size; i++) {
+ Py_ssize_t ix = dk_get_index(keys, i);
+ assert(DKIX_DUMMY <= ix && ix <= usable);
+ }
+
+ for (i=0; i < usable; i++) {
+ PyDictKeyEntry *entry = &entries[i];
+ PyObject *key = entry->me_key;
+
+ if (key != NULL) {
+ if (PyUnicode_CheckExact(key)) {
+ Py_hash_t hash = ((PyASCIIObject *)key)->hash;
+ assert(hash != -1);
+ assert(entry->me_hash == hash);
+ }
+ else {
+ /* test_dict fails if PyObject_Hash() is called again */
+ assert(entry->me_hash != -1);
+ }
+ if (!splitted) {
+ assert(entry->me_value != NULL);
+ }
+ }
+
+ if (splitted) {
+ assert(entry->me_value == NULL);
+ }
+ }
+
+ if (splitted) {
+ /* splitted table */
+ for (i=0; i < mp->ma_used; i++) {
+ assert(mp->ma_values[i] != NULL);
+ }
+ }
+#endif
+
+ return 1;
+}
+#endif
+
+
static PyDictKeysObject *new_keys_object(Py_ssize_t size)
{
PyDictKeysObject *dk;
- Py_ssize_t i;
- PyDictKeyEntry *ep0;
+ Py_ssize_t es, usable;
- assert(size >= PyDict_MINSIZE_SPLIT);
+ assert(size >= PyDict_MINSIZE);
assert(IS_POWER_OF_2(size));
- dk = PyMem_MALLOC(sizeof(PyDictKeysObject) +
- sizeof(PyDictKeyEntry) * (size-1));
- if (dk == NULL) {
- PyErr_NoMemory();
- return NULL;
+
+ usable = USABLE_FRACTION(size);
+ if (size <= 0xff) {
+ es = 1;
+ }
+ else if (size <= 0xffff) {
+ es = 2;
+ }
+#if SIZEOF_VOID_P > 4
+ else if (size <= 0xffffffff) {
+ es = 4;
+ }
+#endif
+ else {
+ es = sizeof(Py_ssize_t);
+ }
+
+ if (size == PyDict_MINSIZE && numfreekeys > 0) {
+ dk = keys_free_list[--numfreekeys];
+ }
+ else {
+ dk = PyObject_MALLOC(sizeof(PyDictKeysObject)
+ - Py_MEMBER_SIZE(PyDictKeysObject, dk_indices)
+ + es * size
+ + sizeof(PyDictKeyEntry) * usable);
+ if (dk == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
}
DK_DEBUG_INCREF dk->dk_refcnt = 1;
dk->dk_size = size;
- dk->dk_usable = USABLE_FRACTION(size);
- ep0 = &dk->dk_entries[0];
- /* Hash value of slot 0 is used by popitem, so it must be initialized */
- ep0->me_hash = 0;
- for (i = 0; i < size; i++) {
- ep0[i].me_key = NULL;
- ep0[i].me_value = NULL;
- }
+ dk->dk_usable = usable;
dk->dk_lookup = lookdict_unicode_nodummy;
+ dk->dk_nentries = 0;
+ memset(&dk->dk_indices.as_1[0], 0xff, es * size);
+ memset(DK_ENTRIES(dk), 0, sizeof(PyDictKeyEntry) * usable);
return dk;
}
static void
free_keys_object(PyDictKeysObject *keys)
{
- PyDictKeyEntry *entries = &keys->dk_entries[0];
+ PyDictKeyEntry *entries = DK_ENTRIES(keys);
Py_ssize_t i, n;
- for (i = 0, n = DK_SIZE(keys); i < n; i++) {
+ for (i = 0, n = keys->dk_nentries; i < n; i++) {
Py_XDECREF(entries[i].me_key);
Py_XDECREF(entries[i].me_value);
}
- PyMem_FREE(keys);
+ if (keys->dk_size == PyDict_MINSIZE && numfreekeys < PyDict_MAXFREELIST) {
+ keys_free_list[numfreekeys++] = keys;
+ return;
+ }
+ PyObject_FREE(keys);
}
#define new_values(size) PyMem_NEW(PyObject *, size)
-
#define free_values(values) PyMem_FREE(values)
/* Consumes a reference to the keys object */
@@ -380,6 +593,8 @@ new_dict(PyDictKeysObject *keys, PyObject **values)
mp->ma_keys = keys;
mp->ma_values = values;
mp->ma_used = 0;
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ assert(_PyDict_CheckConsistency(mp));
return (PyObject *)mp;
}
@@ -390,7 +605,7 @@ new_dict_with_shared_keys(PyDictKeysObject *keys)
PyObject **values;
Py_ssize_t i, size;
- size = DK_SIZE(keys);
+ size = USABLE_FRACTION(DK_SIZE(keys));
values = new_values(size);
if (values == NULL) {
DK_DECREF(keys);
@@ -405,12 +620,44 @@ new_dict_with_shared_keys(PyDictKeysObject *keys)
PyObject *
PyDict_New(void)
{
- PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE_COMBINED);
+ PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE);
if (keys == NULL)
return NULL;
return new_dict(keys, NULL);
}
+/* Search index of hash table from offset of entry table */
+static Py_ssize_t
+lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
+{
+ size_t i;
+ size_t mask = DK_MASK(k);
+ Py_ssize_t ix;
+
+ i = (size_t)hash & mask;
+ ix = dk_get_index(k, i);
+ if (ix == index) {
+ return i;
+ }
+ if (ix == DKIX_EMPTY) {
+ return DKIX_EMPTY;
+ }
+
+ for (size_t perturb = hash;;) {
+ perturb >>= PERTURB_SHIFT;
+ i = mask & ((i << 2) + i + perturb + 1);
+ ix = dk_get_index(k, i);
+ if (ix == index) {
+ return i;
+ }
+ if (ix == DKIX_EMPTY) {
+ return DKIX_EMPTY;
+ }
+ }
+ assert(0); /* NOT REACHED */
+ return DKIX_ERROR;
+}
+
/*
The basic lookup function used by all operations.
This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
@@ -426,52 +673,66 @@ The details in this version are due to Tim Peters, building on many past
contributions by Reimer Behrends, Jyrki Alakuijala, Vladimir Marangozov and
Christian Tismer.
-lookdict() is general-purpose, and may return NULL if (and only if) a
-comparison raises an exception (this was new in Python 2.5).
+lookdict() is general-purpose, and may return DKIX_ERROR if (and only if) a
+comparison raises an exception.
lookdict_unicode() below is specialized to string keys, comparison of which can
-never raise an exception; that function can never return NULL.
+never raise an exception; that function can never return DKIX_ERROR.
lookdict_unicode_nodummy is further specialized for string keys that cannot be
the <dummy> value.
-For both, when the key isn't found a PyDictEntry* is returned
-where the key would have been found, *value_addr points to the matching value
-slot.
+For both, when the key isn't found a DKIX_EMPTY is returned. hashpos returns
+where the key index should be inserted.
*/
-static PyDictKeyEntry *
+static Py_ssize_t
lookdict(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr)
+ Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
{
- size_t i;
- size_t perturb;
- PyDictKeyEntry *freeslot;
- size_t mask;
- PyDictKeyEntry *ep0;
- PyDictKeyEntry *ep;
+ size_t i, mask;
+ Py_ssize_t ix, freeslot;
int cmp;
+ PyDictKeysObject *dk;
+ PyDictKeyEntry *ep0, *ep;
PyObject *startkey;
top:
- mask = DK_MASK(mp->ma_keys);
- ep0 = &mp->ma_keys->dk_entries[0];
+ dk = mp->ma_keys;
+ mask = DK_MASK(dk);
+ ep0 = DK_ENTRIES(dk);
i = (size_t)hash & mask;
- ep = &ep0[i];
- if (ep->me_key == NULL || ep->me_key == key) {
- *value_addr = &ep->me_value;
- return ep;
+
+ ix = dk_get_index(dk, i);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ if (ix == DKIX_DUMMY) {
+ freeslot = i;
}
- if (ep->me_key == dummy)
- freeslot = ep;
else {
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL);
+ if (ep->me_key == key) {
+ *value_addr = &ep->me_value;
+ if (hashpos != NULL)
+ *hashpos = i;
+ return ix;
+ }
if (ep->me_hash == hash) {
startkey = ep->me_key;
Py_INCREF(startkey);
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
Py_DECREF(startkey);
- if (cmp < 0)
- return NULL;
- if (ep0 == mp->ma_keys->dk_entries && ep->me_key == startkey) {
+ if (cmp < 0) {
+ *value_addr = NULL;
+ return DKIX_ERROR;
+ }
+ if (dk == mp->ma_keys && ep->me_key == startkey) {
if (cmp > 0) {
*value_addr = &ep->me_value;
- return ep;
+ if (hashpos != NULL)
+ *hashpos = i;
+ return ix;
}
}
else {
@@ -479,40 +740,50 @@ top:
goto top;
}
}
- freeslot = NULL;
+ freeslot = -1;
}
- /* In the loop, me_key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- if (ep->me_key == NULL) {
- if (freeslot == NULL) {
- *value_addr = &ep->me_value;
- return ep;
- } else {
- *value_addr = &freeslot->me_value;
- return freeslot;
+ for (size_t perturb = hash;;) {
+ perturb >>= PERTURB_SHIFT;
+ i = ((i << 2) + i + perturb + 1) & mask;
+ ix = dk_get_index(dk, i);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL) {
+ *hashpos = (freeslot == -1) ? (Py_ssize_t)i : freeslot;
}
+ *value_addr = NULL;
+ return ix;
}
+ if (ix == DKIX_DUMMY) {
+ if (freeslot == -1)
+ freeslot = i;
+ continue;
+ }
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL);
if (ep->me_key == key) {
+ if (hashpos != NULL) {
+ *hashpos = i;
+ }
*value_addr = &ep->me_value;
- return ep;
+ return ix;
}
- if (ep->me_hash == hash && ep->me_key != dummy) {
+ if (ep->me_hash == hash) {
startkey = ep->me_key;
Py_INCREF(startkey);
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
Py_DECREF(startkey);
if (cmp < 0) {
*value_addr = NULL;
- return NULL;
+ return DKIX_ERROR;
}
- if (ep0 == mp->ma_keys->dk_entries && ep->me_key == startkey) {
+ if (dk == mp->ma_keys && ep->me_key == startkey) {
if (cmp > 0) {
+ if (hashpos != NULL) {
+ *hashpos = i;
+ }
*value_addr = &ep->me_value;
- return ep;
+ return ix;
}
}
else {
@@ -520,72 +791,80 @@ top:
goto top;
}
}
- else if (ep->me_key == dummy && freeslot == NULL)
- freeslot = ep;
}
assert(0); /* NOT REACHED */
return 0;
}
/* Specialized version for string-only keys */
-static PyDictKeyEntry *
+static Py_ssize_t
lookdict_unicode(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr)
+ Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
{
size_t i;
- size_t perturb;
- PyDictKeyEntry *freeslot;
size_t mask = DK_MASK(mp->ma_keys);
- PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- PyDictKeyEntry *ep;
+ Py_ssize_t ix, freeslot;
+ PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
+ assert(mp->ma_values == NULL);
/* Make sure this function doesn't have to handle non-unicode keys,
including subclasses of str; e.g., one reason to subclass
unicodes is to override __eq__, and for speed we don't cater to
that here. */
if (!PyUnicode_CheckExact(key)) {
mp->ma_keys->dk_lookup = lookdict;
- return lookdict(mp, key, hash, value_addr);
+ return lookdict(mp, key, hash, value_addr, hashpos);
}
i = (size_t)hash & mask;
- ep = &ep0[i];
- if (ep->me_key == NULL || ep->me_key == key) {
- *value_addr = &ep->me_value;
- return ep;
+ ix = dk_get_index(mp->ma_keys, i);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ if (ix == DKIX_DUMMY) {
+ freeslot = i;
}
- if (ep->me_key == dummy)
- freeslot = ep;
else {
- if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) {
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL);
+ if (ep->me_key == key
+ || (ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
+ if (hashpos != NULL)
+ *hashpos = i;
*value_addr = &ep->me_value;
- return ep;
+ return ix;
}
- freeslot = NULL;
+ freeslot = -1;
}
- /* In the loop, me_key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- if (ep->me_key == NULL) {
- if (freeslot == NULL) {
- *value_addr = &ep->me_value;
- return ep;
- } else {
- *value_addr = &freeslot->me_value;
- return freeslot;
+ for (size_t perturb = hash;;) {
+ perturb >>= PERTURB_SHIFT;
+ i = mask & ((i << 2) + i + perturb + 1);
+ ix = dk_get_index(mp->ma_keys, i);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL) {
+ *hashpos = (freeslot == -1) ? (Py_ssize_t)i : freeslot;
}
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ if (ix == DKIX_DUMMY) {
+ if (freeslot == -1)
+ freeslot = i;
+ continue;
}
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL);
if (ep->me_key == key
- || (ep->me_hash == hash
- && ep->me_key != dummy
- && unicode_eq(ep->me_key, key))) {
+ || (ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
*value_addr = &ep->me_value;
- return ep;
+ if (hashpos != NULL) {
+ *hashpos = i;
+ }
+ return ix;
}
- if (ep->me_key == dummy && freeslot == NULL)
- freeslot = ep;
}
assert(0); /* NOT REACHED */
return 0;
@@ -593,40 +872,63 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
/* Faster version of lookdict_unicode when it is known that no <dummy> keys
* will be present. */
-static PyDictKeyEntry *
+static Py_ssize_t
lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr)
+ Py_hash_t hash, PyObject ***value_addr,
+ Py_ssize_t *hashpos)
{
size_t i;
- size_t perturb;
size_t mask = DK_MASK(mp->ma_keys);
- PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- PyDictKeyEntry *ep;
+ Py_ssize_t ix;
+ PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
+ assert(mp->ma_values == NULL);
/* Make sure this function doesn't have to handle non-unicode keys,
including subclasses of str; e.g., one reason to subclass
unicodes is to override __eq__, and for speed we don't cater to
that here. */
if (!PyUnicode_CheckExact(key)) {
mp->ma_keys->dk_lookup = lookdict;
- return lookdict(mp, key, hash, value_addr);
+ return lookdict(mp, key, hash, value_addr, hashpos);
}
i = (size_t)hash & mask;
- ep = &ep0[i];
- assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key));
- if (ep->me_key == NULL || ep->me_key == key ||
+ ix = dk_get_index(mp->ma_keys, i);
+ assert (ix != DKIX_DUMMY);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL);
+ assert(PyUnicode_CheckExact(ep->me_key));
+ if (ep->me_key == key ||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
+ if (hashpos != NULL)
+ *hashpos = i;
*value_addr = &ep->me_value;
- return ep;
- }
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key));
- if (ep->me_key == NULL || ep->me_key == key ||
+ return ix;
+ }
+ for (size_t perturb = hash;;) {
+ perturb >>= PERTURB_SHIFT;
+ i = mask & ((i << 2) + i + perturb + 1);
+ ix = dk_get_index(mp->ma_keys, i);
+ assert (ix != DKIX_DUMMY);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
+ if (ep->me_key == key ||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
+ if (hashpos != NULL)
+ *hashpos = i;
*value_addr = &ep->me_value;
- return ep;
+ return ix;
}
}
assert(0); /* NOT REACHED */
@@ -638,39 +940,62 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
* Split tables only contain unicode keys and no dummy keys,
* so algorithm is the same as lookdict_unicode_nodummy.
*/
-static PyDictKeyEntry *
+static Py_ssize_t
lookdict_split(PyDictObject *mp, PyObject *key,
- Py_hash_t hash, PyObject ***value_addr)
+ Py_hash_t hash, PyObject ***value_addr, Py_ssize_t *hashpos)
{
size_t i;
- size_t perturb;
size_t mask = DK_MASK(mp->ma_keys);
- PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- PyDictKeyEntry *ep;
+ Py_ssize_t ix;
+ PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
+ /* mp must split table */
+ assert(mp->ma_values != NULL);
if (!PyUnicode_CheckExact(key)) {
- ep = lookdict(mp, key, hash, value_addr);
- /* lookdict expects a combined-table, so fix value_addr */
- i = ep - ep0;
- *value_addr = &mp->ma_values[i];
- return ep;
+ ix = lookdict(mp, key, hash, value_addr, hashpos);
+ if (ix >= 0) {
+ *value_addr = &mp->ma_values[ix];
+ }
+ return ix;
}
+
i = (size_t)hash & mask;
- ep = &ep0[i];
- assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key));
- if (ep->me_key == NULL || ep->me_key == key ||
+ ix = dk_get_index(mp->ma_keys, i);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ assert(ix >= 0);
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
+ if (ep->me_key == key ||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
- *value_addr = &mp->ma_values[i];
- return ep;
- }
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- assert(ep->me_key == NULL || PyUnicode_CheckExact(ep->me_key));
- if (ep->me_key == NULL || ep->me_key == key ||
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = &mp->ma_values[ix];
+ return ix;
+ }
+ for (size_t perturb = hash;;) {
+ perturb >>= PERTURB_SHIFT;
+ i = mask & ((i << 2) + i + perturb + 1);
+ ix = dk_get_index(mp->ma_keys, i);
+ if (ix == DKIX_EMPTY) {
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = NULL;
+ return DKIX_EMPTY;
+ }
+ assert(ix >= 0);
+ ep = &ep0[ix];
+ assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
+ if (ep->me_key == key ||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
- *value_addr = &mp->ma_values[i & mask];
- return ep;
+ if (hashpos != NULL)
+ *hashpos = i;
+ *value_addr = &mp->ma_values[ix];
+ return ix;
}
}
assert(0); /* NOT REACHED */
@@ -707,27 +1032,27 @@ _PyDict_MaybeUntrack(PyObject *op)
{
PyDictObject *mp;
PyObject *value;
- Py_ssize_t i, size;
+ Py_ssize_t i, numentries;
+ PyDictKeyEntry *ep0;
if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
return;
mp = (PyDictObject *) op;
- size = DK_SIZE(mp->ma_keys);
+ ep0 = DK_ENTRIES(mp->ma_keys);
+ numentries = mp->ma_keys->dk_nentries;
if (_PyDict_HasSplitTable(mp)) {
- for (i = 0; i < size; i++) {
+ for (i = 0; i < numentries; i++) {
if ((value = mp->ma_values[i]) == NULL)
continue;
if (_PyObject_GC_MAY_BE_TRACKED(value)) {
- assert(!_PyObject_GC_MAY_BE_TRACKED(
- mp->ma_keys->dk_entries[i].me_key));
+ assert(!_PyObject_GC_MAY_BE_TRACKED(ep0[i].me_key));
return;
}
}
}
else {
- PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- for (i = 0; i < size; i++) {
+ for (i = 0; i < numentries; i++) {
if ((value = ep0[i].me_value) == NULL)
continue;
if (_PyObject_GC_MAY_BE_TRACKED(value) ||
@@ -739,33 +1064,35 @@ _PyDict_MaybeUntrack(PyObject *op)
}
/* Internal function to find slot for an item from its hash
- * when it is known that the key is not present in the dict.
- */
-static PyDictKeyEntry *
+ when it is known that the key is not present in the dict.
+
+ The dict must be combined. */
+static void
find_empty_slot(PyDictObject *mp, PyObject *key, Py_hash_t hash,
- PyObject ***value_addr)
+ PyObject ***value_addr, Py_ssize_t *hashpos)
{
size_t i;
- size_t perturb;
size_t mask = DK_MASK(mp->ma_keys);
- PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- PyDictKeyEntry *ep;
+ Py_ssize_t ix;
+ PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
+ assert(!_PyDict_HasSplitTable(mp));
+ assert(hashpos != NULL);
assert(key != NULL);
+
if (!PyUnicode_CheckExact(key))
mp->ma_keys->dk_lookup = lookdict;
i = hash & mask;
- ep = &ep0[i];
- for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) {
+ ix = dk_get_index(mp->ma_keys, i);
+ for (size_t perturb = hash; ix != DKIX_EMPTY;) {
+ perturb >>= PERTURB_SHIFT;
i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
+ ix = dk_get_index(mp->ma_keys, i & mask);
}
+ ep = &ep0[mp->ma_keys->dk_nentries];
+ *hashpos = i & mask;
assert(ep->me_value == NULL);
- if (mp->ma_values)
- *value_addr = &mp->ma_values[i & mask];
- else
- *value_addr = &ep->me_value;
- return ep;
+ *value_addr = &ep->me_value;
}
static int
@@ -784,58 +1111,88 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
{
PyObject *old_value;
PyObject **value_addr;
- PyDictKeyEntry *ep;
- assert(key != dummy);
+ PyDictKeyEntry *ep, *ep0;
+ Py_ssize_t hashpos, ix;
if (mp->ma_values != NULL && !PyUnicode_CheckExact(key)) {
if (insertion_resize(mp) < 0)
return -1;
}
- ep = mp->ma_keys->dk_lookup(mp, key, hash, &value_addr);
- if (ep == NULL) {
+ ix = mp->ma_keys->dk_lookup(mp, key, hash, &value_addr, &hashpos);
+ if (ix == DKIX_ERROR) {
return -1;
}
+
assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);
Py_INCREF(value);
MAINTAIN_TRACKING(mp, key, value);
- old_value = *value_addr;
- if (old_value != NULL) {
- assert(ep->me_key != NULL && ep->me_key != dummy);
- *value_addr = value;
- Py_DECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
+
+ /* When insertion order is different from shared key, we can't share
+ * the key anymore. Convert this instance to combine table.
+ */
+ if (_PyDict_HasSplitTable(mp) &&
+ ((ix >= 0 && *value_addr == NULL && mp->ma_used != ix) ||
+ (ix == DKIX_EMPTY && mp->ma_used != mp->ma_keys->dk_nentries))) {
+ if (insertion_resize(mp) < 0) {
+ Py_DECREF(value);
+ return -1;
+ }
+ find_empty_slot(mp, key, hash, &value_addr, &hashpos);
+ ix = DKIX_EMPTY;
}
- else {
- if (ep->me_key == NULL) {
- Py_INCREF(key);
- if (mp->ma_keys->dk_usable <= 0) {
- /* Need to resize. */
- if (insertion_resize(mp) < 0) {
- Py_DECREF(key);
- Py_DECREF(value);
- return -1;
- }
- ep = find_empty_slot(mp, key, hash, &value_addr);
+
+ if (ix == DKIX_EMPTY) {
+ /* Insert into new slot. */
+ if (mp->ma_keys->dk_usable <= 0) {
+ /* Need to resize. */
+ if (insertion_resize(mp) < 0) {
+ Py_DECREF(value);
+ return -1;
}
- mp->ma_keys->dk_usable--;
- assert(mp->ma_keys->dk_usable >= 0);
- ep->me_key = key;
- ep->me_hash = hash;
+ find_empty_slot(mp, key, hash, &value_addr, &hashpos);
+ }
+ ep0 = DK_ENTRIES(mp->ma_keys);
+ ep = &ep0[mp->ma_keys->dk_nentries];
+ dk_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
+ Py_INCREF(key);
+ ep->me_key = key;
+ ep->me_hash = hash;
+ if (mp->ma_values) {
+ assert (mp->ma_values[mp->ma_keys->dk_nentries] == NULL);
+ mp->ma_values[mp->ma_keys->dk_nentries] = value;
}
else {
- if (ep->me_key == dummy) {
- Py_INCREF(key);
- ep->me_key = key;
- ep->me_hash = hash;
- Py_DECREF(dummy);
- } else {
- assert(_PyDict_HasSplitTable(mp));
- }
+ ep->me_value = value;
}
mp->ma_used++;
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ mp->ma_keys->dk_usable--;
+ mp->ma_keys->dk_nentries++;
+ assert(mp->ma_keys->dk_usable >= 0);
+ assert(_PyDict_CheckConsistency(mp));
+ return 0;
+ }
+
+ assert(value_addr != NULL);
+
+ old_value = *value_addr;
+ if (old_value != NULL) {
*value_addr = value;
- assert(ep->me_key != NULL && ep->me_key != dummy);
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ assert(_PyDict_CheckConsistency(mp));
+
+ Py_DECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
+ return 0;
}
+
+ /* pending state */
+ assert(_PyDict_HasSplitTable(mp));
+ assert(ix == mp->ma_used);
+ *value_addr = value;
+ mp->ma_used++;
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ assert(_PyDict_CheckConsistency(mp));
return 0;
}
@@ -854,24 +1211,24 @@ insertdict_clean(PyDictObject *mp, PyObject *key, Py_hash_t hash,
PyObject *value)
{
size_t i;
- size_t perturb;
PyDictKeysObject *k = mp->ma_keys;
size_t mask = (size_t)DK_SIZE(k)-1;
- PyDictKeyEntry *ep0 = &k->dk_entries[0];
+ PyDictKeyEntry *ep0 = DK_ENTRIES(mp->ma_keys);
PyDictKeyEntry *ep;
assert(k->dk_lookup != NULL);
assert(value != NULL);
assert(key != NULL);
- assert(key != dummy);
assert(PyUnicode_CheckExact(key) || k->dk_lookup == lookdict);
i = hash & mask;
- ep = &ep0[i];
- for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
+ for (size_t perturb = hash; dk_get_index(k, i) != DKIX_EMPTY;) {
+ perturb >>= PERTURB_SHIFT;
+ i = mask & ((i << 2) + i + perturb + 1);
}
+ ep = &ep0[k->dk_nentries];
assert(ep->me_value == NULL);
+ dk_set_index(k, i, k->dk_nentries);
+ k->dk_nentries++;
ep->me_key = key;
ep->me_hash = hash;
ep->me_value = value;
@@ -888,16 +1245,16 @@ After resizing a table is always combined,
but can be resplit by make_keys_shared().
*/
static int
-dictresize(PyDictObject *mp, Py_ssize_t minused)
+dictresize(PyDictObject *mp, Py_ssize_t minsize)
{
- Py_ssize_t newsize;
+ Py_ssize_t i, newsize;
PyDictKeysObject *oldkeys;
PyObject **oldvalues;
- Py_ssize_t i, oldsize;
+ PyDictKeyEntry *ep0;
-/* Find the smallest table size > minused. */
- for (newsize = PyDict_MINSIZE_COMBINED;
- newsize <= minused && newsize > 0;
+ /* Find the smallest table size > minused. */
+ for (newsize = PyDict_MINSIZE;
+ newsize < minsize && newsize > 0;
newsize <<= 1)
;
if (newsize <= 0) {
@@ -912,56 +1269,45 @@ dictresize(PyDictObject *mp, Py_ssize_t minused)
mp->ma_keys = oldkeys;
return -1;
}
+ // New table must be large enough.
+ assert(mp->ma_keys->dk_usable >= mp->ma_used);
if (oldkeys->dk_lookup == lookdict)
mp->ma_keys->dk_lookup = lookdict;
- oldsize = DK_SIZE(oldkeys);
mp->ma_values = NULL;
- /* If empty then nothing to copy so just return */
- if (oldsize == 1) {
- assert(oldkeys == Py_EMPTY_KEYS);
- DK_DECREF(oldkeys);
- return 0;
- }
+ ep0 = DK_ENTRIES(oldkeys);
/* Main loop below assumes we can transfer refcount to new keys
* and that value is stored in me_value.
* Increment ref-counts and copy values here to compensate
* This (resizing a split table) should be relatively rare */
if (oldvalues != NULL) {
- for (i = 0; i < oldsize; i++) {
+ for (i = 0; i < oldkeys->dk_nentries; i++) {
if (oldvalues[i] != NULL) {
- Py_INCREF(oldkeys->dk_entries[i].me_key);
- oldkeys->dk_entries[i].me_value = oldvalues[i];
+ Py_INCREF(ep0[i].me_key);
+ ep0[i].me_value = oldvalues[i];
}
}
}
/* Main loop */
- for (i = 0; i < oldsize; i++) {
- PyDictKeyEntry *ep = &oldkeys->dk_entries[i];
+ for (i = 0; i < oldkeys->dk_nentries; i++) {
+ PyDictKeyEntry *ep = &ep0[i];
if (ep->me_value != NULL) {
- assert(ep->me_key != dummy);
insertdict_clean(mp, ep->me_key, ep->me_hash, ep->me_value);
}
}
mp->ma_keys->dk_usable -= mp->ma_used;
if (oldvalues != NULL) {
/* NULL out me_value slot in oldkeys, in case it was shared */
- for (i = 0; i < oldsize; i++)
- oldkeys->dk_entries[i].me_value = NULL;
- assert(oldvalues != empty_values);
- free_values(oldvalues);
+ for (i = 0; i < oldkeys->dk_nentries; i++)
+ ep0[i].me_value = NULL;
DK_DECREF(oldkeys);
+ if (oldvalues != empty_values) {
+ free_values(oldvalues);
+ }
}
else {
assert(oldkeys->dk_lookup != lookdict_split);
- if (oldkeys->dk_lookup != lookdict_unicode_nodummy) {
- PyDictKeyEntry *ep0 = &oldkeys->dk_entries[0];
- for (i = 0; i < oldsize; i++) {
- if (ep0[i].me_key == dummy)
- Py_DECREF(dummy);
- }
- }
assert(oldkeys->dk_refcnt == 1);
- DK_DEBUG_DECREF PyMem_FREE(oldkeys);
+ DK_DEBUG_DECREF PyObject_FREE(oldkeys);
}
return 0;
}
@@ -985,16 +1331,14 @@ make_keys_shared(PyObject *op)
return NULL;
}
else if (mp->ma_keys->dk_lookup == lookdict_unicode) {
- /* Remove dummy keys
- * -1 is required since dictresize() uses key size > minused
- */
- if (dictresize(mp, DK_SIZE(mp->ma_keys) - 1))
+ /* Remove dummy keys */
+ if (dictresize(mp, DK_SIZE(mp->ma_keys)))
return NULL;
}
assert(mp->ma_keys->dk_lookup == lookdict_unicode_nodummy);
/* Copy values into a new array */
- ep0 = &mp->ma_keys->dk_entries[0];
- size = DK_SIZE(mp->ma_keys);
+ ep0 = DK_ENTRIES(mp->ma_keys);
+ size = USABLE_FRACTION(DK_SIZE(mp->ma_keys));
values = new_values(size);
if (values == NULL) {
PyErr_SetString(PyExc_MemoryError,
@@ -1015,12 +1359,26 @@ make_keys_shared(PyObject *op)
PyObject *
_PyDict_NewPresized(Py_ssize_t minused)
{
+ const Py_ssize_t max_presize = 128 * 1024;
Py_ssize_t newsize;
PyDictKeysObject *new_keys;
- for (newsize = PyDict_MINSIZE_COMBINED;
- newsize <= minused && newsize > 0;
- newsize <<= 1)
- ;
+
+ /* There are no strict guarantee that returned dict can contain minused
+ * items without resize. So we create medium size dict instead of very
+ * large dict or MemoryError.
+ */
+ if (minused > USABLE_FRACTION(max_presize)) {
+ newsize = max_presize;
+ }
+ else {
+ Py_ssize_t minsize = ESTIMATE_SIZE(minused);
+ newsize = PyDict_MINSIZE;
+ while (newsize < minsize) {
+ newsize <<= 1;
+ }
+ }
+ assert(IS_POWER_OF_2(newsize));
+
new_keys = new_keys_object(newsize);
if (new_keys == NULL)
return NULL;
@@ -1041,8 +1399,8 @@ PyObject *
PyDict_GetItem(PyObject *op, PyObject *key)
{
Py_hash_t hash;
+ Py_ssize_t ix;
PyDictObject *mp = (PyDictObject *)op;
- PyDictKeyEntry *ep;
PyThreadState *tstate;
PyObject **value_addr;
@@ -1068,15 +1426,15 @@ PyDict_GetItem(PyObject *op, PyObject *key)
/* preserve the existing exception */
PyObject *err_type, *err_value, *err_tb;
PyErr_Fetch(&err_type, &err_value, &err_tb);
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
/* ignore errors */
PyErr_Restore(err_type, err_value, err_tb);
- if (ep == NULL)
+ if (ix < 0)
return NULL;
}
else {
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL) {
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix < 0) {
PyErr_Clear();
return NULL;
}
@@ -1084,39 +1442,25 @@ PyDict_GetItem(PyObject *op, PyObject *key)
return *value_addr;
}
+/* Same as PyDict_GetItemWithError() but with hash supplied by caller.
+ This returns NULL *with* an exception set if an exception occurred.
+ It returns NULL *without* an exception set if the key wasn't present.
+*/
PyObject *
_PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
{
+ Py_ssize_t ix;
PyDictObject *mp = (PyDictObject *)op;
- PyDictKeyEntry *ep;
- PyThreadState *tstate;
PyObject **value_addr;
- if (!PyDict_Check(op))
+ if (!PyDict_Check(op)) {
+ PyErr_BadInternalCall();
return NULL;
-
- /* We can arrive here with a NULL tstate during initialization: try
- running "python -Wi" for an example related to string interning.
- Let's just hope that no exception occurs then... This must be
- _PyThreadState_Current and not PyThreadState_GET() because in debug
- mode, the latter complains if tstate is NULL. */
- tstate = _PyThreadState_UncheckedGet();
- if (tstate != NULL && tstate->curexc_type != NULL) {
- /* preserve the existing exception */
- PyObject *err_type, *err_value, *err_tb;
- PyErr_Fetch(&err_type, &err_value, &err_tb);
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- /* ignore errors */
- PyErr_Restore(err_type, err_value, err_tb);
- if (ep == NULL)
- return NULL;
}
- else {
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL) {
- PyErr_Clear();
- return NULL;
- }
+
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix < 0) {
+ return NULL;
}
return *value_addr;
}
@@ -1128,9 +1472,9 @@ _PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
PyObject *
PyDict_GetItemWithError(PyObject *op, PyObject *key)
{
+ Py_ssize_t ix;
Py_hash_t hash;
PyDictObject*mp = (PyDictObject *)op;
- PyDictKeyEntry *ep;
PyObject **value_addr;
if (!PyDict_Check(op)) {
@@ -1146,8 +1490,8 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key)
}
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix < 0)
return NULL;
return *value_addr;
}
@@ -1162,39 +1506,40 @@ _PyDict_GetItemIdWithError(PyObject *dp, struct _Py_Identifier *key)
return PyDict_GetItemWithError(dp, kv);
}
-/* Fast version of global value lookup.
+/* Fast version of global value lookup (LOAD_GLOBAL).
* Lookup in globals, then builtins.
+ *
+ * Raise an exception and return NULL if an error occurred (ex: computing the
+ * key hash failed, key comparison failed, ...). Return NULL if the key doesn't
+ * exist. Return the value if the key exists.
*/
PyObject *
_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
{
- PyObject *x;
- if (PyUnicode_CheckExact(key)) {
- PyObject **value_addr;
- Py_hash_t hash = ((PyASCIIObject *)key)->hash;
- if (hash != -1) {
- PyDictKeyEntry *e;
- e = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr);
- if (e == NULL) {
- return NULL;
- }
- x = *value_addr;
- if (x != NULL)
- return x;
- e = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr);
- if (e == NULL) {
- return NULL;
- }
- x = *value_addr;
- return x;
- }
+ Py_ssize_t ix;
+ Py_hash_t hash;
+ PyObject **value_addr;
+
+ if (!PyUnicode_CheckExact(key) ||
+ (hash = ((PyASCIIObject *) key)->hash) == -1)
+ {
+ hash = PyObject_Hash(key);
+ if (hash == -1)
+ return NULL;
}
- x = PyDict_GetItemWithError((PyObject *)globals, key);
- if (x != NULL)
- return x;
- if (PyErr_Occurred())
+
+ /* namespace 1: globals */
+ ix = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr, NULL);
+ if (ix == DKIX_ERROR)
return NULL;
- return PyDict_GetItemWithError((PyObject *)builtins, key);
+ if (ix != DKIX_EMPTY && *value_addr != NULL)
+ return *value_addr;
+
+ /* namespace 2: builtins */
+ ix = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr, NULL);
+ if (ix < 0)
+ return NULL;
+ return *value_addr;
}
/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
@@ -1247,36 +1592,33 @@ _PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value,
}
static int
-delitem_common(PyDictObject *mp, PyDictKeyEntry *ep, PyObject **value_addr)
+delitem_common(PyDictObject *mp, Py_ssize_t hashpos, Py_ssize_t ix,
+ PyObject **value_addr)
{
PyObject *old_key, *old_value;
+ PyDictKeyEntry *ep;
old_value = *value_addr;
+ assert(old_value != NULL);
*value_addr = NULL;
mp->ma_used--;
- if (!_PyDict_HasSplitTable(mp)) {
- ENSURE_ALLOWS_DELETIONS(mp);
- old_key = ep->me_key;
- Py_INCREF(dummy);
- ep->me_key = dummy;
- Py_DECREF(old_key);
- }
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ ep = &DK_ENTRIES(mp->ma_keys)[ix];
+ dk_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
+ ENSURE_ALLOWS_DELETIONS(mp);
+ old_key = ep->me_key;
+ ep->me_key = NULL;
+ Py_DECREF(old_key);
Py_DECREF(old_value);
+
+ assert(_PyDict_CheckConsistency(mp));
return 0;
}
int
PyDict_DelItem(PyObject *op, PyObject *key)
{
- PyDictObject *mp;
Py_hash_t hash;
- PyDictKeyEntry *ep;
- PyObject **value_addr;
-
- if (!PyDict_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
assert(key);
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyASCIIObject *) key)->hash) == -1) {
@@ -1284,22 +1626,15 @@ PyDict_DelItem(PyObject *op, PyObject *key)
if (hash == -1)
return -1;
}
- mp = (PyDictObject *)op;
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
- return -1;
- if (*value_addr == NULL) {
- _PyErr_SetKeyError(key);
- return -1;
- }
- return delitem_common(mp, ep, value_addr);
+
+ return _PyDict_DelItem_KnownHash(op, key, hash);
}
int
_PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
{
+ Py_ssize_t hashpos, ix;
PyDictObject *mp;
- PyDictKeyEntry *ep;
PyObject **value_addr;
if (!PyDict_Check(op)) {
@@ -1309,23 +1644,37 @@ _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
assert(key);
assert(hash != -1);
mp = (PyDictObject *)op;
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ if (ix == DKIX_ERROR)
return -1;
- if (*value_addr == NULL) {
+ if (ix == DKIX_EMPTY || *value_addr == NULL) {
_PyErr_SetKeyError(key);
return -1;
}
- return delitem_common(mp, ep, value_addr);
+ assert(dk_get_index(mp->ma_keys, hashpos) == ix);
+
+ // Split table doesn't allow deletion. Combine it.
+ if (_PyDict_HasSplitTable(mp)) {
+ if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
+ return -1;
+ }
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ assert(ix >= 0);
+ }
+ return delitem_common(mp, hashpos, ix, value_addr);
}
+/* This function promises that the predicate -> deletion sequence is atomic
+ * (i.e. protected by the GIL), assuming the predicate itself doesn't
+ * release the GIL.
+ */
int
_PyDict_DelItemIf(PyObject *op, PyObject *key,
int (*predicate)(PyObject *value))
{
+ Py_ssize_t hashpos, ix;
PyDictObject *mp;
Py_hash_t hash;
- PyDictKeyEntry *ep;
PyObject **value_addr;
int res;
@@ -1338,18 +1687,29 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key,
if (hash == -1)
return -1;
mp = (PyDictObject *)op;
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ if (ix == DKIX_ERROR)
return -1;
- if (*value_addr == NULL) {
+ if (ix == DKIX_EMPTY || *value_addr == NULL) {
_PyErr_SetKeyError(key);
return -1;
}
+ assert(dk_get_index(mp->ma_keys, hashpos) == ix);
+
+ // Split table doesn't allow deletion. Combine it.
+ if (_PyDict_HasSplitTable(mp)) {
+ if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
+ return -1;
+ }
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ assert(ix >= 0);
+ }
+
res = predicate(*value_addr);
if (res == -1)
return -1;
if (res > 0)
- return delitem_common(mp, ep, value_addr);
+ return delitem_common(mp, hashpos, ix, value_addr);
else
return 0;
}
@@ -1375,9 +1735,10 @@ PyDict_Clear(PyObject *op)
mp->ma_keys = Py_EMPTY_KEYS;
mp->ma_values = empty_values;
mp->ma_used = 0;
+ mp->ma_version_tag = DICT_NEXT_VERSION();
/* ...then clear the keys and values */
if (oldvalues != NULL) {
- n = DK_SIZE(oldkeys);
+ n = oldkeys->dk_nentries;
for (i = 0; i < n; i++)
Py_CLEAR(oldvalues[i]);
free_values(oldvalues);
@@ -1387,42 +1748,59 @@ PyDict_Clear(PyObject *op)
assert(oldkeys->dk_refcnt == 1);
DK_DECREF(oldkeys);
}
+ assert(_PyDict_CheckConsistency(mp));
}
-/* Returns -1 if no more items (or op is not a dict),
- * index of item otherwise. Stores value in pvalue
+/* Internal version of PyDict_Next that returns a hash value in addition
+ * to the key and value.
+ * Return 1 on success, return 0 when the reached the end of the dictionary
+ * (or if op is not a dictionary)
*/
-Py_LOCAL_INLINE(Py_ssize_t)
-dict_next(PyObject *op, Py_ssize_t i, PyObject **pvalue)
+int
+_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
+ PyObject **pvalue, Py_hash_t *phash)
{
- Py_ssize_t mask, offset;
+ Py_ssize_t i, n;
PyDictObject *mp;
- PyObject **value_ptr;
-
+ PyDictKeyEntry *entry_ptr;
+ PyObject *value;
if (!PyDict_Check(op))
- return -1;
+ return 0;
mp = (PyDictObject *)op;
- if (i < 0)
- return -1;
+ i = *ppos;
+ n = mp->ma_keys->dk_nentries;
+ if ((size_t)i >= (size_t)n)
+ return 0;
if (mp->ma_values) {
- value_ptr = &mp->ma_values[i];
- offset = sizeof(PyObject *);
+ PyObject **value_ptr = &mp->ma_values[i];
+ while (i < n && *value_ptr == NULL) {
+ value_ptr++;
+ i++;
+ }
+ if (i >= n)
+ return 0;
+ entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
+ value = *value_ptr;
}
else {
- value_ptr = &mp->ma_keys->dk_entries[i].me_value;
- offset = sizeof(PyDictKeyEntry);
- }
- mask = DK_MASK(mp->ma_keys);
- while (i <= mask && *value_ptr == NULL) {
- value_ptr = (PyObject **)(((char *)value_ptr) + offset);
- i++;
+ entry_ptr = &DK_ENTRIES(mp->ma_keys)[i];
+ while (i < n && entry_ptr->me_value == NULL) {
+ entry_ptr++;
+ i++;
+ }
+ if (i >= n)
+ return 0;
+ value = entry_ptr->me_value;
}
- if (i > mask)
- return -1;
+ *ppos = i+1;
+ if (pkey)
+ *pkey = entry_ptr->me_key;
+ if (phash)
+ *phash = entry_ptr->me_hash;
if (pvalue)
- *pvalue = *value_ptr;
- return i;
+ *pvalue = value;
+ return 1;
}
/*
@@ -1432,9 +1810,12 @@ dict_next(PyObject *op, Py_ssize_t i, PyObject **pvalue)
* PyObject *key, *value;
* i = 0; # important! i should not otherwise be changed by you
* while (PyDict_Next(yourdict, &i, &key, &value)) {
- * Refer to borrowed references in key and value.
+ * Refer to borrowed references in key and value.
* }
*
+ * Return 1 on success, return 0 when the reached the end of the dictionary
+ * (or if op is not a dictionary)
+ *
* CAUTION: In general, it isn't safe to use PyDict_Next in a loop that
* mutates the dict. One exception: it is safe if the loop merely changes
* the values associated with the keys (but doesn't insert new keys or
@@ -1443,43 +1824,21 @@ dict_next(PyObject *op, Py_ssize_t i, PyObject **pvalue)
int
PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
{
- PyDictObject *mp;
- Py_ssize_t i = dict_next(op, *ppos, pvalue);
- if (i < 0)
- return 0;
- mp = (PyDictObject *)op;
- *ppos = i+1;
- if (pkey)
- *pkey = mp->ma_keys->dk_entries[i].me_key;
- return 1;
-}
-
-/* Internal version of PyDict_Next that returns a hash value in addition
- * to the key and value.
- */
-int
-_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
- PyObject **pvalue, Py_hash_t *phash)
-{
- PyDictObject *mp;
- Py_ssize_t i = dict_next(op, *ppos, pvalue);
- if (i < 0)
- return 0;
- mp = (PyDictObject *)op;
- *ppos = i+1;
- *phash = mp->ma_keys->dk_entries[i].me_hash;
- if (pkey)
- *pkey = mp->ma_keys->dk_entries[i].me_key;
- return 1;
+ return _PyDict_Next(op, ppos, pkey, pvalue, NULL);
}
/* Internal version of dict.pop(). */
PyObject *
-_PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *deflt)
+_PyDict_Pop_KnownHash(PyObject *dict, PyObject *key, Py_hash_t hash, PyObject *deflt)
{
+ Py_ssize_t ix, hashpos;
PyObject *old_value, *old_key;
PyDictKeyEntry *ep;
PyObject **value_addr;
+ PyDictObject *mp;
+
+ assert(PyDict_Check(dict));
+ mp = (PyDictObject *)dict;
if (mp->ma_used == 0) {
if (deflt) {
@@ -1489,11 +1848,10 @@ _PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject
_PyErr_SetKeyError(key);
return NULL;
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ if (ix == DKIX_ERROR)
return NULL;
- old_value = *value_addr;
- if (old_value == NULL) {
+ if (ix == DKIX_EMPTY || *value_addr == NULL) {
if (deflt) {
Py_INCREF(deflt);
return deflt;
@@ -1501,24 +1859,38 @@ _PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject
_PyErr_SetKeyError(key);
return NULL;
}
+
+ // Split table doesn't allow deletion. Combine it.
+ if (_PyDict_HasSplitTable(mp)) {
+ if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
+ return NULL;
+ }
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ assert(ix >= 0);
+ }
+
+ old_value = *value_addr;
+ assert(old_value != NULL);
*value_addr = NULL;
mp->ma_used--;
- if (!_PyDict_HasSplitTable(mp)) {
- ENSURE_ALLOWS_DELETIONS(mp);
- old_key = ep->me_key;
- Py_INCREF(dummy);
- ep->me_key = dummy;
- Py_DECREF(old_key);
- }
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ dk_set_index(mp->ma_keys, hashpos, DKIX_DUMMY);
+ ep = &DK_ENTRIES(mp->ma_keys)[ix];
+ ENSURE_ALLOWS_DELETIONS(mp);
+ old_key = ep->me_key;
+ ep->me_key = NULL;
+ Py_DECREF(old_key);
+
+ assert(_PyDict_CheckConsistency(mp));
return old_value;
}
PyObject *
-_PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt)
+_PyDict_Pop(PyObject *dict, PyObject *key, PyObject *deflt)
{
Py_hash_t hash;
- if (mp->ma_used == 0) {
+ if (((PyDictObject *)dict)->ma_used == 0) {
if (deflt) {
Py_INCREF(deflt);
return deflt;
@@ -1532,7 +1904,7 @@ _PyDict_Pop(PyDictObject *mp, PyObject *key, PyObject *deflt)
if (hash == -1)
return NULL;
}
- return _PyDict_Pop_KnownHash(mp, key, hash, deflt);
+ return _PyDict_Pop_KnownHash(dict, key, hash, deflt);
}
/* Internal version of dict.from_keys(). It is subclass-friendly. */
@@ -1556,7 +1928,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
PyObject *key;
Py_hash_t hash;
- if (dictresize(mp, Py_SIZE(iterable))) {
+ if (dictresize(mp, ESTIMATE_SIZE(Py_SIZE(iterable)))) {
Py_DECREF(d);
return NULL;
}
@@ -1575,7 +1947,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
PyObject *key;
Py_hash_t hash;
- if (dictresize(mp, PySet_GET_SIZE(iterable))) {
+ if (dictresize(mp, ESTIMATE_SIZE(PySet_GET_SIZE(iterable)))) {
Py_DECREF(d);
return NULL;
}
@@ -1635,7 +2007,7 @@ dict_dealloc(PyDictObject *mp)
Py_TRASHCAN_SAFE_BEGIN(mp)
if (values != NULL) {
if (values != empty_values) {
- for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) {
+ for (i = 0, n = mp->ma_keys->dk_nentries; i < n; i++) {
Py_XDECREF(values[i]);
}
free_values(values);
@@ -1747,8 +2119,8 @@ static PyObject *
dict_subscript(PyDictObject *mp, PyObject *key)
{
PyObject *v;
+ Py_ssize_t ix;
Py_hash_t hash;
- PyDictKeyEntry *ep;
PyObject **value_addr;
if (!PyUnicode_CheckExact(key) ||
@@ -1757,11 +2129,10 @@ dict_subscript(PyDictObject *mp, PyObject *key)
if (hash == -1)
return NULL;
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix == DKIX_ERROR)
return NULL;
- v = *value_addr;
- if (v == NULL) {
+ if (ix == DKIX_EMPTY || *value_addr == NULL) {
if (!PyDict_CheckExact(mp)) {
/* Look up __missing__ method if we're a subclass. */
PyObject *missing, *res;
@@ -1779,8 +2150,8 @@ dict_subscript(PyDictObject *mp, PyObject *key)
_PyErr_SetKeyError(key);
return NULL;
}
- else
- Py_INCREF(v);
+ v = *value_addr;
+ Py_INCREF(v);
return v;
}
@@ -1820,8 +2191,8 @@ dict_keys(PyDictObject *mp)
Py_DECREF(v);
goto again;
}
- ep = &mp->ma_keys->dk_entries[0];
- size = DK_SIZE(mp->ma_keys);
+ ep = DK_ENTRIES(mp->ma_keys);
+ size = mp->ma_keys->dk_nentries;
if (mp->ma_values) {
value_ptr = mp->ma_values;
offset = sizeof(PyObject *);
@@ -1848,6 +2219,7 @@ dict_values(PyDictObject *mp)
{
PyObject *v;
Py_ssize_t i, j;
+ PyDictKeyEntry *ep;
Py_ssize_t size, n, offset;
PyObject **value_ptr;
@@ -1863,13 +2235,14 @@ dict_values(PyDictObject *mp)
Py_DECREF(v);
goto again;
}
- size = DK_SIZE(mp->ma_keys);
+ ep = DK_ENTRIES(mp->ma_keys);
+ size = mp->ma_keys->dk_nentries;
if (mp->ma_values) {
value_ptr = mp->ma_values;
offset = sizeof(PyObject *);
}
else {
- value_ptr = &mp->ma_keys->dk_entries[0].me_value;
+ value_ptr = &ep[0].me_value;
offset = sizeof(PyDictKeyEntry);
}
for (i = 0, j = 0; i < size; i++) {
@@ -1920,8 +2293,8 @@ dict_items(PyDictObject *mp)
goto again;
}
/* Nothing we do below makes any function calls. */
- ep = mp->ma_keys->dk_entries;
- size = DK_SIZE(mp->ma_keys);
+ ep = DK_ENTRIES(mp->ma_keys);
+ size = mp->ma_keys->dk_nentries;
if (mp->ma_values) {
value_ptr = mp->ma_values;
offset = sizeof(PyObject *);
@@ -1965,7 +2338,8 @@ dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value)
}
static int
-dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname)
+dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
+ const char *methname)
{
PyObject *arg = NULL;
int result = 0;
@@ -2067,6 +2441,7 @@ PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
}
i = 0;
+ assert(_PyDict_CheckConsistency((PyDictObject *)d));
goto Return;
Fail:
Py_XDECREF(item);
@@ -2077,18 +2452,14 @@ Return:
return Py_SAFE_DOWNCAST(i, Py_ssize_t, int);
}
-int
-PyDict_Update(PyObject *a, PyObject *b)
-{
- return PyDict_Merge(a, b, 1);
-}
-
-int
-PyDict_Merge(PyObject *a, PyObject *b, int override)
+static int
+dict_merge(PyObject *a, PyObject *b, int override)
{
PyDictObject *mp, *other;
Py_ssize_t i, n;
- PyDictKeyEntry *entry;
+ PyDictKeyEntry *entry, *ep0;
+
+ assert(0 <= override && override <= 2);
/* We accept for the argument either a concrete dictionary object,
* or an abstract "mapping" object. For the former, we can do
@@ -2115,13 +2486,16 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
* incrementally resizing as we insert new items. Expect
* that there will be no (or few) overlapping keys.
*/
- if (mp->ma_keys->dk_usable * 3 < other->ma_used * 2)
- if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0)
+ if (USABLE_FRACTION(mp->ma_keys->dk_size) < other->ma_used) {
+ if (dictresize(mp, ESTIMATE_SIZE(mp->ma_used + other->ma_used))) {
return -1;
- for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) {
+ }
+ }
+ ep0 = DK_ENTRIES(other->ma_keys);
+ for (i = 0, n = other->ma_keys->dk_nentries; i < n; i++) {
PyObject *key, *value;
Py_hash_t hash;
- entry = &other->ma_keys->dk_entries[i];
+ entry = &ep0[i];
key = entry->me_key;
hash = entry->me_hash;
if (other->ma_values)
@@ -2133,14 +2507,28 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
int err = 0;
Py_INCREF(key);
Py_INCREF(value);
- if (override || PyDict_GetItem(a, key) == NULL)
+ if (override == 1)
err = insertdict(mp, key, hash, value);
+ else if (_PyDict_GetItem_KnownHash(a, key, hash) == NULL) {
+ if (PyErr_Occurred()) {
+ Py_DECREF(value);
+ Py_DECREF(key);
+ return -1;
+ }
+ err = insertdict(mp, key, hash, value);
+ }
+ else if (override != 0) {
+ _PyErr_SetKeyError(key);
+ Py_DECREF(value);
+ Py_DECREF(key);
+ return -1;
+ }
Py_DECREF(value);
Py_DECREF(key);
if (err != 0)
return -1;
- if (n != DK_SIZE(other->ma_keys)) {
+ if (n != other->ma_keys->dk_nentries) {
PyErr_SetString(PyExc_RuntimeError,
"dict mutated during update");
return -1;
@@ -2169,7 +2557,13 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
return -1;
for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
- if (!override && PyDict_GetItem(a, key) != NULL) {
+ if (override != 1 && PyDict_GetItem(a, key) != NULL) {
+ if (override != 0) {
+ _PyErr_SetKeyError(key);
+ Py_DECREF(key);
+ Py_DECREF(iter);
+ return -1;
+ }
Py_DECREF(key);
continue;
}
@@ -2192,9 +2586,29 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
/* Iterator completed, via error */
return -1;
}
+ assert(_PyDict_CheckConsistency((PyDictObject *)a));
return 0;
}
+int
+PyDict_Update(PyObject *a, PyObject *b)
+{
+ return dict_merge(a, b, 1);
+}
+
+int
+PyDict_Merge(PyObject *a, PyObject *b, int override)
+{
+ /* XXX Deprecate override not in (0, 1). */
+ return dict_merge(a, b, override != 0);
+}
+
+int
+_PyDict_MergeEx(PyObject *a, PyObject *b, int override)
+{
+ return dict_merge(a, b, override);
+}
+
static PyObject *
dict_copy(PyDictObject *mp)
{
@@ -2215,7 +2629,9 @@ PyDict_Copy(PyObject *o)
mp = (PyDictObject *)o;
if (_PyDict_HasSplitTable(mp)) {
PyDictObject *split_copy;
- PyObject **newvalues = new_values(DK_SIZE(mp->ma_keys));
+ Py_ssize_t size = USABLE_FRACTION(DK_SIZE(mp->ma_keys));
+ PyObject **newvalues;
+ newvalues = new_values(size);
if (newvalues == NULL)
return PyErr_NoMemory();
split_copy = PyObject_GC_New(PyDictObject, &PyDict_Type);
@@ -2227,7 +2643,7 @@ PyDict_Copy(PyObject *o)
split_copy->ma_keys = mp->ma_keys;
split_copy->ma_used = mp->ma_used;
DK_INCREF(mp->ma_keys);
- for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) {
+ for (i = 0, n = size; i < n; i++) {
PyObject *value = mp->ma_values[i];
Py_XINCREF(value);
split_copy->ma_values[i] = value;
@@ -2298,8 +2714,8 @@ dict_equal(PyDictObject *a, PyDictObject *b)
/* can't be equal if # of entries differ */
return 0;
/* Same # of entries -- check all of 'em. Exit early on any diff. */
- for (i = 0; i < DK_SIZE(a->ma_keys); i++) {
- PyDictKeyEntry *ep = &a->ma_keys->dk_entries[i];
+ for (i = 0; i < a->ma_keys->dk_nentries; i++) {
+ PyDictKeyEntry *ep = &DK_ENTRIES(a->ma_keys)[i];
PyObject *aval;
if (a->ma_values)
aval = a->ma_values[i];
@@ -2316,7 +2732,7 @@ dict_equal(PyDictObject *a, PyDictObject *b)
/* ditto for key */
Py_INCREF(key);
/* reuse the known hash value */
- if ((b->ma_keys->dk_lookup)(b, key, ep->me_hash, &vaddr) == NULL)
+ if ((b->ma_keys->dk_lookup)(b, key, ep->me_hash, &vaddr, NULL) < 0)
bval = NULL;
else
bval = *vaddr;
@@ -2374,7 +2790,7 @@ dict___contains__(PyDictObject *self, PyObject *key)
{
register PyDictObject *mp = self;
Py_hash_t hash;
- PyDictKeyEntry *ep;
+ Py_ssize_t ix;
PyObject **value_addr;
if (!PyUnicode_CheckExact(key) ||
@@ -2383,10 +2799,12 @@ dict___contains__(PyDictObject *self, PyObject *key)
if (hash == -1)
return NULL;
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix == DKIX_ERROR)
return NULL;
- return PyBool_FromLong(*value_addr != NULL);
+ if (ix == DKIX_EMPTY || *value_addr == NULL)
+ Py_RETURN_FALSE;
+ Py_RETURN_TRUE;
}
static PyObject *
@@ -2396,7 +2814,7 @@ dict_get(PyDictObject *mp, PyObject *args)
PyObject *failobj = Py_None;
PyObject *val = NULL;
Py_hash_t hash;
- PyDictKeyEntry *ep;
+ Py_ssize_t ix;
PyObject **value_addr;
if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj))
@@ -2408,12 +2826,13 @@ dict_get(PyDictObject *mp, PyObject *args)
if (hash == -1)
return NULL;
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix == DKIX_ERROR)
return NULL;
- val = *value_addr;
- if (val == NULL)
+ if (ix == DKIX_EMPTY || *value_addr == NULL)
val = failobj;
+ else
+ val = *value_addr;
Py_INCREF(val);
return val;
}
@@ -2422,43 +2841,88 @@ PyObject *
PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
{
PyDictObject *mp = (PyDictObject *)d;
- PyObject *val = NULL;
+ PyObject *value;
Py_hash_t hash;
- PyDictKeyEntry *ep;
+ Py_ssize_t hashpos, ix;
PyObject **value_addr;
if (!PyDict_Check(d)) {
PyErr_BadInternalCall();
return NULL;
}
+
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyASCIIObject *) key)->hash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return NULL;
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- if (ep == NULL)
+
+ if (mp->ma_values != NULL && !PyUnicode_CheckExact(key)) {
+ if (insertion_resize(mp) < 0)
+ return NULL;
+ }
+
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, &hashpos);
+ if (ix == DKIX_ERROR)
return NULL;
- val = *value_addr;
- if (val == NULL) {
+
+ if (_PyDict_HasSplitTable(mp) &&
+ ((ix >= 0 && *value_addr == NULL && mp->ma_used != ix) ||
+ (ix == DKIX_EMPTY && mp->ma_used != mp->ma_keys->dk_nentries))) {
+ if (insertion_resize(mp) < 0) {
+ return NULL;
+ }
+ find_empty_slot(mp, key, hash, &value_addr, &hashpos);
+ ix = DKIX_EMPTY;
+ }
+
+ if (ix == DKIX_EMPTY) {
+ PyDictKeyEntry *ep, *ep0;
+ value = defaultobj;
if (mp->ma_keys->dk_usable <= 0) {
- /* Need to resize. */
- if (insertion_resize(mp) < 0)
+ if (insertion_resize(mp) < 0) {
return NULL;
- ep = find_empty_slot(mp, key, hash, &value_addr);
+ }
+ find_empty_slot(mp, key, hash, &value_addr, &hashpos);
}
- Py_INCREF(defaultobj);
+ ep0 = DK_ENTRIES(mp->ma_keys);
+ ep = &ep0[mp->ma_keys->dk_nentries];
+ dk_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
Py_INCREF(key);
- MAINTAIN_TRACKING(mp, key, defaultobj);
+ Py_INCREF(value);
+ MAINTAIN_TRACKING(mp, key, value);
ep->me_key = key;
ep->me_hash = hash;
- *value_addr = defaultobj;
- val = defaultobj;
+ if (mp->ma_values) {
+ assert(mp->ma_values[mp->ma_keys->dk_nentries] == NULL);
+ mp->ma_values[mp->ma_keys->dk_nentries] = value;
+ }
+ else {
+ ep->me_value = value;
+ }
+ mp->ma_used++;
+ mp->ma_version_tag = DICT_NEXT_VERSION();
mp->ma_keys->dk_usable--;
+ mp->ma_keys->dk_nentries++;
+ assert(mp->ma_keys->dk_usable >= 0);
+ }
+ else if (*value_addr == NULL) {
+ value = defaultobj;
+ assert(_PyDict_HasSplitTable(mp));
+ assert(ix == mp->ma_used);
+ Py_INCREF(value);
+ MAINTAIN_TRACKING(mp, key, value);
+ *value_addr = value;
mp->ma_used++;
+ mp->ma_version_tag = DICT_NEXT_VERSION();
}
- return val;
+ else {
+ value = *value_addr;
+ }
+
+ assert(_PyDict_CheckConsistency(mp));
+ return value;
}
static PyObject *
@@ -2490,17 +2954,16 @@ dict_pop(PyDictObject *mp, PyObject *args)
if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt))
return NULL;
- return _PyDict_Pop(mp, key, deflt);
+ return _PyDict_Pop((PyObject*)mp, key, deflt);
}
static PyObject *
dict_popitem(PyDictObject *mp)
{
- Py_hash_t i = 0;
- PyDictKeyEntry *ep;
+ Py_ssize_t i, j;
+ PyDictKeyEntry *ep0, *ep;
PyObject *res;
-
/* Allocate the result tuple before checking the size. Believe it
* or not, this allocation could trigger a garbage collection which
* could empty the dict, so if we checked the size first and that
@@ -2521,68 +2984,64 @@ dict_popitem(PyDictObject *mp)
}
/* Convert split table to combined table */
if (mp->ma_keys->dk_lookup == lookdict_split) {
- /* -1 is required since dictresize() uses key size > minused */
- if (dictresize(mp, DK_SIZE(mp->ma_keys) - 1)) {
+ if (dictresize(mp, DK_SIZE(mp->ma_keys))) {
Py_DECREF(res);
return NULL;
}
}
ENSURE_ALLOWS_DELETIONS(mp);
- /* Set ep to "the first" dict entry with a value. We abuse the hash
- * field of slot 0 to hold a search finger:
- * If slot 0 has a value, use slot 0.
- * Else slot 0 is being used to hold a search finger,
- * and we use its hash value as the first index to look.
- */
- ep = &mp->ma_keys->dk_entries[0];
- if (ep->me_value == NULL) {
- Py_ssize_t mask = DK_MASK(mp->ma_keys);
- i = ep->me_hash;
- /* The hash field may be a real hash value, or it may be a
- * legit search finger, or it may be a once-legit search
- * finger that's out of bounds now because it wrapped around
- * or the table shrunk -- simply make sure it's in bounds now.
- */
- if (i > mask || i < 1)
- i = 1; /* skip slot 0 */
- while ((ep = &mp->ma_keys->dk_entries[i])->me_value == NULL) {
- i++;
- if (i > mask)
- i = 1;
- }
+
+ /* Pop last item */
+ ep0 = DK_ENTRIES(mp->ma_keys);
+ i = mp->ma_keys->dk_nentries - 1;
+ while (i >= 0 && ep0[i].me_value == NULL) {
+ i--;
}
+ assert(i >= 0);
+
+ ep = &ep0[i];
+ j = lookdict_index(mp->ma_keys, ep->me_hash, i);
+ assert(j >= 0);
+ assert(dk_get_index(mp->ma_keys, j) == i);
+ dk_set_index(mp->ma_keys, j, DKIX_DUMMY);
+
PyTuple_SET_ITEM(res, 0, ep->me_key);
PyTuple_SET_ITEM(res, 1, ep->me_value);
- Py_INCREF(dummy);
- ep->me_key = dummy;
+ ep->me_key = NULL;
ep->me_value = NULL;
+ /* We can't dk_usable++ since there is DKIX_DUMMY in indices */
+ mp->ma_keys->dk_nentries = i;
mp->ma_used--;
- assert(mp->ma_keys->dk_entries[0].me_value == NULL);
- mp->ma_keys->dk_entries[0].me_hash = i + 1; /* next place to start */
+ mp->ma_version_tag = DICT_NEXT_VERSION();
+ assert(_PyDict_CheckConsistency(mp));
return res;
}
static int
dict_traverse(PyObject *op, visitproc visit, void *arg)
{
- Py_ssize_t i, n;
PyDictObject *mp = (PyDictObject *)op;
- if (mp->ma_keys->dk_lookup == lookdict) {
- for (i = 0; i < DK_SIZE(mp->ma_keys); i++) {
- if (mp->ma_keys->dk_entries[i].me_value != NULL) {
- Py_VISIT(mp->ma_keys->dk_entries[i].me_value);
- Py_VISIT(mp->ma_keys->dk_entries[i].me_key);
+ PyDictKeysObject *keys = mp->ma_keys;
+ PyDictKeyEntry *entries = DK_ENTRIES(keys);
+ Py_ssize_t i, n = keys->dk_nentries;
+
+ if (keys->dk_lookup == lookdict) {
+ for (i = 0; i < n; i++) {
+ if (entries[i].me_value != NULL) {
+ Py_VISIT(entries[i].me_value);
+ Py_VISIT(entries[i].me_key);
}
}
- } else {
+ }
+ else {
if (mp->ma_values != NULL) {
- for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) {
+ for (i = 0; i < n; i++) {
Py_VISIT(mp->ma_values[i]);
}
}
else {
- for (i = 0, n = DK_SIZE(mp->ma_keys); i < n; i++) {
- Py_VISIT(mp->ma_keys->dk_entries[i].me_value);
+ for (i = 0; i < n; i++) {
+ Py_VISIT(entries[i].me_value);
}
}
}
@@ -2601,23 +3060,31 @@ static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
Py_ssize_t
_PyDict_SizeOf(PyDictObject *mp)
{
- Py_ssize_t size, res;
+ Py_ssize_t size, usable, res;
size = DK_SIZE(mp->ma_keys);
+ usable = USABLE_FRACTION(size);
+
res = _PyObject_SIZE(Py_TYPE(mp));
if (mp->ma_values)
- res += size * sizeof(PyObject*);
+ res += usable * sizeof(PyObject*);
/* If the dictionary is split, the keys portion is accounted-for
in the type object. */
if (mp->ma_keys->dk_refcnt == 1)
- res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry);
+ res += (sizeof(PyDictKeysObject)
+ - Py_MEMBER_SIZE(PyDictKeysObject, dk_indices)
+ + DK_IXSIZE(mp->ma_keys) * size
+ + sizeof(PyDictKeyEntry) * usable);
return res;
}
Py_ssize_t
_PyDict_KeysSize(PyDictKeysObject *keys)
{
- return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
+ return (sizeof(PyDictKeysObject)
+ - Py_MEMBER_SIZE(PyDictKeysObject, dk_indices)
+ + DK_IXSIZE(keys) * DK_SIZE(keys)
+ + USABLE_FRACTION(DK_SIZE(keys)) * sizeof(PyDictKeyEntry));
}
static PyObject *
@@ -2704,8 +3171,8 @@ int
PyDict_Contains(PyObject *op, PyObject *key)
{
Py_hash_t hash;
+ Py_ssize_t ix;
PyDictObject *mp = (PyDictObject *)op;
- PyDictKeyEntry *ep;
PyObject **value_addr;
if (!PyUnicode_CheckExact(key) ||
@@ -2714,8 +3181,10 @@ PyDict_Contains(PyObject *op, PyObject *key)
if (hash == -1)
return -1;
}
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- return (ep == NULL) ? -1 : (*value_addr != NULL);
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix == DKIX_ERROR)
+ return -1;
+ return (ix != DKIX_EMPTY && *value_addr != NULL);
}
/* Internal version of PyDict_Contains used when the hash value is already known */
@@ -2723,11 +3192,13 @@ int
_PyDict_Contains(PyObject *op, PyObject *key, Py_hash_t hash)
{
PyDictObject *mp = (PyDictObject *)op;
- PyDictKeyEntry *ep;
PyObject **value_addr;
+ Py_ssize_t ix;
- ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr);
- return (ep == NULL) ? -1 : (*value_addr != NULL);
+ ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
+ if (ix == DKIX_ERROR)
+ return -1;
+ return (ix != DKIX_EMPTY && *value_addr != NULL);
}
/* Hack to implement "key in dict" */
@@ -2761,11 +3232,13 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
_PyObject_GC_UNTRACK(d);
d->ma_used = 0;
- d->ma_keys = new_keys_object(PyDict_MINSIZE_COMBINED);
+ d->ma_version_tag = DICT_NEXT_VERSION();
+ d->ma_keys = new_keys_object(PyDict_MINSIZE);
if (d->ma_keys == NULL) {
Py_DECREF(self);
return NULL;
}
+ assert(_PyDict_CheckConsistency(d));
return self;
}
@@ -2986,13 +3459,13 @@ static PyMethodDef dictiter_methods[] = {
{NULL, NULL} /* sentinel */
};
-static PyObject *dictiter_iternextkey(dictiterobject *di)
+static PyObject*
+dictiter_iternextkey(dictiterobject *di)
{
PyObject *key;
- Py_ssize_t i, mask, offset;
+ Py_ssize_t i, n;
PyDictKeysObject *k;
PyDictObject *d = di->di_dict;
- PyObject **value_ptr;
if (d == NULL)
return NULL;
@@ -3006,27 +3479,30 @@ static PyObject *dictiter_iternextkey(dictiterobject *di)
}
i = di->di_pos;
- if (i < 0)
- goto fail;
k = d->ma_keys;
+ n = k->dk_nentries;
if (d->ma_values) {
- value_ptr = &d->ma_values[i];
- offset = sizeof(PyObject *);
+ PyObject **value_ptr = &d->ma_values[i];
+ while (i < n && *value_ptr == NULL) {
+ value_ptr++;
+ i++;
+ }
+ if (i >= n)
+ goto fail;
+ key = DK_ENTRIES(k)[i].me_key;
}
else {
- value_ptr = &k->dk_entries[i].me_value;
- offset = sizeof(PyDictKeyEntry);
- }
- mask = DK_SIZE(k)-1;
- while (i <= mask && *value_ptr == NULL) {
- value_ptr = (PyObject **)(((char *)value_ptr) + offset);
- i++;
+ PyDictKeyEntry *entry_ptr = &DK_ENTRIES(k)[i];
+ while (i < n && entry_ptr->me_value == NULL) {
+ entry_ptr++;
+ i++;
+ }
+ if (i >= n)
+ goto fail;
+ key = entry_ptr->me_key;
}
di->di_pos = i+1;
- if (i > mask)
- goto fail;
di->len--;
- key = k->dk_entries[i].me_key;
Py_INCREF(key);
return key;
@@ -3069,12 +3545,12 @@ PyTypeObject PyDictIterKey_Type = {
0,
};
-static PyObject *dictiter_iternextvalue(dictiterobject *di)
+static PyObject *
+dictiter_iternextvalue(dictiterobject *di)
{
PyObject *value;
- Py_ssize_t i, mask, offset;
+ Py_ssize_t i, n;
PyDictObject *d = di->di_dict;
- PyObject **value_ptr;
if (d == NULL)
return NULL;
@@ -3088,26 +3564,29 @@ static PyObject *dictiter_iternextvalue(dictiterobject *di)
}
i = di->di_pos;
- mask = DK_SIZE(d->ma_keys)-1;
- if (i < 0 || i > mask)
- goto fail;
+ n = d->ma_keys->dk_nentries;
if (d->ma_values) {
- value_ptr = &d->ma_values[i];
- offset = sizeof(PyObject *);
+ PyObject **value_ptr = &d->ma_values[i];
+ while (i < n && *value_ptr == NULL) {
+ value_ptr++;
+ i++;
+ }
+ if (i >= n)
+ goto fail;
+ value = *value_ptr;
}
else {
- value_ptr = &d->ma_keys->dk_entries[i].me_value;
- offset = sizeof(PyDictKeyEntry);
- }
- while (i <= mask && *value_ptr == NULL) {
- value_ptr = (PyObject **)(((char *)value_ptr) + offset);
- i++;
- if (i > mask)
+ PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
+ while (i < n && entry_ptr->me_value == NULL) {
+ entry_ptr++;
+ i++;
+ }
+ if (i >= n)
goto fail;
+ value = entry_ptr->me_value;
}
di->di_pos = i+1;
di->len--;
- value = *value_ptr;
Py_INCREF(value);
return value;
@@ -3138,7 +3617,7 @@ PyTypeObject PyDictIterValue_Type = {
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)dictiter_traverse, /* tp_traverse */
0, /* tp_clear */
@@ -3150,12 +3629,12 @@ PyTypeObject PyDictIterValue_Type = {
0,
};
-static PyObject *dictiter_iternextitem(dictiterobject *di)
+static PyObject *
+dictiter_iternextitem(dictiterobject *di)
{
PyObject *key, *value, *result = di->di_result;
- Py_ssize_t i, mask, offset;
+ Py_ssize_t i, n;
PyDictObject *d = di->di_dict;
- PyObject **value_ptr;
if (d == NULL)
return NULL;
@@ -3169,37 +3648,41 @@ static PyObject *dictiter_iternextitem(dictiterobject *di)
}
i = di->di_pos;
- if (i < 0)
- goto fail;
- mask = DK_SIZE(d->ma_keys)-1;
+ n = d->ma_keys->dk_nentries;
if (d->ma_values) {
- value_ptr = &d->ma_values[i];
- offset = sizeof(PyObject *);
+ PyObject **value_ptr = &d->ma_values[i];
+ while (i < n && *value_ptr == NULL) {
+ value_ptr++;
+ i++;
+ }
+ if (i >= n)
+ goto fail;
+ key = DK_ENTRIES(d->ma_keys)[i].me_key;
+ value = *value_ptr;
}
else {
- value_ptr = &d->ma_keys->dk_entries[i].me_value;
- offset = sizeof(PyDictKeyEntry);
- }
- while (i <= mask && *value_ptr == NULL) {
- value_ptr = (PyObject **)(((char *)value_ptr) + offset);
- i++;
+ PyDictKeyEntry *entry_ptr = &DK_ENTRIES(d->ma_keys)[i];
+ while (i < n && entry_ptr->me_value == NULL) {
+ entry_ptr++;
+ i++;
+ }
+ if (i >= n)
+ goto fail;
+ key = entry_ptr->me_key;
+ value = entry_ptr->me_value;
}
di->di_pos = i+1;
- if (i > mask)
- goto fail;
-
+ di->len--;
if (result->ob_refcnt == 1) {
Py_INCREF(result);
Py_DECREF(PyTuple_GET_ITEM(result, 0));
Py_DECREF(PyTuple_GET_ITEM(result, 1));
- } else {
+ }
+ else {
result = PyTuple_New(2);
if (result == NULL)
return NULL;
}
- di->len--;
- key = d->ma_keys->dk_entries[i].me_key;
- value = *value_ptr;
Py_INCREF(key);
Py_INCREF(value);
PyTuple_SET_ITEM(result, 0, key); /* steals reference */
@@ -3838,7 +4321,7 @@ dictvalues_new(PyObject *dict)
PyDictKeysObject *
_PyDict_NewKeysForClass(void)
{
- PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE_SPLIT);
+ PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE);
if (keys == NULL)
PyErr_Clear();
else
@@ -3874,7 +4357,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
int
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
- PyObject *key, PyObject *value)
+ PyObject *key, PyObject *value)
{
PyObject *dict;
int res;
@@ -3901,15 +4384,25 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
else {
int was_shared = cached == ((PyDictObject *)dict)->ma_keys;
res = PyDict_SetItem(dict, key, value);
- /* PyDict_SetItem() may call dictresize() and convert split table
- * into combined table. In such case, convert it to split
- * table again and update type's shared key only when this is
- * the only dict sharing key with the type.
- */
if (was_shared && cached != ((PyDictObject *)dict)->ma_keys) {
+ /* PyDict_SetItem() may call dictresize and convert split table
+ * into combined table. In such case, convert it to split
+ * table again and update type's shared key only when this is
+ * the only dict sharing key with the type.
+ *
+ * This is to allow using shared key in class like this:
+ *
+ * class C:
+ * def __init__(self):
+ * # one dict resize happens
+ * self.a, self.b, self.c = 1, 2, 3
+ * self.d, self.e, self.f = 4, 5, 6
+ * a = C()
+ */
if (cached->dk_refcnt == 1) {
CACHED_KEYS(tp) = make_keys_shared(dict);
- } else {
+ }
+ else {
CACHED_KEYS(tp) = NULL;
}
DK_DECREF(cached);
@@ -3939,50 +4432,3 @@ _PyDictKeys_DecRef(PyDictKeysObject *keys)
{
DK_DECREF(keys);
}
-
-
-/* ARGSUSED */
-static PyObject *
-dummy_repr(PyObject *op)
-{
- return PyUnicode_FromString("<dummy key>");
-}
-
-/* ARGUSED */
-static void
-dummy_dealloc(PyObject* ignore)
-{
- /* This should never get called, but we also don't want to SEGV if
- * we accidentally decref dummy-key out of existence.
- */
- Py_FatalError("deallocating <dummy key>");
-}
-
-static PyTypeObject PyDictDummy_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "<dummy key> type",
- 0,
- 0,
- dummy_dealloc, /*tp_dealloc*/ /*never called*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_reserved*/
- dummy_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call */
- 0, /*tp_str */
- 0, /*tp_getattro */
- 0, /*tp_setattro */
- 0, /*tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /*tp_flags */
-};
-
-static PyObject _dummy_struct = {
- _PyObject_EXTRA_INIT
- 2, &PyDictDummy_Type
-};
-
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index c458cfe73d..dae166d5ad 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -250,6 +250,13 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
reversed_meth = _PyObject_LookupSpecial(seq, &PyId___reversed__);
+ if (reversed_meth == Py_None) {
+ Py_DECREF(reversed_meth);
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is not reversible",
+ Py_TYPE(seq)->tp_name);
+ return NULL;
+ }
if (reversed_meth != NULL) {
PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);
Py_DECREF(reversed_meth);
@@ -259,8 +266,9 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
if (!PySequence_Check(seq)) {
- PyErr_SetString(PyExc_TypeError,
- "argument to reversed() must be a sequence");
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is not reversible",
+ Py_TYPE(seq)->tp_name);
return NULL;
}
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 981ead2172..f63f06a145 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -59,15 +59,11 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int
BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *tmp;
-
if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
return -1;
- tmp = self->args;
- self->args = args;
- Py_INCREF(self->args);
- Py_XDECREF(tmp);
+ Py_INCREF(args);
+ Py_XSETREF(self->args, args);
return 0;
}
@@ -234,7 +230,7 @@ BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb)
return -1;
}
- Py_XINCREF(tb);
+ Py_INCREF(tb);
Py_XSETREF(self->traceback, tb);
return 0;
}
@@ -328,11 +324,10 @@ PyException_GetCause(PyObject *self) {
/* Steals a reference to cause */
void
-PyException_SetCause(PyObject *self, PyObject *cause) {
- PyObject *old_cause = ((PyBaseExceptionObject *)self)->cause;
- ((PyBaseExceptionObject *)self)->cause = cause;
+PyException_SetCause(PyObject *self, PyObject *cause)
+{
((PyBaseExceptionObject *)self)->suppress_context = 1;
- Py_XDECREF(old_cause);
+ Py_XSETREF(((PyBaseExceptionObject *)self)->cause, cause);
}
PyObject *
@@ -344,10 +339,9 @@ PyException_GetContext(PyObject *self) {
/* Steals a reference to context */
void
-PyException_SetContext(PyObject *self, PyObject *context) {
- PyObject *old_context = ((PyBaseExceptionObject *)self)->context;
- ((PyBaseExceptionObject *)self)->context = context;
- Py_XDECREF(old_context);
+PyException_SetContext(PyObject *self, PyObject *context)
+{
+ Py_XSETREF(((PyBaseExceptionObject *)self)->context, context);
}
@@ -714,6 +708,13 @@ ComplexExtendsException(PyExc_Exception, ImportError,
"module.");
/*
+ * ModuleNotFoundError extends ImportError
+ */
+
+MiddlingExtendsException(PyExc_ImportError, ModuleNotFoundError, ImportError,
+ "Module not found.");
+
+/*
* OSError extends Exception
*/
@@ -993,7 +994,7 @@ OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds)
return 0;
error:
- Py_XDECREF(args);
+ Py_DECREF(args);
return -1;
}
@@ -1073,8 +1074,7 @@ OSError_str(PyOSErrorObject *self)
}
if (self->myerrno && self->strerror)
return PyUnicode_FromFormat("[Errno %S] %S",
- self->myerrno ? self->myerrno: Py_None,
- self->strerror ? self->strerror: Py_None);
+ self->myerrno, self->strerror);
return BaseException_str((PyBaseExceptionObject *)self);
}
@@ -2478,6 +2478,7 @@ _PyExc_Init(PyObject *bltinmod)
PRE_INIT(SystemExit)
PRE_INIT(KeyboardInterrupt)
PRE_INIT(ImportError)
+ PRE_INIT(ModuleNotFoundError)
PRE_INIT(OSError)
PRE_INIT(EOFError)
PRE_INIT(RuntimeError)
@@ -2550,6 +2551,7 @@ _PyExc_Init(PyObject *bltinmod)
POST_INIT(SystemExit)
POST_INIT(KeyboardInterrupt)
POST_INIT(ImportError)
+ POST_INIT(ModuleNotFoundError)
POST_INIT(OSError)
INIT_ALIAS(EnvironmentError, OSError)
INIT_ALIAS(IOError, OSError)
@@ -2612,7 +2614,9 @@ _PyExc_Init(PyObject *bltinmod)
ADD_ERRNO(BlockingIOError, EWOULDBLOCK);
POST_INIT(BrokenPipeError);
ADD_ERRNO(BrokenPipeError, EPIPE);
+#ifdef ESHUTDOWN
ADD_ERRNO(BrokenPipeError, ESHUTDOWN);
+#endif
POST_INIT(ChildProcessError);
ADD_ERRNO(ChildProcessError, ECHILD);
POST_INIT(ConnectionAbortedError);
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 234d07e5c6..f4424184d2 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -127,7 +127,7 @@ PyFile_GetLine(PyObject *f, int n)
int
PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
{
- PyObject *writer, *value, *args, *result;
+ PyObject *writer, *value, *result;
_Py_IDENTIFIER(write);
if (f == NULL) {
@@ -146,14 +146,7 @@ PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
Py_DECREF(writer);
return -1;
}
- args = PyTuple_Pack(1, value);
- if (args == NULL) {
- Py_DECREF(value);
- Py_DECREF(writer);
- return -1;
- }
- result = PyEval_CallObject(writer, args);
- Py_DECREF(args);
+ result = _PyObject_CallArg1(writer, value);
Py_DECREF(value);
Py_DECREF(writer);
if (result == NULL)
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index d92bec35b5..80bf71efd2 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -124,11 +124,43 @@ PyFloat_FromDouble(double fval)
return (PyObject *) op;
}
+static PyObject *
+float_from_string_inner(const char *s, Py_ssize_t len, void *obj)
+{
+ double x;
+ const char *end;
+ const char *last = s + len;
+ /* strip space */
+ while (s < last && Py_ISSPACE(*s)) {
+ s++;
+ }
+
+ while (s < last - 1 && Py_ISSPACE(last[-1])) {
+ last--;
+ }
+
+ /* We don't care about overflow or underflow. If the platform
+ * supports them, infinities and signed zeroes (on underflow) are
+ * fine. */
+ x = PyOS_string_to_double(s, (char **)&end, NULL);
+ if (end != last) {
+ PyErr_Format(PyExc_ValueError,
+ "could not convert string to float: "
+ "%R", obj);
+ return NULL;
+ }
+ else if (x == -1.0 && PyErr_Occurred()) {
+ return NULL;
+ }
+ else {
+ return PyFloat_FromDouble(x);
+ }
+}
+
PyObject *
PyFloat_FromString(PyObject *v)
{
- const char *s, *last, *end;
- double x;
+ const char *s;
PyObject *s_buffer = NULL;
Py_ssize_t len;
Py_buffer view = {NULL, NULL};
@@ -169,27 +201,8 @@ PyFloat_FromString(PyObject *v)
Py_TYPE(v)->tp_name);
return NULL;
}
- last = s + len;
- /* strip space */
- while (s < last && Py_ISSPACE(*s))
- s++;
- while (s < last - 1 && Py_ISSPACE(last[-1]))
- last--;
- /* We don't care about overflow or underflow. If the platform
- * supports them, infinities and signed zeroes (on underflow) are
- * fine. */
- x = PyOS_string_to_double(s, (char **)&end, NULL);
- if (end != last) {
- PyErr_Format(PyExc_ValueError,
- "could not convert string to float: "
- "%R", v);
- result = NULL;
- }
- else if (x == -1.0 && PyErr_Occurred())
- result = NULL;
- else
- result = PyFloat_FromDouble(x);
-
+ result = _Py_string_to_number_with_underscores(s, len, "float", v, v,
+ float_from_string_inner);
PyBuffer_Release(&view);
Py_XDECREF(s_buffer);
return result;
@@ -215,35 +228,49 @@ double
PyFloat_AsDouble(PyObject *op)
{
PyNumberMethods *nb;
- PyFloatObject *fo;
+ PyObject *res;
double val;
- if (op && PyFloat_Check(op))
- return PyFloat_AS_DOUBLE((PyFloatObject*) op);
-
if (op == NULL) {
PyErr_BadArgument();
return -1;
}
- if ((nb = Py_TYPE(op)->tp_as_number) == NULL || nb->nb_float == NULL) {
- PyErr_SetString(PyExc_TypeError, "a float is required");
- return -1;
+ if (PyFloat_Check(op)) {
+ return PyFloat_AS_DOUBLE(op);
}
- fo = (PyFloatObject*) (*nb->nb_float) (op);
- if (fo == NULL)
- return -1;
- if (!PyFloat_Check(fo)) {
- Py_DECREF(fo);
- PyErr_SetString(PyExc_TypeError,
- "nb_float should return float object");
+ nb = Py_TYPE(op)->tp_as_number;
+ if (nb == NULL || nb->nb_float == NULL) {
+ PyErr_Format(PyExc_TypeError, "must be real number, not %.50s",
+ op->ob_type->tp_name);
return -1;
}
- val = PyFloat_AS_DOUBLE(fo);
- Py_DECREF(fo);
+ res = (*nb->nb_float) (op);
+ if (res == NULL) {
+ return -1;
+ }
+ if (!PyFloat_CheckExact(res)) {
+ if (!PyFloat_Check(res)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.50s.__float__ returned non-float (type %.50s)",
+ op->ob_type->tp_name, res->ob_type->tp_name);
+ Py_DECREF(res);
+ return -1;
+ }
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "%.50s.__float__ returned non-float (type %.50s). "
+ "The ability to return an instance of a strict subclass of float "
+ "is deprecated, and may be removed in a future version of Python.",
+ op->ob_type->tp_name, res->ob_type->tp_name)) {
+ Py_DECREF(res);
+ return -1;
+ }
+ }
+ val = PyFloat_AS_DOUBLE(res);
+ Py_DECREF(res);
return val;
}
@@ -1195,7 +1222,7 @@ Return a hexadecimal representation of a floating-point number.\n\
static PyObject *
float_fromhex(PyObject *cls, PyObject *arg)
{
- PyObject *result_as_float, *result;
+ PyObject *result;
double x;
long exp, top_exp, lsb, key_digit;
char *s, *coeff_start, *s_store, *coeff_end, *exp_start, *s_end;
@@ -1247,7 +1274,7 @@ float_fromhex(PyObject *cls, PyObject *arg)
* exp+4*ndigits and exp-4*ndigits are within the range of a long.
*/
- s = _PyUnicode_AsStringAndSize(arg, &length);
+ s = PyUnicode_AsUTF8AndSize(arg, &length);
if (s == NULL)
return NULL;
s_end = s + length;
@@ -1410,11 +1437,10 @@ float_fromhex(PyObject *cls, PyObject *arg)
s++;
if (s != s_end)
goto parse_error;
- result_as_float = Py_BuildValue("(d)", negate ? -x : x);
- if (result_as_float == NULL)
- return NULL;
- result = PyObject_CallObject(cls, result_as_float);
- Py_DECREF(result_as_float);
+ result = PyFloat_FromDouble(negate ? -x : x);
+ if (cls != (PyObject *)&PyFloat_Type && result != NULL) {
+ Py_SETREF(result, PyObject_CallFunctionObjArgs(cls, result, NULL));
+ }
return result;
overflow_error:
@@ -1451,29 +1477,23 @@ float_as_integer_ratio(PyObject *v, PyObject *unused)
int exponent;
int i;
- PyObject *prev;
PyObject *py_exponent = NULL;
PyObject *numerator = NULL;
PyObject *denominator = NULL;
PyObject *result_pair = NULL;
PyNumberMethods *long_methods = PyLong_Type.tp_as_number;
-#define INPLACE_UPDATE(obj, call) \
- prev = obj; \
- obj = call; \
- Py_DECREF(prev); \
-
CONVERT_TO_DOUBLE(v, self);
if (Py_IS_INFINITY(self)) {
- PyErr_SetString(PyExc_OverflowError,
- "Cannot pass infinity to float.as_integer_ratio.");
- return NULL;
+ PyErr_SetString(PyExc_OverflowError,
+ "cannot convert Infinity to integer ratio");
+ return NULL;
}
if (Py_IS_NAN(self)) {
- PyErr_SetString(PyExc_ValueError,
- "Cannot pass NaN to float.as_integer_ratio.");
- return NULL;
+ PyErr_SetString(PyExc_ValueError,
+ "cannot convert NaN to integer ratio");
+ return NULL;
}
PyFPE_START_PROTECT("as_integer_ratio", goto error);
@@ -1489,29 +1509,31 @@ float_as_integer_ratio(PyObject *v, PyObject *unused)
to be truncated by PyLong_FromDouble(). */
numerator = PyLong_FromDouble(float_part);
- if (numerator == NULL) goto error;
+ if (numerator == NULL)
+ goto error;
+ denominator = PyLong_FromLong(1);
+ if (denominator == NULL)
+ goto error;
+ py_exponent = PyLong_FromLong(Py_ABS(exponent));
+ if (py_exponent == NULL)
+ goto error;
/* fold in 2**exponent */
- denominator = PyLong_FromLong(1);
- py_exponent = PyLong_FromLong(labs((long)exponent));
- if (py_exponent == NULL) goto error;
- INPLACE_UPDATE(py_exponent,
- long_methods->nb_lshift(denominator, py_exponent));
- if (py_exponent == NULL) goto error;
if (exponent > 0) {
- INPLACE_UPDATE(numerator,
- long_methods->nb_multiply(numerator, py_exponent));
- if (numerator == NULL) goto error;
+ Py_SETREF(numerator,
+ long_methods->nb_lshift(numerator, py_exponent));
+ if (numerator == NULL)
+ goto error;
}
else {
- Py_DECREF(denominator);
- denominator = py_exponent;
- py_exponent = NULL;
+ Py_SETREF(denominator,
+ long_methods->nb_lshift(denominator, py_exponent));
+ if (denominator == NULL)
+ goto error;
}
result_pair = PyTuple_Pack(2, numerator, denominator);
-#undef INPLACE_UPDATE
error:
Py_XDECREF(py_exponent);
Py_XDECREF(denominator);
@@ -1606,7 +1628,7 @@ float_getformat(PyTypeObject *v, PyObject* arg)
Py_TYPE(arg)->tp_name);
return NULL;
}
- s = _PyUnicode_AsString(arg);
+ s = PyUnicode_AsUTF8(arg);
if (s == NULL)
return NULL;
if (strcmp(s, "double") == 0) {
@@ -1966,8 +1988,120 @@ _PyFloat_DebugMallocStats(FILE *out)
/*----------------------------------------------------------------------------
- * _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
+ * _PyFloat_{Pack,Unpack}{2,4,8}. See floatobject.h.
+ * To match the NPY_HALF_ROUND_TIES_TO_EVEN behavior in:
+ * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c
+ * We use:
+ * bits = (unsigned short)f; Note the truncation
+ * if ((f - bits > 0.5) || (f - bits == 0.5 && bits % 2)) {
+ * bits++;
+ * }
*/
+
+int
+_PyFloat_Pack2(double x, unsigned char *p, int le)
+{
+ unsigned char sign;
+ int e;
+ double f;
+ unsigned short bits;
+ int incr = 1;
+
+ if (x == 0.0) {
+ sign = (copysign(1.0, x) == -1.0);
+ e = 0;
+ bits = 0;
+ }
+ else if (Py_IS_INFINITY(x)) {
+ sign = (x < 0.0);
+ e = 0x1f;
+ bits = 0;
+ }
+ else if (Py_IS_NAN(x)) {
+ /* There are 2046 distinct half-precision NaNs (1022 signaling and
+ 1024 quiet), but there are only two quiet NaNs that don't arise by
+ quieting a signaling NaN; we get those by setting the topmost bit
+ of the fraction field and clearing all other fraction bits. We
+ choose the one with the appropriate sign. */
+ sign = (copysign(1.0, x) == -1.0);
+ e = 0x1f;
+ bits = 512;
+ }
+ else {
+ sign = (x < 0.0);
+ if (sign) {
+ x = -x;
+ }
+
+ f = frexp(x, &e);
+ if (f < 0.5 || f >= 1.0) {
+ PyErr_SetString(PyExc_SystemError,
+ "frexp() result out of range");
+ return -1;
+ }
+
+ /* Normalize f to be in the range [1.0, 2.0) */
+ f *= 2.0;
+ e--;
+
+ if (e >= 16) {
+ goto Overflow;
+ }
+ else if (e < -25) {
+ /* |x| < 2**-25. Underflow to zero. */
+ f = 0.0;
+ e = 0;
+ }
+ else if (e < -14) {
+ /* |x| < 2**-14. Gradual underflow */
+ f = ldexp(f, 14 + e);
+ e = 0;
+ }
+ else /* if (!(e == 0 && f == 0.0)) */ {
+ e += 15;
+ f -= 1.0; /* Get rid of leading 1 */
+ }
+
+ f *= 1024.0; /* 2**10 */
+ /* Round to even */
+ bits = (unsigned short)f; /* Note the truncation */
+ assert(bits < 1024);
+ assert(e < 31);
+ if ((f - bits > 0.5) || ((f - bits == 0.5) && (bits % 2 == 1))) {
+ ++bits;
+ if (bits == 1024) {
+ /* The carry propagated out of a string of 10 1 bits. */
+ bits = 0;
+ ++e;
+ if (e == 31)
+ goto Overflow;
+ }
+ }
+ }
+
+ bits |= (e << 10) | (sign << 15);
+
+ /* Write out result. */
+ if (le) {
+ p += 1;
+ incr = -1;
+ }
+
+ /* First byte */
+ *p = (unsigned char)((bits >> 8) & 0xFF);
+ p += incr;
+
+ /* Second byte */
+ *p = (unsigned char)(bits & 0xFF);
+
+ return 0;
+
+ Overflow:
+ PyErr_SetString(PyExc_OverflowError,
+ "float too large to pack with e format");
+ return -1;
+}
+
int
_PyFloat_Pack4(double x, unsigned char *p, int le)
{
@@ -2203,6 +2337,76 @@ _PyFloat_Pack8(double x, unsigned char *p, int le)
}
double
+_PyFloat_Unpack2(const unsigned char *p, int le)
+{
+ unsigned char sign;
+ int e;
+ unsigned int f;
+ double x;
+ int incr = 1;
+
+ if (le) {
+ p += 1;
+ incr = -1;
+ }
+
+ /* First byte */
+ sign = (*p >> 7) & 1;
+ e = (*p & 0x7C) >> 2;
+ f = (*p & 0x03) << 8;
+ p += incr;
+
+ /* Second byte */
+ f |= *p;
+
+ if (e == 0x1f) {
+#ifdef PY_NO_SHORT_FLOAT_REPR
+ if (f == 0) {
+ /* Infinity */
+ return sign ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ }
+ else {
+ /* NaN */
+#ifdef Py_NAN
+ return sign ? -Py_NAN : Py_NAN;
+#else
+ PyErr_SetString(
+ PyExc_ValueError,
+ "can't unpack IEEE 754 NaN "
+ "on platform that does not support NaNs");
+ return -1;
+#endif /* #ifdef Py_NAN */
+ }
+#else
+ if (f == 0) {
+ /* Infinity */
+ return _Py_dg_infinity(sign);
+ }
+ else {
+ /* NaN */
+ return _Py_dg_stdnan(sign);
+ }
+#endif /* #ifdef PY_NO_SHORT_FLOAT_REPR */
+ }
+
+ x = (double)f / 1024.0;
+
+ if (e == 0) {
+ e = -14;
+ }
+ else {
+ x += 1.0;
+ e -= 15;
+ }
+ x = ldexp(x, e);
+
+ if (sign)
+ x = -x;
+
+ return x;
+}
+
+double
_PyFloat_Unpack4(const unsigned char *p, int le)
{
if (float_format == unknown_format) {
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 9aadd61019..62f9f34c8e 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -137,7 +137,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
new_lasti = -1;
for (offset = 0; offset < lnotab_len; offset += 2) {
addr += lnotab[offset];
- line += lnotab[offset+1];
+ line += (signed char)lnotab[offset+1];
if (line >= new_lineno) {
new_lasti = addr;
new_lineno = line;
@@ -189,7 +189,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
memset(blockstack, '\0', sizeof(blockstack));
memset(in_finally, '\0', sizeof(in_finally));
blockstack_top = 0;
- for (addr = 0; addr < code_len; addr++) {
+ for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) {
unsigned char op = code[addr];
switch (op) {
case SETUP_LOOP:
@@ -251,10 +251,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
}
}
}
-
- if (op >= HAVE_ARGUMENT) {
- addr += 2;
- }
}
/* Verify that the blockstack tracking code didn't get lost. */
@@ -277,7 +273,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
* can tell whether the jump goes into any blocks without coming out
* again - in that case we raise an exception below. */
delta_iblock = 0;
- for (addr = min_addr; addr < max_addr; addr++) {
+ for (addr = min_addr; addr < max_addr; addr += sizeof(_Py_CODEUNIT)) {
unsigned char op = code[addr];
switch (op) {
case SETUP_LOOP:
@@ -294,10 +290,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
}
min_delta_iblock = Py_MIN(min_delta_iblock, delta_iblock);
-
- if (op >= HAVE_ARGUMENT) {
- addr += 2;
- }
}
/* Derive the absolute iblock values from the deltas. */
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index 4cd6590cae..69cd973384 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -249,7 +249,6 @@ func_get_code(PyFunctionObject *op)
static int
func_set_code(PyFunctionObject *op, PyObject *value)
{
- PyObject *tmp;
Py_ssize_t nfree, nclosure;
/* Not legal to del f.func_code or to set it to anything
@@ -270,10 +269,8 @@ func_set_code(PyFunctionObject *op, PyObject *value)
nclosure, nfree);
return -1;
}
- tmp = op->func_code;
Py_INCREF(value);
- op->func_code = value;
- Py_DECREF(tmp);
+ Py_XSETREF(op->func_code, value);
return 0;
}
@@ -287,8 +284,6 @@ func_get_name(PyFunctionObject *op)
static int
func_set_name(PyFunctionObject *op, PyObject *value)
{
- PyObject *tmp;
-
/* Not legal to del f.func_name or to set it to anything
* other than a string object. */
if (value == NULL || !PyUnicode_Check(value)) {
@@ -296,10 +291,8 @@ func_set_name(PyFunctionObject *op, PyObject *value)
"__name__ must be set to a string object");
return -1;
}
- tmp = op->func_name;
Py_INCREF(value);
- op->func_name = value;
- Py_DECREF(tmp);
+ Py_XSETREF(op->func_name, value);
return 0;
}
@@ -313,8 +306,6 @@ func_get_qualname(PyFunctionObject *op)
static int
func_set_qualname(PyFunctionObject *op, PyObject *value)
{
- PyObject *tmp;
-
/* Not legal to del f.__qualname__ or to set it to anything
* other than a string object. */
if (value == NULL || !PyUnicode_Check(value)) {
@@ -322,10 +313,8 @@ func_set_qualname(PyFunctionObject *op, PyObject *value)
"__qualname__ must be set to a string object");
return -1;
}
- tmp = op->func_qualname;
Py_INCREF(value);
- op->func_qualname = value;
- Py_DECREF(tmp);
+ Py_XSETREF(op->func_qualname, value);
return 0;
}
@@ -343,8 +332,6 @@ func_get_defaults(PyFunctionObject *op)
static int
func_set_defaults(PyFunctionObject *op, PyObject *value)
{
- PyObject *tmp;
-
/* Legal to del f.func_defaults.
* Can only set func_defaults to NULL or a tuple. */
if (value == Py_None)
@@ -354,10 +341,8 @@ func_set_defaults(PyFunctionObject *op, PyObject *value)
"__defaults__ must be set to a tuple object");
return -1;
}
- tmp = op->func_defaults;
Py_XINCREF(value);
- op->func_defaults = value;
- Py_XDECREF(tmp);
+ Py_XSETREF(op->func_defaults, value);
return 0;
}
@@ -375,8 +360,6 @@ func_get_kwdefaults(PyFunctionObject *op)
static int
func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
{
- PyObject *tmp;
-
if (value == Py_None)
value = NULL;
/* Legal to del f.func_kwdefaults.
@@ -386,10 +369,8 @@ func_set_kwdefaults(PyFunctionObject *op, PyObject *value)
"__kwdefaults__ must be set to a dict object");
return -1;
}
- tmp = op->func_kwdefaults;
Py_XINCREF(value);
- op->func_kwdefaults = value;
- Py_XDECREF(tmp);
+ Py_XSETREF(op->func_kwdefaults, value);
return 0;
}
@@ -408,8 +389,6 @@ func_get_annotations(PyFunctionObject *op)
static int
func_set_annotations(PyFunctionObject *op, PyObject *value)
{
- PyObject *tmp;
-
if (value == Py_None)
value = NULL;
/* Legal to del f.func_annotations.
@@ -420,10 +399,8 @@ func_set_annotations(PyFunctionObject *op, PyObject *value)
"__annotations__ must be set to a dict object");
return -1;
}
- tmp = op->func_annotations;
Py_XINCREF(value);
- op->func_annotations = value;
- Py_XDECREF(tmp);
+ Py_XSETREF(op->func_annotations, value);
return 0;
}
diff --git a/Objects/genobject.c b/Objects/genobject.c
index d403598181..2680ab0e12 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -5,7 +5,15 @@
#include "structmember.h"
#include "opcode.h"
-static PyObject *gen_close(PyGenObject *gen, PyObject *args);
+static PyObject *gen_close(PyGenObject *, PyObject *);
+static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *);
+static PyObject *async_gen_athrow_new(PyAsyncGenObject *, PyObject *);
+
+static char *NON_INIT_CORO_MSG = "can't send non-None value to a "
+ "just-started coroutine";
+
+static char *ASYNC_GEN_IGNORED_EXIT_MSG =
+ "async generator ignored GeneratorExit";
static int
gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
@@ -28,6 +36,26 @@ _PyGen_Finalize(PyObject *self)
/* Generator isn't paused, so no need to close */
return;
+ if (PyAsyncGen_CheckExact(self)) {
+ PyAsyncGenObject *agen = (PyAsyncGenObject*)self;
+ PyObject *finalizer = agen->ag_finalizer;
+ if (finalizer && !agen->ag_closed) {
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ res = PyObject_CallFunctionObjArgs(finalizer, self, NULL);
+
+ if (res == NULL) {
+ PyErr_WriteUnraisable(self);
+ } else {
+ Py_DECREF(res);
+ }
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+ return;
+ }
+ }
+
/* Save the current exception, if any. */
PyErr_Fetch(&error_type, &error_value, &error_traceback);
@@ -74,6 +102,12 @@ gen_dealloc(PyGenObject *gen)
return; /* resurrected. :( */
_PyObject_GC_UNTRACK(self);
+ if (PyAsyncGen_CheckExact(gen)) {
+ /* We have to handle this case for asynchronous generators
+ right here, because this code has to be between UNTRACK
+ and GC_Del. */
+ Py_CLEAR(((PyAsyncGenObject*)gen)->ag_finalizer);
+ }
if (gen->gi_frame != NULL) {
gen->gi_frame->f_gen = NULL;
Py_CLEAR(gen->gi_frame);
@@ -93,8 +127,12 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
if (gen->gi_running) {
char *msg = "generator already executing";
- if (PyCoro_CheckExact(gen))
+ if (PyCoro_CheckExact(gen)) {
msg = "coroutine already executing";
+ }
+ else if (PyAsyncGen_CheckExact(gen)) {
+ msg = "async generator already executing";
+ }
PyErr_SetString(PyExc_ValueError, msg);
return NULL;
}
@@ -106,10 +144,16 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
PyErr_SetString(
PyExc_RuntimeError,
"cannot reuse already awaited coroutine");
- } else if (arg && !exc) {
+ }
+ else if (arg && !exc) {
/* `gen` is an exhausted generator:
only set exception if called from send(). */
- PyErr_SetNone(PyExc_StopIteration);
+ if (PyAsyncGen_CheckExact(gen)) {
+ PyErr_SetNone(PyExc_StopAsyncIteration);
+ }
+ else {
+ PyErr_SetNone(PyExc_StopIteration);
+ }
}
return NULL;
}
@@ -118,9 +162,13 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
if (arg && arg != Py_None) {
char *msg = "can't send non-None value to a "
"just-started generator";
- if (PyCoro_CheckExact(gen))
+ if (PyCoro_CheckExact(gen)) {
+ msg = NON_INIT_CORO_MSG;
+ }
+ else if (PyAsyncGen_CheckExact(gen)) {
msg = "can't send non-None value to a "
- "just-started coroutine";
+ "just-started async generator";
+ }
PyErr_SetString(PyExc_TypeError, msg);
return NULL;
}
@@ -152,8 +200,16 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
if (result && f->f_stacktop == NULL) {
if (result == Py_None) {
/* Delay exception instantiation if we can */
- PyErr_SetNone(PyExc_StopIteration);
- } else {
+ if (PyAsyncGen_CheckExact(gen)) {
+ PyErr_SetNone(PyExc_StopAsyncIteration);
+ }
+ else {
+ PyErr_SetNone(PyExc_StopIteration);
+ }
+ }
+ else {
+ /* Async generators cannot return anything but None */
+ assert(!PyAsyncGen_CheckExact(gen));
_PyGen_SetStopIterationValue(result);
}
Py_CLEAR(result);
@@ -162,34 +218,43 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
/* Check for __future__ generator_stop and conditionally turn
* a leaking StopIteration into RuntimeError (with its cause
* set appropriately). */
- if (((PyCodeObject *)gen->gi_code)->co_flags &
- (CO_FUTURE_GENERATOR_STOP | CO_COROUTINE | CO_ITERABLE_COROUTINE))
+
+ const int check_stop_iter_error_flags = CO_FUTURE_GENERATOR_STOP |
+ CO_COROUTINE |
+ CO_ITERABLE_COROUTINE |
+ CO_ASYNC_GENERATOR;
+
+ if (gen->gi_code != NULL &&
+ ((PyCodeObject *)gen->gi_code)->co_flags &
+ check_stop_iter_error_flags)
{
- PyObject *exc, *val, *val2, *tb;
- char *msg = "generator raised StopIteration";
- if (PyCoro_CheckExact(gen))
+ /* `gen` is either:
+ * a generator with CO_FUTURE_GENERATOR_STOP flag;
+ * a coroutine;
+ * a generator with CO_ITERABLE_COROUTINE flag
+ (decorated with types.coroutine decorator);
+ * an async generator.
+ */
+ const char *msg = "generator raised StopIteration";
+ if (PyCoro_CheckExact(gen)) {
msg = "coroutine raised StopIteration";
- PyErr_Fetch(&exc, &val, &tb);
- PyErr_NormalizeException(&exc, &val, &tb);
- if (tb != NULL)
- PyException_SetTraceback(val, tb);
- Py_DECREF(exc);
- Py_XDECREF(tb);
- PyErr_SetString(PyExc_RuntimeError, msg);
- PyErr_Fetch(&exc, &val2, &tb);
- PyErr_NormalizeException(&exc, &val2, &tb);
- Py_INCREF(val);
- PyException_SetCause(val2, val);
- PyException_SetContext(val2, val);
- PyErr_Restore(exc, val2, tb);
+ }
+ else if PyAsyncGen_CheckExact(gen) {
+ msg = "async generator raised StopIteration";
+ }
+ _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
}
else {
+ /* `gen` is an ordinary generator without
+ CO_FUTURE_GENERATOR_STOP flag.
+ */
+
PyObject *exc, *val, *tb;
/* Pop the exception before issuing a warning. */
PyErr_Fetch(&exc, &val, &tb);
- if (PyErr_WarnFormat(PyExc_PendingDeprecationWarning, 1,
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"generator '%.50S' raised StopIteration",
gen->gi_qualname)) {
/* Warning was converted to an error. */
@@ -202,6 +267,15 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
}
}
}
+ else if (PyAsyncGen_CheckExact(gen) && !result &&
+ PyErr_ExceptionMatches(PyExc_StopAsyncIteration))
+ {
+ /* code in `gen` raised a StopAsyncIteration error:
+ raise a RuntimeError.
+ */
+ const char *msg = "async generator raised StopAsyncIteration";
+ _PyErr_FormatFromCause(PyExc_RuntimeError, "%s", msg);
+ }
if (!result || f->f_stacktop == NULL) {
/* generator can't be rerun, so release the frame */
@@ -248,18 +322,20 @@ gen_close_iter(PyObject *yf)
PyObject *retval = NULL;
_Py_IDENTIFIER(close);
- if (PyGen_CheckExact(yf)) {
+ if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
retval = gen_close((PyGenObject *)yf, NULL);
if (retval == NULL)
return -1;
- } else {
+ }
+ else {
PyObject *meth = _PyObject_GetAttrId(yf, &PyId_close);
if (meth == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
PyErr_WriteUnraisable(yf);
PyErr_Clear();
- } else {
- retval = PyObject_CallFunction(meth, "");
+ }
+ else {
+ retval = _PyObject_CallNoArg(meth);
Py_DECREF(meth);
if (retval == NULL)
return -1;
@@ -279,7 +355,15 @@ _PyGen_yf(PyGenObject *gen)
PyObject *bytecode = f->f_code->co_code;
unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
- if (code[f->f_lasti + 1] != YIELD_FROM)
+ if (f->f_lasti < 0) {
+ /* Return immediately if the frame didn't start yet. YIELD_FROM
+ always come after LOAD_CONST: a code object should not start
+ with YIELD_FROM */
+ assert(code[0] != YIELD_FROM);
+ return NULL;
+ }
+
+ if (code[f->f_lasti + sizeof(_Py_CODEUNIT)] != YIELD_FROM)
return NULL;
yf = f->f_stacktop[-1];
Py_INCREF(yf);
@@ -306,8 +390,11 @@ gen_close(PyGenObject *gen, PyObject *args)
retval = gen_send_ex(gen, Py_None, 1, 1);
if (retval) {
char *msg = "generator ignored GeneratorExit";
- if (PyCoro_CheckExact(gen))
+ if (PyCoro_CheckExact(gen)) {
msg = "coroutine ignored GeneratorExit";
+ } else if (PyAsyncGen_CheckExact(gen)) {
+ msg = ASYNC_GEN_IGNORED_EXIT_MSG;
+ }
Py_DECREF(retval);
PyErr_SetString(PyExc_RuntimeError, msg);
return NULL;
@@ -327,21 +414,22 @@ PyDoc_STRVAR(throw_doc,
return next yielded value or raise StopIteration.");
static PyObject *
-gen_throw(PyGenObject *gen, PyObject *args)
+_gen_throw(PyGenObject *gen, int close_on_genexit,
+ PyObject *typ, PyObject *val, PyObject *tb)
{
- PyObject *typ;
- PyObject *tb = NULL;
- PyObject *val = NULL;
PyObject *yf = _PyGen_yf(gen);
_Py_IDENTIFIER(throw);
- if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
- return NULL;
-
if (yf) {
PyObject *ret;
int err;
- if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
+ if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) &&
+ close_on_genexit
+ ) {
+ /* Asynchronous generators *should not* be closed right away.
+ We have to allow some awaits to work it through, hence the
+ `close_on_genexit` parameter here.
+ */
gen->gi_running = 1;
err = gen_close_iter(yf);
gen->gi_running = 0;
@@ -350,11 +438,16 @@ gen_throw(PyGenObject *gen, PyObject *args)
return gen_send_ex(gen, Py_None, 1, 0);
goto throw_here;
}
- if (PyGen_CheckExact(yf)) {
+ if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) {
+ /* `yf` is a generator or a coroutine. */
gen->gi_running = 1;
- ret = gen_throw((PyGenObject *)yf, args);
+ /* Close the generator that we are currently iterating with
+ 'yield from' or awaiting on with 'await'. */
+ ret = _gen_throw((PyGenObject *)yf, close_on_genexit,
+ typ, val, tb);
gen->gi_running = 0;
} else {
+ /* `yf` is an iterator or a coroutine-like object. */
PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
if (meth == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -366,7 +459,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
goto throw_here;
}
gen->gi_running = 1;
- ret = PyObject_CallObject(meth, args);
+ ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL);
gen->gi_running = 0;
Py_DECREF(meth);
}
@@ -378,7 +471,8 @@ gen_throw(PyGenObject *gen, PyObject *args)
assert(ret == yf);
Py_DECREF(ret);
/* Termination repetition of YIELD_FROM */
- gen->gi_frame->f_lasti++;
+ assert(gen->gi_frame->f_lasti >= 0);
+ gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT);
if (_PyGen_FetchStopIterationValue(&val) == 0) {
ret = gen_send_ex(gen, val, 0, 0);
Py_DECREF(val);
@@ -449,6 +543,21 @@ failed_throw:
static PyObject *
+gen_throw(PyGenObject *gen, PyObject *args)
+{
+ PyObject *typ;
+ PyObject *tb = NULL;
+ PyObject *val = NULL;
+
+ if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) {
+ return NULL;
+ }
+
+ return _gen_throw(gen, 1, typ, val, tb);
+}
+
+
+static PyObject *
gen_iternext(PyGenObject *gen)
{
return gen_send_ex(gen, NULL, 0, 0);
@@ -566,8 +675,6 @@ gen_get_name(PyGenObject *op)
static int
gen_set_name(PyGenObject *op, PyObject *value)
{
- PyObject *tmp;
-
/* Not legal to del gen.gi_name or to set it to anything
* other than a string object. */
if (value == NULL || !PyUnicode_Check(value)) {
@@ -575,10 +682,8 @@ gen_set_name(PyGenObject *op, PyObject *value)
"__name__ must be set to a string object");
return -1;
}
- tmp = op->gi_name;
Py_INCREF(value);
- op->gi_name = value;
- Py_DECREF(tmp);
+ Py_XSETREF(op->gi_name, value);
return 0;
}
@@ -592,8 +697,6 @@ gen_get_qualname(PyGenObject *op)
static int
gen_set_qualname(PyGenObject *op, PyObject *value)
{
- PyObject *tmp;
-
/* Not legal to del gen.__qualname__ or to set it to anything
* other than a string object. */
if (value == NULL || !PyUnicode_Check(value)) {
@@ -601,10 +704,8 @@ gen_set_qualname(PyGenObject *op, PyObject *value)
"__qualname__ must be set to a string object");
return -1;
}
- tmp = op->gi_qualname;
Py_INCREF(value);
- op->gi_qualname = value;
- Py_DECREF(tmp);
+ Py_XSETREF(op->gi_qualname, value);
return 0;
}
@@ -1045,21 +1146,21 @@ PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
typedef struct {
PyObject_HEAD
- PyObject *aw_aiter;
+ PyObject *ags_aiter;
} PyAIterWrapper;
static PyObject *
aiter_wrapper_iternext(PyAIterWrapper *aw)
{
- _PyGen_SetStopIterationValue(aw->aw_aiter);
+ _PyGen_SetStopIterationValue(aw->ags_aiter);
return NULL;
}
static int
aiter_wrapper_traverse(PyAIterWrapper *aw, visitproc visit, void *arg)
{
- Py_VISIT((PyObject *)aw->aw_aiter);
+ Py_VISIT((PyObject *)aw->ags_aiter);
return 0;
}
@@ -1067,7 +1168,7 @@ static void
aiter_wrapper_dealloc(PyAIterWrapper *aw)
{
_PyObject_GC_UNTRACK((PyObject *)aw);
- Py_CLEAR(aw->aw_aiter);
+ Py_CLEAR(aw->ags_aiter);
PyObject_GC_Del(aw);
}
@@ -1129,7 +1230,851 @@ _PyAIterWrapper_New(PyObject *aiter)
return NULL;
}
Py_INCREF(aiter);
- aw->aw_aiter = aiter;
+ aw->ags_aiter = aiter;
_PyObject_GC_TRACK(aw);
return (PyObject *)aw;
}
+
+
+/* ========= Asynchronous Generators ========= */
+
+
+typedef enum {
+ AWAITABLE_STATE_INIT, /* new awaitable, has not yet been iterated */
+ AWAITABLE_STATE_ITER, /* being iterated */
+ AWAITABLE_STATE_CLOSED, /* closed */
+} AwaitableState;
+
+
+typedef struct {
+ PyObject_HEAD
+ PyAsyncGenObject *ags_gen;
+
+ /* Can be NULL, when in the __anext__() mode
+ (equivalent of "asend(None)") */
+ PyObject *ags_sendval;
+
+ AwaitableState ags_state;
+} PyAsyncGenASend;
+
+
+typedef struct {
+ PyObject_HEAD
+ PyAsyncGenObject *agt_gen;
+
+ /* Can be NULL, when in the "aclose()" mode
+ (equivalent of "athrow(GeneratorExit)") */
+ PyObject *agt_args;
+
+ AwaitableState agt_state;
+} PyAsyncGenAThrow;
+
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *agw_val;
+} _PyAsyncGenWrappedValue;
+
+
+#ifndef _PyAsyncGen_MAXFREELIST
+#define _PyAsyncGen_MAXFREELIST 80
+#endif
+
+/* Freelists boost performance 6-10%; they also reduce memory
+ fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
+ are short-living objects that are instantiated for every
+ __anext__ call.
+*/
+
+static _PyAsyncGenWrappedValue *ag_value_freelist[_PyAsyncGen_MAXFREELIST];
+static int ag_value_freelist_free = 0;
+
+static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST];
+static int ag_asend_freelist_free = 0;
+
+#define _PyAsyncGenWrappedValue_CheckExact(o) \
+ (Py_TYPE(o) == &_PyAsyncGenWrappedValue_Type)
+
+#define PyAsyncGenASend_CheckExact(o) \
+ (Py_TYPE(o) == &_PyAsyncGenASend_Type)
+
+
+static int
+async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg)
+{
+ Py_VISIT(gen->ag_finalizer);
+ return gen_traverse((PyGenObject*)gen, visit, arg);
+}
+
+
+static PyObject *
+async_gen_repr(PyAsyncGenObject *o)
+{
+ return PyUnicode_FromFormat("<async_generator object %S at %p>",
+ o->ag_qualname, o);
+}
+
+
+static int
+async_gen_init_hooks(PyAsyncGenObject *o)
+{
+ PyThreadState *tstate;
+ PyObject *finalizer;
+ PyObject *firstiter;
+
+ if (o->ag_hooks_inited) {
+ return 0;
+ }
+
+ o->ag_hooks_inited = 1;
+
+ tstate = PyThreadState_GET();
+
+ finalizer = tstate->async_gen_finalizer;
+ if (finalizer) {
+ Py_INCREF(finalizer);
+ o->ag_finalizer = finalizer;
+ }
+
+ firstiter = tstate->async_gen_firstiter;
+ if (firstiter) {
+ PyObject *res;
+
+ Py_INCREF(firstiter);
+ res = PyObject_CallFunction(firstiter, "O", o);
+ Py_DECREF(firstiter);
+ if (res == NULL) {
+ return 1;
+ }
+ Py_DECREF(res);
+ }
+
+ return 0;
+}
+
+
+static PyObject *
+async_gen_anext(PyAsyncGenObject *o)
+{
+ if (async_gen_init_hooks(o)) {
+ return NULL;
+ }
+ return async_gen_asend_new(o, NULL);
+}
+
+
+static PyObject *
+async_gen_asend(PyAsyncGenObject *o, PyObject *arg)
+{
+ if (async_gen_init_hooks(o)) {
+ return NULL;
+ }
+ return async_gen_asend_new(o, arg);
+}
+
+
+static PyObject *
+async_gen_aclose(PyAsyncGenObject *o, PyObject *arg)
+{
+ if (async_gen_init_hooks(o)) {
+ return NULL;
+ }
+ return async_gen_athrow_new(o, NULL);
+}
+
+static PyObject *
+async_gen_athrow(PyAsyncGenObject *o, PyObject *args)
+{
+ if (async_gen_init_hooks(o)) {
+ return NULL;
+ }
+ return async_gen_athrow_new(o, args);
+}
+
+
+static PyGetSetDef async_gen_getsetlist[] = {
+ {"__name__", (getter)gen_get_name, (setter)gen_set_name,
+ PyDoc_STR("name of the async generator")},
+ {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
+ PyDoc_STR("qualified name of the async generator")},
+ {"ag_await", (getter)coro_get_cr_await, NULL,
+ PyDoc_STR("object being awaited on, or None")},
+ {NULL} /* Sentinel */
+};
+
+static PyMemberDef async_gen_memberlist[] = {
+ {"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), READONLY},
+ {"ag_running", T_BOOL, offsetof(PyAsyncGenObject, ag_running), READONLY},
+ {"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), READONLY},
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(async_aclose_doc,
+"aclose() -> raise GeneratorExit inside generator.");
+
+PyDoc_STRVAR(async_asend_doc,
+"asend(v) -> send 'v' in generator.");
+
+PyDoc_STRVAR(async_athrow_doc,
+"athrow(typ[,val[,tb]]) -> raise exception in generator.");
+
+static PyMethodDef async_gen_methods[] = {
+ {"asend", (PyCFunction)async_gen_asend, METH_O, async_asend_doc},
+ {"athrow",(PyCFunction)async_gen_athrow, METH_VARARGS, async_athrow_doc},
+ {"aclose", (PyCFunction)async_gen_aclose, METH_NOARGS, async_aclose_doc},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+static PyAsyncMethods async_gen_as_async = {
+ 0, /* am_await */
+ PyObject_SelfIter, /* am_aiter */
+ (unaryfunc)async_gen_anext /* am_anext */
+};
+
+
+PyTypeObject PyAsyncGen_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "async_generator", /* tp_name */
+ sizeof(PyAsyncGenObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)gen_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ &async_gen_as_async, /* tp_as_async */
+ (reprfunc)async_gen_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)async_gen_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(PyAsyncGenObject, ag_weakreflist), /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ async_gen_methods, /* tp_methods */
+ async_gen_memberlist, /* tp_members */
+ async_gen_getsetlist, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0, /* tp_version_tag */
+ _PyGen_Finalize, /* tp_finalize */
+};
+
+
+PyObject *
+PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
+{
+ PyAsyncGenObject *o;
+ o = (PyAsyncGenObject *)gen_new_with_qualname(
+ &PyAsyncGen_Type, f, name, qualname);
+ if (o == NULL) {
+ return NULL;
+ }
+ o->ag_finalizer = NULL;
+ o->ag_closed = 0;
+ o->ag_hooks_inited = 0;
+ return (PyObject*)o;
+}
+
+
+int
+PyAsyncGen_ClearFreeLists(void)
+{
+ int ret = ag_value_freelist_free + ag_asend_freelist_free;
+
+ while (ag_value_freelist_free) {
+ _PyAsyncGenWrappedValue *o;
+ o = ag_value_freelist[--ag_value_freelist_free];
+ assert(_PyAsyncGenWrappedValue_CheckExact(o));
+ PyObject_GC_Del(o);
+ }
+
+ while (ag_asend_freelist_free) {
+ PyAsyncGenASend *o;
+ o = ag_asend_freelist[--ag_asend_freelist_free];
+ assert(Py_TYPE(o) == &_PyAsyncGenASend_Type);
+ PyObject_GC_Del(o);
+ }
+
+ return ret;
+}
+
+void
+PyAsyncGen_Fini(void)
+{
+ PyAsyncGen_ClearFreeLists();
+}
+
+
+static PyObject *
+async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result)
+{
+ if (result == NULL) {
+ if (!PyErr_Occurred()) {
+ PyErr_SetNone(PyExc_StopAsyncIteration);
+ }
+
+ if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)
+ || PyErr_ExceptionMatches(PyExc_GeneratorExit)
+ ) {
+ gen->ag_closed = 1;
+ }
+
+ return NULL;
+ }
+
+ if (_PyAsyncGenWrappedValue_CheckExact(result)) {
+ /* async yield */
+ _PyGen_SetStopIterationValue(((_PyAsyncGenWrappedValue*)result)->agw_val);
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+
+/* ---------- Async Generator ASend Awaitable ------------ */
+
+
+static void
+async_gen_asend_dealloc(PyAsyncGenASend *o)
+{
+ _PyObject_GC_UNTRACK((PyObject *)o);
+ Py_CLEAR(o->ags_gen);
+ Py_CLEAR(o->ags_sendval);
+ if (ag_asend_freelist_free < _PyAsyncGen_MAXFREELIST) {
+ assert(PyAsyncGenASend_CheckExact(o));
+ ag_asend_freelist[ag_asend_freelist_free++] = o;
+ } else {
+ PyObject_GC_Del(o);
+ }
+}
+
+static int
+async_gen_asend_traverse(PyAsyncGenASend *o, visitproc visit, void *arg)
+{
+ Py_VISIT(o->ags_gen);
+ Py_VISIT(o->ags_sendval);
+ return 0;
+}
+
+
+static PyObject *
+async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg)
+{
+ PyObject *result;
+
+ if (o->ags_state == AWAITABLE_STATE_CLOSED) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ if (o->ags_state == AWAITABLE_STATE_INIT) {
+ if (arg == NULL || arg == Py_None) {
+ arg = o->ags_sendval;
+ }
+ o->ags_state = AWAITABLE_STATE_ITER;
+ }
+
+ result = gen_send_ex((PyGenObject*)o->ags_gen, arg, 0, 0);
+ result = async_gen_unwrap_value(o->ags_gen, result);
+
+ if (result == NULL) {
+ o->ags_state = AWAITABLE_STATE_CLOSED;
+ }
+
+ return result;
+}
+
+
+static PyObject *
+async_gen_asend_iternext(PyAsyncGenASend *o)
+{
+ return async_gen_asend_send(o, NULL);
+}
+
+
+static PyObject *
+async_gen_asend_throw(PyAsyncGenASend *o, PyObject *args)
+{
+ PyObject *result;
+
+ if (o->ags_state == AWAITABLE_STATE_CLOSED) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ result = gen_throw((PyGenObject*)o->ags_gen, args);
+ result = async_gen_unwrap_value(o->ags_gen, result);
+
+ if (result == NULL) {
+ o->ags_state = AWAITABLE_STATE_CLOSED;
+ }
+
+ return result;
+}
+
+
+static PyObject *
+async_gen_asend_close(PyAsyncGenASend *o, PyObject *args)
+{
+ o->ags_state = AWAITABLE_STATE_CLOSED;
+ Py_RETURN_NONE;
+}
+
+
+static PyMethodDef async_gen_asend_methods[] = {
+ {"send", (PyCFunction)async_gen_asend_send, METH_O, send_doc},
+ {"throw", (PyCFunction)async_gen_asend_throw, METH_VARARGS, throw_doc},
+ {"close", (PyCFunction)async_gen_asend_close, METH_NOARGS, close_doc},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+static PyAsyncMethods async_gen_asend_as_async = {
+ PyObject_SelfIter, /* am_await */
+ 0, /* am_aiter */
+ 0 /* am_anext */
+};
+
+
+PyTypeObject _PyAsyncGenASend_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "async_generator_asend", /* tp_name */
+ sizeof(PyAsyncGenASend), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)async_gen_asend_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ &async_gen_asend_as_async, /* tp_as_async */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)async_gen_asend_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)async_gen_asend_iternext, /* tp_iternext */
+ async_gen_asend_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+static PyObject *
+async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval)
+{
+ PyAsyncGenASend *o;
+ if (ag_asend_freelist_free) {
+ ag_asend_freelist_free--;
+ o = ag_asend_freelist[ag_asend_freelist_free];
+ _Py_NewReference((PyObject *)o);
+ } else {
+ o = PyObject_GC_New(PyAsyncGenASend, &_PyAsyncGenASend_Type);
+ if (o == NULL) {
+ return NULL;
+ }
+ }
+
+ Py_INCREF(gen);
+ o->ags_gen = gen;
+
+ Py_XINCREF(sendval);
+ o->ags_sendval = sendval;
+
+ o->ags_state = AWAITABLE_STATE_INIT;
+
+ _PyObject_GC_TRACK((PyObject*)o);
+ return (PyObject*)o;
+}
+
+
+/* ---------- Async Generator Value Wrapper ------------ */
+
+
+static void
+async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o)
+{
+ _PyObject_GC_UNTRACK((PyObject *)o);
+ Py_CLEAR(o->agw_val);
+ if (ag_value_freelist_free < _PyAsyncGen_MAXFREELIST) {
+ assert(_PyAsyncGenWrappedValue_CheckExact(o));
+ ag_value_freelist[ag_value_freelist_free++] = o;
+ } else {
+ PyObject_GC_Del(o);
+ }
+}
+
+
+static int
+async_gen_wrapped_val_traverse(_PyAsyncGenWrappedValue *o,
+ visitproc visit, void *arg)
+{
+ Py_VISIT(o->agw_val);
+ return 0;
+}
+
+
+PyTypeObject _PyAsyncGenWrappedValue_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "async_generator_wrapped_value", /* tp_name */
+ sizeof(_PyAsyncGenWrappedValue), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)async_gen_wrapped_val_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_as_async */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)async_gen_wrapped_val_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+PyObject *
+_PyAsyncGenValueWrapperNew(PyObject *val)
+{
+ _PyAsyncGenWrappedValue *o;
+ assert(val);
+
+ if (ag_value_freelist_free) {
+ ag_value_freelist_free--;
+ o = ag_value_freelist[ag_value_freelist_free];
+ assert(_PyAsyncGenWrappedValue_CheckExact(o));
+ _Py_NewReference((PyObject*)o);
+ } else {
+ o = PyObject_GC_New(_PyAsyncGenWrappedValue,
+ &_PyAsyncGenWrappedValue_Type);
+ if (o == NULL) {
+ return NULL;
+ }
+ }
+ o->agw_val = val;
+ Py_INCREF(val);
+ _PyObject_GC_TRACK((PyObject*)o);
+ return (PyObject*)o;
+}
+
+
+/* ---------- Async Generator AThrow awaitable ------------ */
+
+
+static void
+async_gen_athrow_dealloc(PyAsyncGenAThrow *o)
+{
+ _PyObject_GC_UNTRACK((PyObject *)o);
+ Py_CLEAR(o->agt_gen);
+ Py_CLEAR(o->agt_args);
+ PyObject_GC_Del(o);
+}
+
+
+static int
+async_gen_athrow_traverse(PyAsyncGenAThrow *o, visitproc visit, void *arg)
+{
+ Py_VISIT(o->agt_gen);
+ Py_VISIT(o->agt_args);
+ return 0;
+}
+
+
+static PyObject *
+async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg)
+{
+ PyGenObject *gen = (PyGenObject*)o->agt_gen;
+ PyFrameObject *f = gen->gi_frame;
+ PyObject *retval;
+
+ if (f == NULL || f->f_stacktop == NULL ||
+ o->agt_state == AWAITABLE_STATE_CLOSED) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ if (o->agt_state == AWAITABLE_STATE_INIT) {
+ if (o->agt_gen->ag_closed) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ if (arg != Py_None) {
+ PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
+ return NULL;
+ }
+
+ o->agt_state = AWAITABLE_STATE_ITER;
+
+ if (o->agt_args == NULL) {
+ /* aclose() mode */
+ o->agt_gen->ag_closed = 1;
+
+ retval = _gen_throw((PyGenObject *)gen,
+ 0, /* Do not close generator when
+ PyExc_GeneratorExit is passed */
+ PyExc_GeneratorExit, NULL, NULL);
+
+ if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
+ Py_DECREF(retval);
+ goto yield_close;
+ }
+ } else {
+ PyObject *typ;
+ PyObject *tb = NULL;
+ PyObject *val = NULL;
+
+ if (!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3,
+ &typ, &val, &tb)) {
+ return NULL;
+ }
+
+ retval = _gen_throw((PyGenObject *)gen,
+ 0, /* Do not close generator when
+ PyExc_GeneratorExit is passed */
+ typ, val, tb);
+ retval = async_gen_unwrap_value(o->agt_gen, retval);
+ }
+ if (retval == NULL) {
+ goto check_error;
+ }
+ return retval;
+ }
+
+ assert(o->agt_state == AWAITABLE_STATE_ITER);
+
+ retval = gen_send_ex((PyGenObject *)gen, arg, 0, 0);
+ if (o->agt_args) {
+ return async_gen_unwrap_value(o->agt_gen, retval);
+ } else {
+ /* aclose() mode */
+ if (retval) {
+ if (_PyAsyncGenWrappedValue_CheckExact(retval)) {
+ Py_DECREF(retval);
+ goto yield_close;
+ }
+ else {
+ return retval;
+ }
+ }
+ else {
+ goto check_error;
+ }
+ }
+
+yield_close:
+ PyErr_SetString(
+ PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
+ return NULL;
+
+check_error:
+ if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) {
+ o->agt_state = AWAITABLE_STATE_CLOSED;
+ if (o->agt_args == NULL) {
+ /* when aclose() is called we don't want to propagate
+ StopAsyncIteration; just raise StopIteration, signalling
+ that 'aclose()' is done. */
+ PyErr_Clear();
+ PyErr_SetNone(PyExc_StopIteration);
+ }
+ }
+ else if (PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
+ o->agt_state = AWAITABLE_STATE_CLOSED;
+ PyErr_Clear(); /* ignore these errors */
+ PyErr_SetNone(PyExc_StopIteration);
+ }
+ return NULL;
+}
+
+
+static PyObject *
+async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args)
+{
+ PyObject *retval;
+
+ if (o->agt_state == AWAITABLE_STATE_INIT) {
+ PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
+ return NULL;
+ }
+
+ if (o->agt_state == AWAITABLE_STATE_CLOSED) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ retval = gen_throw((PyGenObject*)o->agt_gen, args);
+ if (o->agt_args) {
+ return async_gen_unwrap_value(o->agt_gen, retval);
+ } else {
+ /* aclose() mode */
+ if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
+ Py_DECREF(retval);
+ PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
+ return NULL;
+ }
+ return retval;
+ }
+}
+
+
+static PyObject *
+async_gen_athrow_iternext(PyAsyncGenAThrow *o)
+{
+ return async_gen_athrow_send(o, Py_None);
+}
+
+
+static PyObject *
+async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args)
+{
+ o->agt_state = AWAITABLE_STATE_CLOSED;
+ Py_RETURN_NONE;
+}
+
+
+static PyMethodDef async_gen_athrow_methods[] = {
+ {"send", (PyCFunction)async_gen_athrow_send, METH_O, send_doc},
+ {"throw", (PyCFunction)async_gen_athrow_throw, METH_VARARGS, throw_doc},
+ {"close", (PyCFunction)async_gen_athrow_close, METH_NOARGS, close_doc},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+static PyAsyncMethods async_gen_athrow_as_async = {
+ PyObject_SelfIter, /* am_await */
+ 0, /* am_aiter */
+ 0 /* am_anext */
+};
+
+
+PyTypeObject _PyAsyncGenAThrow_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "async_generator_athrow", /* tp_name */
+ sizeof(PyAsyncGenAThrow), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)async_gen_athrow_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ &async_gen_athrow_as_async, /* tp_as_async */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)async_gen_athrow_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)async_gen_athrow_iternext, /* tp_iternext */
+ async_gen_athrow_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+static PyObject *
+async_gen_athrow_new(PyAsyncGenObject *gen, PyObject *args)
+{
+ PyAsyncGenAThrow *o;
+ o = PyObject_GC_New(PyAsyncGenAThrow, &_PyAsyncGenAThrow_Type);
+ if (o == NULL) {
+ return NULL;
+ }
+ o->agt_gen = gen;
+ o->agt_args = args;
+ o->agt_state = AWAITABLE_STATE_INIT;
+ Py_INCREF(gen);
+ Py_XINCREF(args);
+ _PyObject_GC_TRACK((PyObject*)o);
+ return (PyObject*)o;
+}
diff --git a/Objects/iterobject.c b/Objects/iterobject.c
index ab29ff81a9..75b2fcbd41 100644
--- a/Objects/iterobject.c
+++ b/Objects/iterobject.c
@@ -208,30 +208,32 @@ calliter_traverse(calliterobject *it, visitproc visit, void *arg)
static PyObject *
calliter_iternext(calliterobject *it)
{
- if (it->it_callable != NULL) {
- PyObject *args = PyTuple_New(0);
- PyObject *result;
- if (args == NULL)
- return NULL;
- result = PyObject_Call(it->it_callable, args, NULL);
- Py_DECREF(args);
- if (result != NULL) {
- int ok;
- ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
- if (ok == 0)
- return result; /* Common case, fast path */
- Py_DECREF(result);
- if (ok > 0) {
- Py_CLEAR(it->it_callable);
- Py_CLEAR(it->it_sentinel);
- }
+ PyObject *result;
+
+ if (it->it_callable == NULL) {
+ return NULL;
+ }
+
+ result = _PyObject_CallNoArg(it->it_callable);
+ if (result != NULL) {
+ int ok;
+
+ ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
+ if (ok == 0) {
+ return result; /* Common case, fast path */
}
- else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyErr_Clear();
+
+ Py_DECREF(result);
+ if (ok > 0) {
Py_CLEAR(it->it_callable);
Py_CLEAR(it->it_sentinel);
}
}
+ else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
+ PyErr_Clear();
+ Py_CLEAR(it->it_callable);
+ Py_CLEAR(it->it_sentinel);
+ }
return NULL;
}
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 815a1b9ea2..dcd7b5efe5 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -49,7 +49,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
/* check for integer overflow */
- if (new_allocated > PY_SIZE_MAX - newsize) {
+ if (new_allocated > SIZE_MAX - newsize) {
PyErr_NoMemory();
return -1;
} else {
@@ -59,7 +59,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
if (newsize == 0)
new_allocated = 0;
items = self->ob_item;
- if (new_allocated <= (PY_SIZE_MAX / sizeof(PyObject *)))
+ if (new_allocated <= (SIZE_MAX / sizeof(PyObject *)))
PyMem_RESIZE(items, PyObject *, new_allocated);
else
items = NULL;
@@ -82,6 +82,16 @@ static size_t count_reuse = 0;
static void
show_alloc(void)
{
+ PyObject *xoptions, *value;
+ _Py_IDENTIFIER(showalloccount);
+
+ xoptions = PySys_GetXOptions();
+ if (xoptions == NULL)
+ return;
+ value = _PyDict_GetItemId(xoptions, &PyId_showalloccount);
+ if (value != Py_True)
+ return;
+
fprintf(stderr, "List allocations: %" PY_FORMAT_SIZE_T "d\n",
count_alloc);
fprintf(stderr, "List reuse through freelist: %" PY_FORMAT_SIZE_T
@@ -130,7 +140,6 @@ PyObject *
PyList_New(Py_ssize_t size)
{
PyListObject *op;
- size_t nbytes;
#ifdef SHOW_ALLOC_COUNT
static int initialized = 0;
if (!initialized) {
@@ -143,11 +152,6 @@ PyList_New(Py_ssize_t size)
PyErr_BadInternalCall();
return NULL;
}
- /* Check for overflow without an actual overflow,
- * which can cause compiler to optimise out */
- if ((size_t)size > PY_SIZE_MAX / sizeof(PyObject *))
- return PyErr_NoMemory();
- nbytes = size * sizeof(PyObject *);
if (numfree) {
numfree--;
op = free_list[numfree];
@@ -166,12 +170,11 @@ PyList_New(Py_ssize_t size)
if (size <= 0)
op->ob_item = NULL;
else {
- op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
+ op->ob_item = (PyObject **) PyMem_Calloc(size, sizeof(PyObject *));
if (op->ob_item == NULL) {
Py_DECREF(op);
return PyErr_NoMemory();
}
- memset(op->ob_item, 0, nbytes);
}
Py_SIZE(op) = size;
op->allocated = size;
@@ -216,7 +219,6 @@ int
PyList_SetItem(PyObject *op, Py_ssize_t i,
PyObject *newitem)
{
- PyObject *olditem;
PyObject **p;
if (!PyList_Check(op)) {
Py_XDECREF(newitem);
@@ -230,9 +232,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i,
return -1;
}
p = ((PyListObject *)op) -> ob_item + i;
- olditem = *p;
- *p = newitem;
- Py_XDECREF(olditem);
+ Py_XSETREF(*p, newitem);
return 0;
}
@@ -251,7 +251,7 @@ ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
return -1;
}
- if (list_resize(self, n+1) == -1)
+ if (list_resize(self, n+1) < 0)
return -1;
if (where < 0) {
@@ -291,7 +291,7 @@ app1(PyListObject *self, PyObject *v)
return -1;
}
- if (list_resize(self, n+1) == -1)
+ if (list_resize(self, n+1) < 0)
return -1;
Py_INCREF(v);
@@ -481,9 +481,9 @@ list_concat(PyListObject *a, PyObject *bb)
return NULL;
}
#define b ((PyListObject *)bb)
- size = Py_SIZE(a) + Py_SIZE(b);
- if (size < 0)
+ if (Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b))
return PyErr_NoMemory();
+ size = Py_SIZE(a) + Py_SIZE(b);
np = (PyListObject *) PyList_New(size);
if (np == NULL) {
return NULL;
@@ -714,7 +714,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n)
return PyErr_NoMemory();
}
- if (list_resize(self, size*n) == -1)
+ if (list_resize(self, size*n) < 0)
return NULL;
p = size;
@@ -733,7 +733,6 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n)
static int
list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)
{
- PyObject *old_value;
if (i < 0 || i >= Py_SIZE(a)) {
PyErr_SetString(PyExc_IndexError,
"list assignment index out of range");
@@ -742,9 +741,7 @@ list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)
if (v == NULL)
return list_ass_slice(a, i, i+1, v);
Py_INCREF(v);
- old_value = a->ob_item[i];
- a->ob_item[i] = v;
- Py_DECREF(old_value);
+ Py_SETREF(a->ob_item[i], v);
return 0;
}
@@ -807,7 +804,7 @@ listextend(PyListObject *self, PyObject *b)
Py_RETURN_NONE;
}
m = Py_SIZE(self);
- if (list_resize(self, m + n) == -1) {
+ if (list_resize(self, m + n) < 0) {
Py_DECREF(b);
return NULL;
}
@@ -835,23 +832,25 @@ listextend(PyListObject *self, PyObject *b)
/* Guess a result list size. */
n = PyObject_LengthHint(b, 8);
- if (n == -1) {
+ if (n < 0) {
Py_DECREF(it);
return NULL;
}
m = Py_SIZE(self);
- mn = m + n;
- if (mn >= m) {
+ if (m > PY_SSIZE_T_MAX - n) {
+ /* m + n overflowed; on the chance that n lied, and there really
+ * is enough room, ignore it. If n was telling the truth, we'll
+ * eventually run out of memory during the loop.
+ */
+ }
+ else {
+ mn = m + n;
/* Make room. */
- if (list_resize(self, mn) == -1)
+ if (list_resize(self, mn) < 0)
goto error;
/* Make the list sane again. */
Py_SIZE(self) = m;
}
- /* Else m + n overflowed; on the chance that n lied, and there really
- * is enough room, ignore it. If n was telling the truth, we'll
- * eventually run out of memory during the loop.
- */
/* Run iterator to exhaustion. */
for (;;) {
@@ -2500,9 +2499,6 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
step = -step;
}
- assert((size_t)slicelength <=
- PY_SIZE_MAX / sizeof(PyObject*));
-
garbage = (PyObject**)
PyMem_MALLOC(slicelength*sizeof(PyObject*));
if (!garbage) {
diff --git a/Objects/listsort.txt b/Objects/listsort.txt
index 152a2700ad..17d27973f8 100644
--- a/Objects/listsort.txt
+++ b/Objects/listsort.txt
@@ -486,7 +486,7 @@ sub-run, yet finding such very efficiently when they exist.
I first learned about the galloping strategy in a related context; see:
"Adaptive Set Intersections, Unions, and Differences" (2000)
- Erik D. Demaine, Alejandro López-Ortiz, J. Ian Munro
+ Erik D. Demaine, Alejandro López-Ortiz, J. Ian Munro
and its followup(s). An earlier paper called the same strategy
"exponential search":
diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt
index d247eddd6f..515375772e 100644
--- a/Objects/lnotab_notes.txt
+++ b/Objects/lnotab_notes.txt
@@ -12,42 +12,47 @@ pairs. The details are important and delicate, best illustrated by example:
0 1
6 2
50 7
- 350 307
- 361 308
+ 350 207
+ 361 208
Instead of storing these numbers literally, we compress the list by storing only
-the increments from one row to the next. Conceptually, the stored list might
+the difference from one row to the next. Conceptually, the stored list might
look like:
- 0, 1, 6, 1, 44, 5, 300, 300, 11, 1
+ 0, 1, 6, 1, 44, 5, 300, 200, 11, 1
-The above doesn't really work, but it's a start. Note that an unsigned byte
-can't hold negative values, or values larger than 255, and the above example
-contains two such values. So we make two tweaks:
+The above doesn't really work, but it's a start. An unsigned byte (byte code
+offset) can't hold negative values, or values larger than 255, a signed byte
+(line number) can't hold values larger than 127 or less than -128, and the
+above example contains two such values. So we make two tweaks:
- (a) there's a deep assumption that byte code offsets and their corresponding
- line #s both increase monotonically, and
- (b) if at least one column jumps by more than 255 from one row to the next,
- more than one pair is written to the table. In case #b, there's no way to know
- from looking at the table later how many were written. That's the delicate
- part. A user of co_lnotab desiring to find the source line number
- corresponding to a bytecode address A should do something like this
+ (a) there's a deep assumption that byte code offsets increase monotonically,
+ and
+ (b) if byte code offset jumps by more than 255 from one row to the next, or if
+ source code line number jumps by more than 127 or less than -128 from one row
+ to the next, more than one pair is written to the table. In case #b,
+ there's no way to know from looking at the table later how many were written.
+ That's the delicate part. A user of co_lnotab desiring to find the source
+ line number corresponding to a bytecode address A should do something like
+ this:
lineno = addr = 0
for addr_incr, line_incr in co_lnotab:
addr += addr_incr
if addr > A:
return lineno
+ if line_incr >= 0x80:
+ line_incr -= 0x100
lineno += line_incr
(In C, this is implemented by PyCode_Addr2Line().) In order for this to work,
when the addr field increments by more than 255, the line # increment in each
pair generated must be 0 until the remaining addr increment is < 256. So, in
the example above, assemble_lnotab in compile.c should not (as was actually done
-until 2.2) expand 300, 300 to
+until 2.2) expand 300, 200 to
255, 255, 45, 45,
but to
- 255, 0, 45, 255, 0, 45.
+ 255, 0, 45, 128, 0, 72.
The above is sufficient to reconstruct line numbers for tracebacks, but not for
line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c
@@ -90,16 +95,16 @@ which compiles to this:
6 POP_JUMP_IF_FALSE 17
3 9 LOAD_CONST 1 (1)
- 12 PRINT_ITEM
+ 12 PRINT_ITEM
- 4 13 BREAK_LOOP
+ 4 13 BREAK_LOOP
14 JUMP_ABSOLUTE 3
- >> 17 POP_BLOCK
+ >> 17 POP_BLOCK
6 18 LOAD_CONST 2 (2)
- 21 PRINT_ITEM
+ 21 PRINT_ITEM
>> 22 LOAD_CONST 0 (None)
- 25 RETURN_VALUE
+ 25 RETURN_VALUE
If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 17
and the co_lnotab will claim that execution has moved to line 4, which is wrong.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 8510e90648..ad239ce84e 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -722,7 +722,7 @@ _PyLong_NumBits(PyObject *vv)
assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
if (ndigits > 0) {
digit msd = v->ob_digit[ndigits - 1];
- if ((size_t)(ndigits - 1) > PY_SIZE_MAX / (size_t)PyLong_SHIFT)
+ if ((size_t)(ndigits - 1) > SIZE_MAX / (size_t)PyLong_SHIFT)
goto Overflow;
result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
do {
@@ -990,16 +990,13 @@ PyObject *
PyLong_FromVoidPtr(void *p)
{
#if SIZEOF_VOID_P <= SIZEOF_LONG
- return PyLong_FromUnsignedLong((unsigned long)(Py_uintptr_t)p);
+ return PyLong_FromUnsignedLong((unsigned long)(uintptr_t)p);
#else
-#ifndef HAVE_LONG_LONG
-# error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long"
-#endif
#if SIZEOF_LONG_LONG < SIZEOF_VOID_P
-# error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
+# error "PyLong_FromVoidPtr: sizeof(long long) < sizeof(void*)"
#endif
- return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)(Py_uintptr_t)p);
+ return PyLong_FromUnsignedLongLong((unsigned long long)(uintptr_t)p);
#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
}
@@ -1018,13 +1015,10 @@ PyLong_AsVoidPtr(PyObject *vv)
x = PyLong_AsUnsignedLong(vv);
#else
-#ifndef HAVE_LONG_LONG
-# error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long"
-#endif
#if SIZEOF_LONG_LONG < SIZEOF_VOID_P
-# error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
+# error "PyLong_AsVoidPtr: sizeof(long long) < sizeof(void*)"
#endif
- PY_LONG_LONG x;
+ long long x;
if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0)
x = PyLong_AsLongLong(vv);
@@ -1038,22 +1032,20 @@ PyLong_AsVoidPtr(PyObject *vv)
return (void *)x;
}
-#ifdef HAVE_LONG_LONG
-
-/* Initial PY_LONG_LONG support by Chris Herborth (chrish@qnx.com), later
+/* Initial long long support by Chris Herborth (chrish@qnx.com), later
* rewritten to use the newer PyLong_{As,From}ByteArray API.
*/
-#define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN)
+#define PY_ABS_LLONG_MIN (0-(unsigned long long)PY_LLONG_MIN)
-/* Create a new int object from a C PY_LONG_LONG int. */
+/* Create a new int object from a C long long int. */
PyObject *
-PyLong_FromLongLong(PY_LONG_LONG ival)
+PyLong_FromLongLong(long long ival)
{
PyLongObject *v;
- unsigned PY_LONG_LONG abs_ival;
- unsigned PY_LONG_LONG t; /* unsigned so >> doesn't propagate sign bit */
+ unsigned long long abs_ival;
+ unsigned long long t; /* unsigned so >> doesn't propagate sign bit */
int ndigits = 0;
int negative = 0;
@@ -1061,11 +1053,11 @@ PyLong_FromLongLong(PY_LONG_LONG ival)
if (ival < 0) {
/* avoid signed overflow on negation; see comments
in PyLong_FromLong above. */
- abs_ival = (unsigned PY_LONG_LONG)(-1-ival) + 1;
+ abs_ival = (unsigned long long)(-1-ival) + 1;
negative = 1;
}
else {
- abs_ival = (unsigned PY_LONG_LONG)ival;
+ abs_ival = (unsigned long long)ival;
}
/* Count the number of Python digits.
@@ -1090,19 +1082,19 @@ PyLong_FromLongLong(PY_LONG_LONG ival)
return (PyObject *)v;
}
-/* Create a new int object from a C unsigned PY_LONG_LONG int. */
+/* Create a new int object from a C unsigned long long int. */
PyObject *
-PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival)
+PyLong_FromUnsignedLongLong(unsigned long long ival)
{
PyLongObject *v;
- unsigned PY_LONG_LONG t;
+ unsigned long long t;
int ndigits = 0;
if (ival < PyLong_BASE)
return PyLong_FromLong((long)ival);
/* Count the number of Python digits. */
- t = (unsigned PY_LONG_LONG)ival;
+ t = (unsigned long long)ival;
while (t) {
++ndigits;
t >>= PyLong_SHIFT;
@@ -1191,11 +1183,11 @@ PyLong_FromSize_t(size_t ival)
/* Get a C long long int from an int object or any object that has an
__int__ method. Return -1 and set an error if overflow occurs. */
-PY_LONG_LONG
+long long
PyLong_AsLongLong(PyObject *vv)
{
PyLongObject *v;
- PY_LONG_LONG bytes;
+ long long bytes;
int res;
int do_decref = 0; /* if nb_int was called */
@@ -1233,30 +1225,30 @@ PyLong_AsLongLong(PyObject *vv)
Py_DECREF(v);
}
- /* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
+ /* Plan 9 can't handle long long in ? : expressions */
if (res < 0)
- return (PY_LONG_LONG)-1;
+ return (long long)-1;
else
return bytes;
}
-/* Get a C unsigned PY_LONG_LONG int from an int object.
+/* Get a C unsigned long long int from an int object.
Return -1 and set an error if overflow occurs. */
-unsigned PY_LONG_LONG
+unsigned long long
PyLong_AsUnsignedLongLong(PyObject *vv)
{
PyLongObject *v;
- unsigned PY_LONG_LONG bytes;
+ unsigned long long bytes;
int res;
if (vv == NULL) {
PyErr_BadInternalCall();
- return (unsigned PY_LONG_LONG)-1;
+ return (unsigned long long)-1;
}
if (!PyLong_Check(vv)) {
PyErr_SetString(PyExc_TypeError, "an integer is required");
- return (unsigned PY_LONG_LONG)-1;
+ return (unsigned long long)-1;
}
v = (PyLongObject*)vv;
@@ -1268,9 +1260,9 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
res = _PyLong_AsByteArray((PyLongObject *)vv, (unsigned char *)&bytes,
SIZEOF_LONG_LONG, PY_LITTLE_ENDIAN, 0);
- /* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
+ /* Plan 9 can't handle long long in ? : expressions */
if (res < 0)
- return (unsigned PY_LONG_LONG)res;
+ return (unsigned long long)res;
else
return bytes;
}
@@ -1278,11 +1270,11 @@ PyLong_AsUnsignedLongLong(PyObject *vv)
/* Get a C unsigned long int from an int object, ignoring the high bits.
Returns -1 and sets an error condition if an error occurs. */
-static unsigned PY_LONG_LONG
+static unsigned long long
_PyLong_AsUnsignedLongLongMask(PyObject *vv)
{
PyLongObject *v;
- unsigned PY_LONG_LONG x;
+ unsigned long long x;
Py_ssize_t i;
int sign;
@@ -1308,11 +1300,11 @@ _PyLong_AsUnsignedLongLongMask(PyObject *vv)
return x * sign;
}
-unsigned PY_LONG_LONG
+unsigned long long
PyLong_AsUnsignedLongLongMask(PyObject *op)
{
PyLongObject *lo;
- unsigned PY_LONG_LONG val;
+ unsigned long long val;
if (op == NULL) {
PyErr_BadInternalCall();
@@ -1325,7 +1317,7 @@ PyLong_AsUnsignedLongLongMask(PyObject *op)
lo = _PyLong_FromNbInt(op);
if (lo == NULL)
- return (unsigned PY_LONG_LONG)-1;
+ return (unsigned long long)-1;
val = _PyLong_AsUnsignedLongLongMask((PyObject *)lo);
Py_DECREF(lo);
@@ -1342,13 +1334,13 @@ PyLong_AsUnsignedLongLongMask(PyObject *op)
In this case *overflow will be 0.
*/
-PY_LONG_LONG
+long long
PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
{
/* This version by Tim Peters */
PyLongObject *v;
- unsigned PY_LONG_LONG x, prev;
- PY_LONG_LONG res;
+ unsigned long long x, prev;
+ long long res;
Py_ssize_t i;
int sign;
int do_decref = 0; /* if nb_int was called */
@@ -1400,8 +1392,8 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
/* Haven't lost any bits, but casting to long requires extra
* care (see comment above).
*/
- if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
- res = (PY_LONG_LONG)x * sign;
+ if (x <= (unsigned long long)PY_LLONG_MAX) {
+ res = (long long)x * sign;
}
else if (sign < 0 && x == PY_ABS_LLONG_MIN) {
res = PY_LLONG_MIN;
@@ -1418,8 +1410,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
return res;
}
-#endif /* HAVE_LONG_LONG */
-
#define CHECK_BINOP(v,w) \
do { \
if (!PyLong_Check(v) || !PyLong_Check(w)) \
@@ -1583,13 +1573,16 @@ divrem1(PyLongObject *a, digit n, digit *prem)
static int
long_to_decimal_string_internal(PyObject *aa,
PyObject **p_output,
- _PyUnicodeWriter *writer)
+ _PyUnicodeWriter *writer,
+ _PyBytesWriter *bytes_writer,
+ char **bytes_str)
{
PyLongObject *scratch, *a;
- PyObject *str;
+ PyObject *str = NULL;
Py_ssize_t size, strlen, size_a, i, j;
digit *pout, *pin, rem, tenpow;
int negative;
+ int d;
enum PyUnicode_Kind kind;
a = (PyLongObject *)aa;
@@ -1607,15 +1600,17 @@ long_to_decimal_string_internal(PyObject *aa,
But log2(a) < size_a * PyLong_SHIFT, and
log2(_PyLong_DECIMAL_BASE) = log2(10) * _PyLong_DECIMAL_SHIFT
- > 3 * _PyLong_DECIMAL_SHIFT
+ > 3.3 * _PyLong_DECIMAL_SHIFT
+
+ size_a * PyLong_SHIFT / (3.3 * _PyLong_DECIMAL_SHIFT) =
+ size_a + size_a / d < size_a + size_a / floor(d),
+ where d = (3.3 * _PyLong_DECIMAL_SHIFT) /
+ (PyLong_SHIFT - 3.3 * _PyLong_DECIMAL_SHIFT)
*/
- if (size_a > PY_SSIZE_T_MAX / PyLong_SHIFT) {
- PyErr_SetString(PyExc_OverflowError,
- "int too large to format");
- return -1;
- }
- /* the expression size_a * PyLong_SHIFT is now safe from overflow */
- size = 1 + size_a * PyLong_SHIFT / (3 * _PyLong_DECIMAL_SHIFT);
+ d = (33 * _PyLong_DECIMAL_SHIFT) /
+ (10 * PyLong_SHIFT - 33 * _PyLong_DECIMAL_SHIFT);
+ assert(size_a < PY_SSIZE_T_MAX/2);
+ size = 1 + size_a + size_a / d;
scratch = _PyLong_New(size);
if (scratch == NULL)
return -1;
@@ -1663,7 +1658,13 @@ long_to_decimal_string_internal(PyObject *aa,
return -1;
}
kind = writer->kind;
- str = NULL;
+ }
+ else if (bytes_writer) {
+ *bytes_str = _PyBytesWriter_Prepare(bytes_writer, *bytes_str, strlen);
+ if (*bytes_str == NULL) {
+ Py_DECREF(scratch);
+ return -1;
+ }
}
else {
str = PyUnicode_New(strlen, '9');
@@ -1674,13 +1675,8 @@ long_to_decimal_string_internal(PyObject *aa,
kind = PyUnicode_KIND(str);
}
-#define WRITE_DIGITS(TYPE) \
+#define WRITE_DIGITS(p) \
do { \
- if (writer) \
- p = (TYPE*)PyUnicode_DATA(writer->buffer) + writer->pos + strlen; \
- else \
- p = (TYPE*)PyUnicode_DATA(str) + strlen; \
- \
/* pout[0] through pout[size-2] contribute exactly \
_PyLong_DECIMAL_SHIFT digits each */ \
for (i=0; i < size - 1; i++) { \
@@ -1700,6 +1696,16 @@ long_to_decimal_string_internal(PyObject *aa,
/* and sign */ \
if (negative) \
*--p = '-'; \
+ } while (0)
+
+#define WRITE_UNICODE_DIGITS(TYPE) \
+ do { \
+ if (writer) \
+ p = (TYPE*)PyUnicode_DATA(writer->buffer) + writer->pos + strlen; \
+ else \
+ p = (TYPE*)PyUnicode_DATA(str) + strlen; \
+ \
+ WRITE_DIGITS(p); \
\
/* check we've counted correctly */ \
if (writer) \
@@ -1709,25 +1715,34 @@ long_to_decimal_string_internal(PyObject *aa,
} while (0)
/* fill the string right-to-left */
- if (kind == PyUnicode_1BYTE_KIND) {
+ if (bytes_writer) {
+ char *p = *bytes_str + strlen;
+ WRITE_DIGITS(p);
+ assert(p == *bytes_str);
+ }
+ else if (kind == PyUnicode_1BYTE_KIND) {
Py_UCS1 *p;
- WRITE_DIGITS(Py_UCS1);
+ WRITE_UNICODE_DIGITS(Py_UCS1);
}
else if (kind == PyUnicode_2BYTE_KIND) {
Py_UCS2 *p;
- WRITE_DIGITS(Py_UCS2);
+ WRITE_UNICODE_DIGITS(Py_UCS2);
}
else {
Py_UCS4 *p;
assert (kind == PyUnicode_4BYTE_KIND);
- WRITE_DIGITS(Py_UCS4);
+ WRITE_UNICODE_DIGITS(Py_UCS4);
}
#undef WRITE_DIGITS
+#undef WRITE_UNICODE_DIGITS
Py_DECREF(scratch);
if (writer) {
writer->pos += strlen;
}
+ else if (bytes_writer) {
+ (*bytes_str) += strlen;
+ }
else {
assert(_PyUnicode_CheckConsistency(str, 1));
*p_output = (PyObject *)str;
@@ -1739,7 +1754,7 @@ static PyObject *
long_to_decimal_string(PyObject *aa)
{
PyObject *v;
- if (long_to_decimal_string_internal(aa, &v, NULL) == -1)
+ if (long_to_decimal_string_internal(aa, &v, NULL, NULL, NULL) == -1)
return NULL;
return v;
}
@@ -1751,10 +1766,11 @@ long_to_decimal_string(PyObject *aa)
static int
long_format_binary(PyObject *aa, int base, int alternate,
- PyObject **p_output, _PyUnicodeWriter *writer)
+ PyObject **p_output, _PyUnicodeWriter *writer,
+ _PyBytesWriter *bytes_writer, char **bytes_str)
{
PyLongObject *a = (PyLongObject *)aa;
- PyObject *v;
+ PyObject *v = NULL;
Py_ssize_t sz;
Py_ssize_t size_a;
enum PyUnicode_Kind kind;
@@ -1811,7 +1827,11 @@ long_format_binary(PyObject *aa, int base, int alternate,
if (_PyUnicodeWriter_Prepare(writer, sz, 'x') == -1)
return -1;
kind = writer->kind;
- v = NULL;
+ }
+ else if (bytes_writer) {
+ *bytes_str = _PyBytesWriter_Prepare(bytes_writer, *bytes_str, sz);
+ if (*bytes_str == NULL)
+ return -1;
}
else {
v = PyUnicode_New(sz, 'x');
@@ -1820,13 +1840,8 @@ long_format_binary(PyObject *aa, int base, int alternate,
kind = PyUnicode_KIND(v);
}
-#define WRITE_DIGITS(TYPE) \
+#define WRITE_DIGITS(p) \
do { \
- if (writer) \
- p = (TYPE*)PyUnicode_DATA(writer->buffer) + writer->pos + sz; \
- else \
- p = (TYPE*)PyUnicode_DATA(v) + sz; \
- \
if (size_a == 0) { \
*--p = '0'; \
} \
@@ -1861,30 +1876,50 @@ long_format_binary(PyObject *aa, int base, int alternate,
} \
if (negative) \
*--p = '-'; \
+ } while (0)
+
+#define WRITE_UNICODE_DIGITS(TYPE) \
+ do { \
+ if (writer) \
+ p = (TYPE*)PyUnicode_DATA(writer->buffer) + writer->pos + sz; \
+ else \
+ p = (TYPE*)PyUnicode_DATA(v) + sz; \
+ \
+ WRITE_DIGITS(p); \
+ \
if (writer) \
assert(p == ((TYPE*)PyUnicode_DATA(writer->buffer) + writer->pos)); \
else \
assert(p == (TYPE*)PyUnicode_DATA(v)); \
} while (0)
- if (kind == PyUnicode_1BYTE_KIND) {
+ if (bytes_writer) {
+ char *p = *bytes_str + sz;
+ WRITE_DIGITS(p);
+ assert(p == *bytes_str);
+ }
+ else if (kind == PyUnicode_1BYTE_KIND) {
Py_UCS1 *p;
- WRITE_DIGITS(Py_UCS1);
+ WRITE_UNICODE_DIGITS(Py_UCS1);
}
else if (kind == PyUnicode_2BYTE_KIND) {
Py_UCS2 *p;
- WRITE_DIGITS(Py_UCS2);
+ WRITE_UNICODE_DIGITS(Py_UCS2);
}
else {
Py_UCS4 *p;
assert (kind == PyUnicode_4BYTE_KIND);
- WRITE_DIGITS(Py_UCS4);
+ WRITE_UNICODE_DIGITS(Py_UCS4);
}
#undef WRITE_DIGITS
+#undef WRITE_UNICODE_DIGITS
if (writer) {
writer->pos += sz;
}
+ else if (bytes_writer) {
+ (*bytes_str) += sz;
+ }
else {
assert(_PyUnicode_CheckConsistency(v, 1));
*p_output = v;
@@ -1898,9 +1933,9 @@ _PyLong_Format(PyObject *obj, int base)
PyObject *str;
int err;
if (base == 10)
- err = long_to_decimal_string_internal(obj, &str, NULL);
+ err = long_to_decimal_string_internal(obj, &str, NULL, NULL, NULL);
else
- err = long_format_binary(obj, base, 1, &str, NULL);
+ err = long_format_binary(obj, base, 1, &str, NULL, NULL, NULL);
if (err == -1)
return NULL;
return str;
@@ -1912,9 +1947,31 @@ _PyLong_FormatWriter(_PyUnicodeWriter *writer,
int base, int alternate)
{
if (base == 10)
- return long_to_decimal_string_internal(obj, NULL, writer);
+ return long_to_decimal_string_internal(obj, NULL, writer,
+ NULL, NULL);
+ else
+ return long_format_binary(obj, base, alternate, NULL, writer,
+ NULL, NULL);
+}
+
+char*
+_PyLong_FormatBytesWriter(_PyBytesWriter *writer, char *str,
+ PyObject *obj,
+ int base, int alternate)
+{
+ char *str2;
+ int res;
+ str2 = str;
+ if (base == 10)
+ res = long_to_decimal_string_internal(obj, NULL, NULL,
+ writer, &str2);
else
- return long_format_binary(obj, base, alternate, NULL, writer);
+ res = long_format_binary(obj, base, alternate, NULL, NULL,
+ writer, &str2);
+ if (res < 0)
+ return NULL;
+ assert(str2 != NULL);
+ return str2;
}
/* Table of digit values for 8-bit string -> integer conversion.
@@ -1948,12 +2005,18 @@ unsigned char _PyLong_DigitValue[256] = {
* non-digit (which may be *str!). A normalized int is returned.
* The point to this routine is that it takes time linear in the number of
* string characters.
+ *
+ * Return values:
+ * -1 on syntax error (exception needs to be set, *res is untouched)
+ * 0 else (exception may be set, in that case *res is set to NULL)
*/
-static PyLongObject *
-long_from_binary_base(const char **str, int base)
+static int
+long_from_binary_base(const char **str, int base, PyLongObject **res)
{
const char *p = *str;
const char *start = p;
+ char prev = 0;
+ int digits = 0;
int bits_per_char;
Py_ssize_t n;
PyLongObject *z;
@@ -1963,23 +2026,43 @@ long_from_binary_base(const char **str, int base)
assert(base >= 2 && base <= 32 && (base & (base - 1)) == 0);
n = base;
- for (bits_per_char = -1; n; ++bits_per_char)
+ for (bits_per_char = -1; n; ++bits_per_char) {
n >>= 1;
- /* n <- total # of bits needed, while setting p to end-of-string */
- while (_PyLong_DigitValue[Py_CHARMASK(*p)] < base)
+ }
+ /* count digits and set p to end-of-string */
+ while (_PyLong_DigitValue[Py_CHARMASK(*p)] < base || *p == '_') {
+ if (*p == '_') {
+ if (prev == '_') {
+ *str = p - 1;
+ return -1;
+ }
+ } else {
+ ++digits;
+ }
+ prev = *p;
++p;
+ }
+ if (prev == '_') {
+ /* Trailing underscore not allowed. */
+ *str = p - 1;
+ return -1;
+ }
+
*str = p;
/* n <- # of Python digits needed, = ceiling(n/PyLong_SHIFT). */
- n = (p - start) * bits_per_char + PyLong_SHIFT - 1;
+ n = digits * bits_per_char + PyLong_SHIFT - 1;
if (n / bits_per_char < p - start) {
PyErr_SetString(PyExc_ValueError,
"int string too large to convert");
- return NULL;
+ *res = NULL;
+ return 0;
}
n = n / PyLong_SHIFT;
z = _PyLong_New(n);
- if (z == NULL)
- return NULL;
+ if (z == NULL) {
+ *res = NULL;
+ return 0;
+ }
/* Read string from right, and fill in int from left; i.e.,
* from least to most significant in both.
*/
@@ -1987,7 +2070,11 @@ long_from_binary_base(const char **str, int base)
bits_in_accum = 0;
pdigit = z->ob_digit;
while (--p >= start) {
- int k = (int)_PyLong_DigitValue[Py_CHARMASK(*p)];
+ int k;
+ if (*p == '_') {
+ continue;
+ }
+ k = (int)_PyLong_DigitValue[Py_CHARMASK(*p)];
assert(k >= 0 && k < base);
accum |= (twodigits)k << bits_in_accum;
bits_in_accum += bits_per_char;
@@ -2006,7 +2093,8 @@ long_from_binary_base(const char **str, int base)
}
while (pdigit - z->ob_digit < n)
*pdigit++ = 0;
- return long_normalize(z);
+ *res = long_normalize(z);
+ return 0;
}
/* Parses an int from a bytestring. Leading and trailing whitespace will be
@@ -2031,23 +2119,29 @@ PyLong_FromString(const char *str, char **pend, int base)
"int() arg 2 must be >= 2 and <= 36");
return NULL;
}
- while (*str != '\0' && Py_ISSPACE(Py_CHARMASK(*str)))
+ while (*str != '\0' && Py_ISSPACE(Py_CHARMASK(*str))) {
str++;
- if (*str == '+')
+ }
+ if (*str == '+') {
++str;
+ }
else if (*str == '-') {
++str;
sign = -1;
}
if (base == 0) {
- if (str[0] != '0')
+ if (str[0] != '0') {
base = 10;
- else if (str[1] == 'x' || str[1] == 'X')
+ }
+ else if (str[1] == 'x' || str[1] == 'X') {
base = 16;
- else if (str[1] == 'o' || str[1] == 'O')
+ }
+ else if (str[1] == 'o' || str[1] == 'O') {
base = 8;
- else if (str[1] == 'b' || str[1] == 'B')
+ }
+ else if (str[1] == 'b' || str[1] == 'B') {
base = 2;
+ }
else {
/* "old" (C-style) octal literal, now invalid.
it might still be zero though */
@@ -2058,12 +2152,26 @@ PyLong_FromString(const char *str, char **pend, int base)
if (str[0] == '0' &&
((base == 16 && (str[1] == 'x' || str[1] == 'X')) ||
(base == 8 && (str[1] == 'o' || str[1] == 'O')) ||
- (base == 2 && (str[1] == 'b' || str[1] == 'B'))))
+ (base == 2 && (str[1] == 'b' || str[1] == 'B')))) {
str += 2;
+ /* One underscore allowed here. */
+ if (*str == '_') {
+ ++str;
+ }
+ }
+ if (str[0] == '_') {
+ /* May not start with underscores. */
+ goto onError;
+ }
start = str;
- if ((base & (base - 1)) == 0)
- z = long_from_binary_base(&str, base);
+ if ((base & (base - 1)) == 0) {
+ int res = long_from_binary_base(&str, base, &z);
+ if (res < 0) {
+ /* Syntax error. */
+ goto onError;
+ }
+ }
else {
/***
Binary bases can be converted in time linear in the number of digits, because
@@ -2152,11 +2260,13 @@ digit beyond the first.
***/
twodigits c; /* current input character */
Py_ssize_t size_z;
+ int digits = 0;
int i;
int convwidth;
twodigits convmultmax, convmult;
digit *pz, *pzstop;
- const char* scan;
+ const char *scan, *lastdigit;
+ char prev = 0;
static double log_base_BASE[37] = {0.0e0,};
static int convwidth_base[37] = {0,};
@@ -2170,8 +2280,9 @@ digit beyond the first.
log((double)PyLong_BASE));
for (;;) {
twodigits next = convmax * base;
- if (next > PyLong_BASE)
+ if (next > PyLong_BASE) {
break;
+ }
convmax = next;
++i;
}
@@ -2182,21 +2293,43 @@ digit beyond the first.
/* Find length of the string of numeric characters. */
scan = str;
- while (_PyLong_DigitValue[Py_CHARMASK(*scan)] < base)
+ lastdigit = str;
+
+ while (_PyLong_DigitValue[Py_CHARMASK(*scan)] < base || *scan == '_') {
+ if (*scan == '_') {
+ if (prev == '_') {
+ /* Only one underscore allowed. */
+ str = lastdigit + 1;
+ goto onError;
+ }
+ }
+ else {
+ ++digits;
+ lastdigit = scan;
+ }
+ prev = *scan;
++scan;
+ }
+ if (prev == '_') {
+ /* Trailing underscore not allowed. */
+ /* Set error pointer to first underscore. */
+ str = lastdigit + 1;
+ goto onError;
+ }
/* Create an int object that can contain the largest possible
* integer with this base and length. Note that there's no
* need to initialize z->ob_digit -- no slot is read up before
* being stored into.
*/
- size_z = (Py_ssize_t)((scan - str) * log_base_BASE[base]) + 1;
+ size_z = (Py_ssize_t)(digits * log_base_BASE[base]) + 1;
/* Uncomment next line to test exceedingly rare copy code */
/* size_z = 1; */
assert(size_z > 0);
z = _PyLong_New(size_z);
- if (z == NULL)
+ if (z == NULL) {
return NULL;
+ }
Py_SIZE(z) = 0;
/* `convwidth` consecutive input digits are treated as a single
@@ -2207,9 +2340,17 @@ digit beyond the first.
/* Work ;-) */
while (str < scan) {
+ if (*str == '_') {
+ str++;
+ continue;
+ }
/* grab up to convwidth digits from the input string */
c = (digit)_PyLong_DigitValue[Py_CHARMASK(*str++)];
- for (i = 1; i < convwidth && str != scan; ++i, ++str) {
+ for (i = 1; i < convwidth && str != scan; ++str) {
+ if (*str == '_') {
+ continue;
+ }
+ i++;
c = (twodigits)(c * base +
(int)_PyLong_DigitValue[Py_CHARMASK(*str)]);
assert(c < PyLong_BASE);
@@ -2221,8 +2362,9 @@ digit beyond the first.
*/
if (i != convwidth) {
convmult = base;
- for ( ; i > 1; --i)
+ for ( ; i > 1; --i) {
convmult *= base;
+ }
}
/* Multiply z by convmult, and add c. */
@@ -2260,41 +2402,51 @@ digit beyond the first.
}
}
}
- if (z == NULL)
+ if (z == NULL) {
return NULL;
+ }
if (error_if_nonzero) {
/* reset the base to 0, else the exception message
doesn't make too much sense */
base = 0;
- if (Py_SIZE(z) != 0)
+ if (Py_SIZE(z) != 0) {
goto onError;
+ }
/* there might still be other problems, therefore base
remains zero here for the same reason */
}
- if (str == start)
+ if (str == start) {
goto onError;
- if (sign < 0)
+ }
+ if (sign < 0) {
Py_SIZE(z) = -(Py_SIZE(z));
- while (*str && Py_ISSPACE(Py_CHARMASK(*str)))
+ }
+ while (*str && Py_ISSPACE(Py_CHARMASK(*str))) {
str++;
- if (*str != '\0')
+ }
+ if (*str != '\0') {
goto onError;
+ }
long_normalize(z);
z = maybe_small_long(z);
- if (z == NULL)
+ if (z == NULL) {
return NULL;
- if (pend != NULL)
+ }
+ if (pend != NULL) {
*pend = (char *)str;
+ }
return (PyObject *) z;
onError:
- if (pend != NULL)
+ if (pend != NULL) {
*pend = (char *)str;
+ }
Py_XDECREF(z);
slen = strlen(orig_str) < 200 ? strlen(orig_str) : 200;
strobj = PyUnicode_FromStringAndSize(orig_str, slen);
- if (strobj == NULL)
+ if (strobj == NULL) {
return NULL;
+ }
PyErr_Format(PyExc_ValueError,
"invalid literal for int() with base %d: %.200R",
base, strobj);
@@ -2395,8 +2547,11 @@ long_divrem(PyLongObject *a, PyLongObject *b,
*pdiv = (PyLongObject*)PyLong_FromLong(0);
if (*pdiv == NULL)
return -1;
- Py_INCREF(a);
- *prem = (PyLongObject *) a;
+ *prem = (PyLongObject *)long_long((PyObject *)a);
+ if (*prem == NULL) {
+ Py_CLEAR(*pdiv);
+ return -1;
+ }
return 0;
}
if (size_b == 1) {
@@ -2706,6 +2861,13 @@ PyLong_AsDouble(PyObject *v)
PyErr_SetString(PyExc_TypeError, "an integer is required");
return -1.0;
}
+ if (Py_ABS(Py_SIZE(v)) <= 1) {
+ /* Fast path; single digit long (31 bits) will cast safely
+ to double. This improves performance of FP/long operations
+ by 20%.
+ */
+ return (double)MEDIUM_VALUE((PyLongObject *)v);
+ }
x = _PyLong_Frexp((PyLongObject *)v, &exponent);
if ((x == -1.0 && PyErr_Occurred()) || exponent > DBL_MAX_EXP) {
PyErr_SetString(PyExc_OverflowError,
@@ -2930,9 +3092,7 @@ x_sub(PyLongObject *a, PyLongObject *b)
}
assert(borrow == 0);
if (sign < 0) {
- _PyLong_Negate(&z);
- if (z == NULL)
- return NULL;
+ Py_SIZE(z) = -Py_SIZE(z);
}
return long_normalize(z);
}
@@ -2952,8 +3112,14 @@ long_add(PyLongObject *a, PyLongObject *b)
if (Py_SIZE(a) < 0) {
if (Py_SIZE(b) < 0) {
z = x_add(a, b);
- if (z != NULL && Py_SIZE(z) != 0)
+ if (z != NULL) {
+ /* x_add received at least one multiple-digit int,
+ and thus z must be a multiple-digit int.
+ That also means z is not an element of
+ small_ints, so negating it in-place is safe. */
+ assert(Py_REFCNT(z) == 1);
Py_SIZE(z) = -(Py_SIZE(z));
+ }
}
else
z = x_sub(b, a);
@@ -2984,8 +3150,10 @@ long_sub(PyLongObject *a, PyLongObject *b)
z = x_sub(a, b);
else
z = x_add(a, b);
- if (z != NULL && Py_SIZE(z) != 0)
+ if (z != NULL) {
+ assert(Py_SIZE(z) == 0 || Py_REFCNT(z) == 1);
Py_SIZE(z) = -(Py_SIZE(z));
+ }
}
else {
if (Py_SIZE(b) < 0)
@@ -3409,17 +3577,7 @@ long_mul(PyLongObject *a, PyLongObject *b)
/* fast path for single-digit multiplication */
if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) {
stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b);
-#ifdef HAVE_LONG_LONG
- return PyLong_FromLongLong((PY_LONG_LONG)v);
-#else
- /* if we don't have long long then we're almost certainly
- using 15-bit digits, so v will fit in a long. In the
- unlikely event that we're using 30-bit digits on a platform
- without long long, a large v will just cause us to fall
- through to the general multiplication code below. */
- if (v >= LONG_MIN && v <= LONG_MAX)
- return PyLong_FromLong((long)v);
-#endif
+ return PyLong_FromLongLong((long long)v);
}
z = k_mul(a, b);
@@ -3432,6 +3590,52 @@ long_mul(PyLongObject *a, PyLongObject *b)
return (PyObject *)z;
}
+/* Fast modulo division for single-digit longs. */
+static PyObject *
+fast_mod(PyLongObject *a, PyLongObject *b)
+{
+ sdigit left = a->ob_digit[0];
+ sdigit right = b->ob_digit[0];
+ sdigit mod;
+
+ assert(Py_ABS(Py_SIZE(a)) == 1);
+ assert(Py_ABS(Py_SIZE(b)) == 1);
+
+ if (Py_SIZE(a) == Py_SIZE(b)) {
+ /* 'a' and 'b' have the same sign. */
+ mod = left % right;
+ }
+ else {
+ /* Either 'a' or 'b' is negative. */
+ mod = right - 1 - (left - 1) % right;
+ }
+
+ return PyLong_FromLong(mod * (sdigit)Py_SIZE(b));
+}
+
+/* Fast floor division for single-digit longs. */
+static PyObject *
+fast_floor_div(PyLongObject *a, PyLongObject *b)
+{
+ sdigit left = a->ob_digit[0];
+ sdigit right = b->ob_digit[0];
+ sdigit div;
+
+ assert(Py_ABS(Py_SIZE(a)) == 1);
+ assert(Py_ABS(Py_SIZE(b)) == 1);
+
+ if (Py_SIZE(a) == Py_SIZE(b)) {
+ /* 'a' and 'b' have the same sign. */
+ div = left / right;
+ }
+ else {
+ /* Either 'a' or 'b' is negative. */
+ div = -1 - (left - 1) / right;
+ }
+
+ return PyLong_FromLong(div);
+}
+
/* The / and % operators are now defined in terms of divmod().
The expression a mod b has the value a - b*floor(a/b).
The long_divrem function gives the remainder after division of
@@ -3459,6 +3663,30 @@ l_divmod(PyLongObject *v, PyLongObject *w,
{
PyLongObject *div, *mod;
+ if (Py_ABS(Py_SIZE(v)) == 1 && Py_ABS(Py_SIZE(w)) == 1) {
+ /* Fast path for single-digit longs */
+ div = NULL;
+ if (pdiv != NULL) {
+ div = (PyLongObject *)fast_floor_div(v, w);
+ if (div == NULL) {
+ return -1;
+ }
+ }
+ if (pmod != NULL) {
+ mod = (PyLongObject *)fast_mod(v, w);
+ if (mod == NULL) {
+ Py_XDECREF(div);
+ return -1;
+ }
+ *pmod = mod;
+ }
+ if (pdiv != NULL) {
+ /* We only want to set `*pdiv` when `*pmod` is
+ set successfully. */
+ *pdiv = div;
+ }
+ return 0;
+ }
if (long_divrem(v, w, &div, &mod) < 0)
return -1;
if ((Py_SIZE(mod) < 0 && Py_SIZE(w) > 0) ||
@@ -3503,6 +3731,11 @@ long_div(PyObject *a, PyObject *b)
PyLongObject *div;
CHECK_BINOP(a, b);
+
+ if (Py_ABS(Py_SIZE(a)) == 1 && Py_ABS(Py_SIZE(b)) == 1) {
+ return fast_floor_div((PyLongObject*)a, (PyLongObject*)b);
+ }
+
if (l_divmod((PyLongObject*)a, (PyLongObject*)b, &div, NULL) < 0)
div = NULL;
return (PyObject *)div;
@@ -3742,9 +3975,9 @@ long_true_divide(PyObject *v, PyObject *w)
/* Round by directly modifying the low digit of x. */
mask = (digit)1 << (extra_bits - 1);
low = x->ob_digit[0] | inexact;
- if (low & mask && low & (3*mask-1))
+ if ((low & mask) && (low & (3U*mask-1U)))
low += mask;
- x->ob_digit[0] = low & ~(mask-1U);
+ x->ob_digit[0] = low & ~(2U*mask-1U);
/* Convert x to a double dx; the conversion is exact. */
dx = x->ob_digit[--x_size];
@@ -3778,6 +4011,10 @@ long_mod(PyObject *a, PyObject *b)
CHECK_BINOP(a, b);
+ if (Py_ABS(Py_SIZE(a)) == 1 && Py_ABS(Py_SIZE(b)) == 1) {
+ return fast_mod((PyLongObject*)a, (PyLongObject*)b);
+ }
+
if (l_divmod((PyLongObject*)a, (PyLongObject*)b, NULL, &mod) < 0)
mod = NULL;
return (PyObject *)mod;
@@ -4012,8 +4249,10 @@ long_invert(PyLongObject *v)
Py_DECREF(w);
if (x == NULL)
return NULL;
- Py_SIZE(x) = -(Py_SIZE(x));
- return (PyObject *)maybe_small_long(x);
+ _PyLong_Negate(&x);
+ /* No need for maybe_small_long here, since any small
+ longs will have been caught in the Py_SIZE <= 1 fast path. */
+ return (PyObject *)x;
}
static PyObject *
@@ -4118,6 +4357,11 @@ long_lshift(PyObject *v, PyObject *w)
PyErr_SetString(PyExc_ValueError, "negative shift count");
return NULL;
}
+
+ if (Py_SIZE(a) == 0) {
+ return PyLong_FromLong(0);
+ }
+
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */
wordshift = shiftby / PyLong_SHIFT;
remshift = shiftby - wordshift * PyLong_SHIFT;
@@ -4502,7 +4746,7 @@ simple:
/* a fits into a long, so b must too */
x = PyLong_AsLong((PyObject *)a);
y = PyLong_AsLong((PyObject *)b);
-#elif defined(PY_LONG_LONG) && PY_LLONG_MAX >> PyLong_SHIFT >> PyLong_SHIFT
+#elif PY_LLONG_MAX >> PyLong_SHIFT >> PyLong_SHIFT
x = PyLong_AsLongLong((PyObject *)a);
y = PyLong_AsLongLong((PyObject *)b);
#else
@@ -4521,7 +4765,7 @@ simple:
}
#if LONG_MAX >> PyLong_SHIFT >> PyLong_SHIFT
return PyLong_FromLong(x);
-#elif defined(PY_LONG_LONG) && PY_LLONG_MAX >> PyLong_SHIFT >> PyLong_SHIFT
+#elif PY_LLONG_MAX >> PyLong_SHIFT >> PyLong_SHIFT
return PyLong_FromLongLong(x);
#else
# error "_PyLong_GCD"
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index e261ee0cbf..b1798a2073 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -57,7 +57,7 @@
}
-Py_LOCAL_INLINE(_PyManagedBufferObject *)
+static inline _PyManagedBufferObject *
mbuf_alloc(void)
{
_PyManagedBufferObject *mbuf;
@@ -243,7 +243,7 @@ Create a new memoryview object which references the given object.");
#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \
(view->suboffsets && view->suboffsets[dest->ndim-1] >= 0)
-Py_LOCAL_INLINE(int)
+static inline int
last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
{
assert(dest->ndim > 0 && src->ndim > 0);
@@ -259,7 +259,7 @@ last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src)
assignments, where the lvalue is already known to have a single character
format. This is a performance hack that could be rewritten (if properly
benchmarked). */
-Py_LOCAL_INLINE(int)
+static inline int
equiv_format(const Py_buffer *dest, const Py_buffer *src)
{
const char *dfmt, *sfmt;
@@ -279,7 +279,7 @@ equiv_format(const Py_buffer *dest, const Py_buffer *src)
/* Two shapes are equivalent if they are either equal or identical up
to a zero element at the same position. For example, in NumPy arrays
the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */
-Py_LOCAL_INLINE(int)
+static inline int
equiv_shape(const Py_buffer *dest, const Py_buffer *src)
{
int i;
@@ -438,7 +438,7 @@ copy_buffer(Py_buffer *dest, Py_buffer *src)
}
/* Initialize strides for a C-contiguous array. */
-Py_LOCAL_INLINE(void)
+static inline void
init_strides_from_shape(Py_buffer *view)
{
Py_ssize_t i;
@@ -451,7 +451,7 @@ init_strides_from_shape(Py_buffer *view)
}
/* Initialize strides for a Fortran-contiguous array. */
-Py_LOCAL_INLINE(void)
+static inline void
init_fortran_strides_from_shape(Py_buffer *view)
{
Py_ssize_t i;
@@ -513,7 +513,7 @@ buffer_to_contiguous(char *mem, Py_buffer *src, char order)
/****************************************************************************/
/* Initialize values that are shared with the managed buffer. */
-Py_LOCAL_INLINE(void)
+static inline void
init_shared_values(Py_buffer *dest, const Py_buffer *src)
{
dest->obj = src->obj;
@@ -553,7 +553,7 @@ init_shape_strides(Py_buffer *dest, const Py_buffer *src)
}
}
-Py_LOCAL_INLINE(void)
+static inline void
init_suboffsets(Py_buffer *dest, const Py_buffer *src)
{
Py_ssize_t i;
@@ -567,7 +567,7 @@ init_suboffsets(Py_buffer *dest, const Py_buffer *src)
}
/* len = product(shape) * itemsize */
-Py_LOCAL_INLINE(void)
+static inline void
init_len(Py_buffer *view)
{
Py_ssize_t i, len;
@@ -614,7 +614,7 @@ init_flags(PyMemoryViewObject *mv)
/* Allocate a new memoryview and perform basic initialization. New memoryviews
are exclusively created through the mbuf_add functions. */
-Py_LOCAL_INLINE(PyMemoryViewObject *)
+static inline PyMemoryViewObject *
memory_alloc(int ndim)
{
PyMemoryViewObject *mv;
@@ -1099,7 +1099,7 @@ memory_exit(PyObject *self, PyObject *args)
#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c')
-Py_LOCAL_INLINE(Py_ssize_t)
+static inline Py_ssize_t
get_native_fmtchar(char *result, const char *fmt)
{
Py_ssize_t size = -1;
@@ -1111,17 +1111,11 @@ get_native_fmtchar(char *result, const char *fmt)
case 'h': case 'H': size = sizeof(short); break;
case 'i': case 'I': size = sizeof(int); break;
case 'l': case 'L': size = sizeof(long); break;
- #ifdef HAVE_LONG_LONG
- case 'q': case 'Q': size = sizeof(PY_LONG_LONG); break;
- #endif
+ case 'q': case 'Q': size = sizeof(long long); break;
case 'n': case 'N': size = sizeof(Py_ssize_t); break;
case 'f': size = sizeof(float); break;
case 'd': size = sizeof(double); break;
- #ifdef HAVE_C99_BOOL
case '?': size = sizeof(_Bool); break;
- #else
- case '?': size = sizeof(char); break;
- #endif
case 'P': size = sizeof(void *); break;
}
@@ -1133,7 +1127,7 @@ get_native_fmtchar(char *result, const char *fmt)
return -1;
}
-Py_LOCAL_INLINE(char *)
+static inline const char *
get_native_fmtstr(const char *fmt)
{
int at = 0;
@@ -1158,19 +1152,13 @@ get_native_fmtstr(const char *fmt)
case 'I': RETURN("I");
case 'l': RETURN("l");
case 'L': RETURN("L");
- #ifdef HAVE_LONG_LONG
case 'q': RETURN("q");
case 'Q': RETURN("Q");
- #endif
case 'n': RETURN("n");
case 'N': RETURN("N");
case 'f': RETURN("f");
case 'd': RETURN("d");
- #ifdef HAVE_C99_BOOL
case '?': RETURN("?");
- #else
- case '?': RETURN("?");
- #endif
case 'P': RETURN("P");
}
@@ -1221,7 +1209,7 @@ cast_to_1D(PyMemoryViewObject *mv, PyObject *format)
goto out;
}
- view->format = get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
+ view->format = (char *)get_native_fmtstr(PyBytes_AS_STRING(asciifmt));
if (view->format == NULL) {
/* NOT_REACHED: get_native_fmtchar() already validates the format. */
PyErr_SetString(PyExc_RuntimeError,
@@ -1581,12 +1569,11 @@ pylong_as_lu(PyObject *item)
return lu;
}
-#ifdef HAVE_LONG_LONG
-static PY_LONG_LONG
+static long long
pylong_as_lld(PyObject *item)
{
PyObject *tmp;
- PY_LONG_LONG lld;
+ long long lld;
tmp = PyNumber_Index(item);
if (tmp == NULL)
@@ -1597,21 +1584,20 @@ pylong_as_lld(PyObject *item)
return lld;
}
-static unsigned PY_LONG_LONG
+static unsigned long long
pylong_as_llu(PyObject *item)
{
PyObject *tmp;
- unsigned PY_LONG_LONG llu;
+ unsigned long long llu;
tmp = PyNumber_Index(item);
if (tmp == NULL)
- return (unsigned PY_LONG_LONG)-1;
+ return (unsigned long long)-1;
llu = PyLong_AsUnsignedLongLong(tmp);
Py_DECREF(tmp);
return llu;
}
-#endif
static Py_ssize_t
pylong_as_zd(PyObject *item)
@@ -1656,13 +1642,13 @@ pylong_as_zu(PyObject *item)
/* Unpack a single item. 'fmt' can be any native format character in struct
module syntax. This function is very sensitive to small changes. With this
layout gcc automatically generates a fast jump table. */
-Py_LOCAL_INLINE(PyObject *)
+static inline PyObject *
unpack_single(const char *ptr, const char *fmt)
{
- unsigned PY_LONG_LONG llu;
+ unsigned long long llu;
unsigned long lu;
size_t zu;
- PY_LONG_LONG lld;
+ long long lld;
long ld;
Py_ssize_t zd;
double d;
@@ -1679,11 +1665,7 @@ unpack_single(const char *ptr, const char *fmt)
case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld;
/* boolean */
- #ifdef HAVE_C99_BOOL
case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool;
- #else
- case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool;
- #endif
/* unsigned integers */
case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu;
@@ -1691,10 +1673,8 @@ unpack_single(const char *ptr, const char *fmt)
case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu;
/* native 64-bit */
- #ifdef HAVE_LONG_LONG
- case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld;
- case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu;
- #endif
+ case 'q': UNPACK_SINGLE(lld, ptr, long long); goto convert_lld;
+ case 'Q': UNPACK_SINGLE(llu, ptr, unsigned long long); goto convert_llu;
/* ssize_t and size_t */
case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd;
@@ -1755,10 +1735,10 @@ err_format:
static int
pack_single(char *ptr, PyObject *item, const char *fmt)
{
- unsigned PY_LONG_LONG llu;
+ unsigned long long llu;
unsigned long lu;
size_t zu;
- PY_LONG_LONG lld;
+ long long lld;
long ld;
Py_ssize_t zd;
double d;
@@ -1806,20 +1786,18 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
break;
/* native 64-bit */
- #ifdef HAVE_LONG_LONG
case 'q':
lld = pylong_as_lld(item);
if (lld == -1 && PyErr_Occurred())
goto err_occurred;
- PACK_SINGLE(ptr, lld, PY_LONG_LONG);
+ PACK_SINGLE(ptr, lld, long long);
break;
case 'Q':
llu = pylong_as_llu(item);
- if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
+ if (llu == (unsigned long long)-1 && PyErr_Occurred())
goto err_occurred;
- PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG);
+ PACK_SINGLE(ptr, llu, unsigned long long);
break;
- #endif
/* ssize_t and size_t */
case 'n':
@@ -1853,11 +1831,7 @@ pack_single(char *ptr, PyObject *item, const char *fmt)
ld = PyObject_IsTrue(item);
if (ld < 0)
return -1; /* preserve original error */
- #ifdef HAVE_C99_BOOL
PACK_SINGLE(ptr, ld, _Bool);
- #else
- PACK_SINGLE(ptr, ld, char);
- #endif
break;
/* bytes object */
@@ -2024,7 +1998,7 @@ struct_unpack_single(const char *ptr, struct unpacker *x)
/****************************************************************************/
/* allow explicit form of native format */
-Py_LOCAL_INLINE(const char *)
+static inline const char *
adjust_fmt(const Py_buffer *view)
{
const char *fmt;
@@ -2306,7 +2280,7 @@ memory_item_multi(PyMemoryViewObject *self, PyObject *tup)
return unpack_single(ptr, fmt);
}
-Py_LOCAL_INLINE(int)
+static inline int
init_slice(Py_buffer *base, PyObject *key, int dim)
{
Py_ssize_t start, stop, step, slicelength;
@@ -2628,7 +2602,7 @@ struct_unpack_cmp(const char *p, const char *q,
equal = (x == y); \
} while (0)
-Py_LOCAL_INLINE(int)
+static inline int
unpack_cmp(const char *p, const char *q, char fmt,
struct unpacker *unpack_p, struct unpacker *unpack_q)
{
@@ -2644,11 +2618,7 @@ unpack_cmp(const char *p, const char *q, char fmt,
case 'l': CMP_SINGLE(p, q, long); return equal;
/* boolean */
- #ifdef HAVE_C99_BOOL
case '?': CMP_SINGLE(p, q, _Bool); return equal;
- #else
- case '?': CMP_SINGLE(p, q, char); return equal;
- #endif
/* unsigned integers */
case 'H': CMP_SINGLE(p, q, unsigned short); return equal;
@@ -2656,10 +2626,8 @@ unpack_cmp(const char *p, const char *q, char fmt,
case 'L': CMP_SINGLE(p, q, unsigned long); return equal;
/* native 64-bit */
- #ifdef HAVE_LONG_LONG
- case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal;
- case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal;
- #endif
+ case 'q': CMP_SINGLE(p, q, long long); return equal;
+ case 'Q': CMP_SINGLE(p, q, unsigned long long); return equal;
/* ssize_t and size_t */
case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal;
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 946357f24a..c2001f0169 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -97,6 +97,11 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
if (flags == (METH_VARARGS | METH_KEYWORDS)) {
res = (*(PyCFunctionWithKeywords)meth)(self, args, kwds);
}
+ else if (flags == METH_FASTCALL) {
+ PyObject **stack = &PyTuple_GET_ITEM(args, 0);
+ Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+ res = _PyCFunction_FastCallDict(func, stack, nargs, kwds);
+ }
else {
if (kwds != NULL && PyDict_Size(kwds) != 0) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
@@ -145,6 +150,153 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
return _Py_CheckFunctionResult(func, res, NULL);
}
+PyObject *
+_PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
+ PyObject *kwargs)
+{
+ PyCFunctionObject *func = (PyCFunctionObject*)func_obj;
+ PyCFunction meth = PyCFunction_GET_FUNCTION(func);
+ PyObject *self = PyCFunction_GET_SELF(func);
+ PyObject *result;
+ int flags;
+
+ assert(PyCFunction_Check(func));
+ assert(func != NULL);
+ assert(nargs >= 0);
+ assert(nargs == 0 || args != NULL);
+ assert(kwargs == NULL || PyDict_Check(kwargs));
+
+ /* _PyCFunction_FastCallDict() must not be called with an exception set,
+ because it may clear it (directly or indirectly) and so the
+ caller loses its exception */
+ assert(!PyErr_Occurred());
+
+ flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
+
+ switch (flags)
+ {
+ case METH_NOARGS:
+ if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
+ PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
+ func->m_ml->ml_name);
+ return NULL;
+ }
+
+ if (nargs != 0) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes no arguments (%zd given)",
+ func->m_ml->ml_name, nargs);
+ return NULL;
+ }
+
+ result = (*meth) (self, NULL);
+ break;
+
+ case METH_O:
+ if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
+ PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
+ func->m_ml->ml_name);
+ return NULL;
+ }
+
+ if (nargs != 1) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes exactly one argument (%zd given)",
+ func->m_ml->ml_name, nargs);
+ return NULL;
+ }
+
+ result = (*meth) (self, args[0]);
+ break;
+
+ case METH_VARARGS:
+ case METH_VARARGS | METH_KEYWORDS:
+ {
+ /* Slow-path: create a temporary tuple */
+ PyObject *tuple;
+
+ if (!(flags & METH_KEYWORDS) && kwargs != NULL && PyDict_Size(kwargs) != 0) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes no keyword arguments",
+ func->m_ml->ml_name);
+ return NULL;
+ }
+
+ tuple = _PyStack_AsTuple(args, nargs);
+ if (tuple == NULL) {
+ return NULL;
+ }
+
+ if (flags & METH_KEYWORDS) {
+ result = (*(PyCFunctionWithKeywords)meth) (self, tuple, kwargs);
+ }
+ else {
+ result = (*meth) (self, tuple);
+ }
+ Py_DECREF(tuple);
+ break;
+ }
+
+ case METH_FASTCALL:
+ {
+ PyObject **stack;
+ PyObject *kwnames;
+ _PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
+
+ stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj);
+ if (stack == NULL) {
+ return NULL;
+ }
+
+ result = (*fastmeth) (self, stack, nargs, kwnames);
+ if (stack != args) {
+ PyMem_Free(stack);
+ }
+ Py_XDECREF(kwnames);
+ break;
+ }
+
+ default:
+ PyErr_SetString(PyExc_SystemError,
+ "Bad call flags in PyCFunction_Call. "
+ "METH_OLDARGS is no longer supported!");
+ return NULL;
+ }
+
+ result = _Py_CheckFunctionResult(func_obj, result, NULL);
+
+ return result;
+}
+
+PyObject *
+_PyCFunction_FastCallKeywords(PyObject *func, PyObject **stack,
+ Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *kwdict, *result;
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+
+ assert(PyCFunction_Check(func));
+ assert(nargs >= 0);
+ assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
+ assert((nargs == 0 && nkwargs == 0) || stack != NULL);
+ /* kwnames must only contains str strings, no subclass, and all keys must
+ be unique */
+
+ if (nkwargs > 0) {
+ kwdict = _PyStack_AsDict(stack + nargs, kwnames);
+ if (kwdict == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ kwdict = NULL;
+ }
+
+ result = _PyCFunction_FastCallDict(func, stack, nargs, kwdict);
+ Py_XDECREF(kwdict);
+ return result;
+}
+
/* Methods (the standard built-in methods, that is) */
static void
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index ae72da6e3b..79be51a806 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -380,7 +380,7 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def)
for (cur_slot = def->m_slots; cur_slot && cur_slot->slot; cur_slot++) {
switch (cur_slot->slot) {
case Py_mod_create:
- /* handled in PyModule_CreateFromSlots */
+ /* handled in PyModule_FromDefAndSpec2 */
break;
case Py_mod_exec:
ret = ((int (*)(PyObject *))cur_slot->value)(module);
@@ -450,8 +450,7 @@ PyModule_GetDict(PyObject *m)
return NULL;
}
d = ((PyModuleObject *)m) -> md_dict;
- if (d == NULL)
- ((PyModuleObject *)m) -> md_dict = d = PyDict_New();
+ assert(d != NULL);
return d;
}
@@ -484,7 +483,7 @@ PyModule_GetName(PyObject *m)
if (name == NULL)
return NULL;
Py_DECREF(name); /* module dict has still a reference */
- return _PyUnicode_AsString(name);
+ return PyUnicode_AsUTF8(name);
}
PyObject*
@@ -517,7 +516,7 @@ PyModule_GetFilename(PyObject *m)
fileobj = PyModule_GetFilenameObject(m);
if (fileobj == NULL)
return NULL;
- utf8 = _PyUnicode_AsString(fileobj);
+ utf8 = PyUnicode_AsUTF8(fileobj);
Py_DECREF(fileobj); /* module dict has still a reference */
return utf8;
}
@@ -570,7 +569,7 @@ _PyModule_ClearDict(PyObject *d)
if (PyUnicode_READ_CHAR(key, 0) == '_' &&
PyUnicode_READ_CHAR(key, 1) != '_') {
if (Py_VerboseFlag > 1) {
- const char *s = _PyUnicode_AsString(key);
+ const char *s = PyUnicode_AsUTF8(key);
if (s != NULL)
PySys_WriteStderr("# clear[1] %s\n", s);
else
@@ -590,7 +589,7 @@ _PyModule_ClearDict(PyObject *d)
!_PyUnicode_EqualToASCIIString(key, "__builtins__"))
{
if (Py_VerboseFlag > 1) {
- const char *s = _PyUnicode_AsString(key);
+ const char *s = PyUnicode_AsUTF8(key);
if (s != NULL)
PySys_WriteStderr("# clear[2] %s\n", s);
else
diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c
index 3d27a95f1f..0bb3063844 100644
--- a/Objects/namespaceobject.c
+++ b/Objects/namespaceobject.c
@@ -1,4 +1,4 @@
-/* namespace object implementation */
+// namespace object implementation
#include "Python.h"
#include "structmember.h"
@@ -16,7 +16,7 @@ static PyMemberDef namespace_members[] = {
};
-/* Methods */
+// Methods
static PyObject *
namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -40,7 +40,7 @@ namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int
namespace_init(_PyNamespaceObject *ns, PyObject *args, PyObject *kwds)
{
- /* ignore args if it's NULL or empty */
+ // ignore args if it's NULL or empty
if (args != NULL) {
Py_ssize_t argcount = PyObject_Size(args);
if (argcount < 0)
@@ -191,7 +191,7 @@ namespace_reduce(_PyNamespaceObject *ns)
static PyMethodDef namespace_methods[] = {
{"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS,
namespace_reduce__doc__},
- {NULL, NULL} /* sentinel */
+ {NULL, NULL} // sentinel
};
diff --git a/Objects/object.c b/Objects/object.c
index d21fd906df..d88ae3b94f 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -22,12 +22,6 @@ _Py_GetRefTotal(void)
{
PyObject *o;
Py_ssize_t total = _Py_RefTotal;
- /* ignore the references to the dummy object of the dicts and sets
- because they are not reliable and not useful (now that the
- hash table code is well-tested) */
- o = _PyDict_Dummy();
- if (o != NULL)
- total -= o->ob_refcnt;
o = _PySet_Dummy;
if (o != NULL)
total -= o->ob_refcnt;
@@ -109,6 +103,15 @@ void
dump_counts(FILE* f)
{
PyTypeObject *tp;
+ PyObject *xoptions, *value;
+ _Py_IDENTIFIER(showalloccount);
+
+ xoptions = PySys_GetXOptions();
+ if (xoptions == NULL)
+ return;
+ value = _PyDict_GetItemId(xoptions, &PyId_showalloccount);
+ if (value != Py_True)
+ return;
for (tp = type_list; tp; tp = tp->tp_next)
fprintf(f, "%s alloc'd: %" PY_FORMAT_SIZE_T "d, "
@@ -644,7 +647,7 @@ PyObject_Bytes(PyObject *v)
/* Map rich comparison operators to their swapped version, e.g. LT <--> GT */
int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
-static char *opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
+static const char * const opstrings[] = {"<", "<=", "==", "!=", ">", ">="};
/* Perform a rich comparison, raising TypeError when the requested comparison
operator is not supported. */
@@ -686,11 +689,10 @@ do_richcompare(PyObject *v, PyObject *w, int op)
res = (v != w) ? Py_True : Py_False;
break;
default:
- /* XXX Special-case None so it doesn't show as NoneType() */
PyErr_Format(PyExc_TypeError,
- "unorderable types: %.100s() %s %.100s()",
- v->ob_type->tp_name,
+ "'%s' not supported between instances of '%.100s' and '%.100s'",
opstrings[op],
+ v->ob_type->tp_name,
w->ob_type->tp_name);
return NULL;
}
@@ -888,7 +890,7 @@ PyObject_GetAttr(PyObject *v, PyObject *name)
if (tp->tp_getattro != NULL)
return (*tp->tp_getattro)(v, name);
if (tp->tp_getattr != NULL) {
- char *name_str = _PyUnicode_AsString(name);
+ char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
return NULL;
return (*tp->tp_getattr)(v, name_str);
@@ -932,7 +934,7 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
return err;
}
if (tp->tp_setattr != NULL) {
- char *name_str = _PyUnicode_AsString(name);
+ char *name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
return -1;
err = (*tp->tp_setattr)(v, name_str, value);
@@ -1041,8 +1043,7 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
name->ob_type->tp_name);
return NULL;
}
- else
- Py_INCREF(name);
+ Py_INCREF(name);
if (tp->tp_dict == NULL) {
if (PyType_Ready(tp) < 0)
@@ -1050,10 +1051,10 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
}
descr = _PyType_Lookup(tp, name);
- Py_XINCREF(descr);
f = NULL;
if (descr != NULL) {
+ Py_INCREF(descr);
f = descr->ob_type->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) {
res = f(descr, obj, (PyObject *)obj->ob_type);
@@ -1073,8 +1074,9 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, PyObject *dict)
if (tsize < 0)
tsize = -tsize;
size = _PyObject_VAR_SIZE(tp, tsize);
+ assert(size <= PY_SSIZE_T_MAX);
- dictoffset += (long)size;
+ dictoffset += (Py_ssize_t)size;
assert(dictoffset > 0);
assert(dictoffset % SIZEOF_VOID_P == 0);
}
@@ -1142,12 +1144,11 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
Py_INCREF(name);
descr = _PyType_Lookup(tp, name);
- Py_XINCREF(descr);
- f = NULL;
if (descr != NULL) {
+ Py_INCREF(descr);
f = descr->ob_type->tp_descr_set;
- if (f != NULL && PyDescr_IsData(descr)) {
+ if (f != NULL) {
res = f(descr, obj, value);
goto done;
}
@@ -1155,40 +1156,32 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
if (dict == NULL) {
dictptr = _PyObject_GetDictPtr(obj);
- if (dictptr != NULL) {
- res = _PyObjectDict_SetItem(Py_TYPE(obj), dictptr, name, value);
- if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
- PyErr_SetObject(PyExc_AttributeError, name);
+ if (dictptr == NULL) {
+ if (descr == NULL) {
+ PyErr_Format(PyExc_AttributeError,
+ "'%.100s' object has no attribute '%U'",
+ tp->tp_name, name);
+ }
+ else {
+ PyErr_Format(PyExc_AttributeError,
+ "'%.50s' object attribute '%U' is read-only",
+ tp->tp_name, name);
+ }
goto done;
}
+ res = _PyObjectDict_SetItem(tp, dictptr, name, value);
}
- if (dict != NULL) {
+ else {
Py_INCREF(dict);
if (value == NULL)
res = PyDict_DelItem(dict, name);
else
res = PyDict_SetItem(dict, name, value);
Py_DECREF(dict);
- if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
- PyErr_SetObject(PyExc_AttributeError, name);
- goto done;
- }
-
- if (f != NULL) {
- res = f(descr, obj, value);
- goto done;
}
+ if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
+ PyErr_SetObject(PyExc_AttributeError, name);
- if (descr == NULL) {
- PyErr_Format(PyExc_AttributeError,
- "'%.100s' object has no attribute '%U'",
- tp->tp_name, name);
- goto done;
- }
-
- PyErr_Format(PyExc_AttributeError,
- "'%.50s' object attribute '%U' is read-only",
- tp->tp_name, name);
done:
Py_XDECREF(descr);
Py_DECREF(name);
@@ -1204,7 +1197,7 @@ PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
int
PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
{
- PyObject *dict, **dictptr = _PyObject_GetDictPtr(obj);
+ PyObject **dictptr = _PyObject_GetDictPtr(obj);
if (dictptr == NULL) {
PyErr_SetString(PyExc_AttributeError,
"This object has no __dict__");
@@ -1220,10 +1213,8 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
"not a '%.200s'", Py_TYPE(value)->tp_name);
return -1;
}
- dict = *dictptr;
- Py_XINCREF(value);
- *dictptr = value;
- Py_XDECREF(dict);
+ Py_INCREF(value);
+ Py_XSETREF(*dictptr, value);
return 0;
}
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 7cc889f817..a1142f3b09 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -1,31 +1,42 @@
#include "Python.h"
+#include <stdbool.h>
+
+
+/* Defined in tracemalloc.c */
+extern void _PyMem_DumpTraceback(int fd, const void *ptr);
+
+
/* Python's malloc wrappers (see pymem.h) */
-#ifdef PYMALLOC_DEBUG /* WITH_PYMALLOC && PYMALLOC_DEBUG */
+#undef uint
+#define uint unsigned int /* assuming >= 16 bits */
+
/* Forward declaration */
+static void* _PyMem_DebugRawMalloc(void *ctx, size_t size);
+static void* _PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize);
+static void* _PyMem_DebugRawRealloc(void *ctx, void *ptr, size_t size);
+static void _PyMem_DebugRawFree(void *ctx, void *p);
+
static void* _PyMem_DebugMalloc(void *ctx, size_t size);
static void* _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize);
-static void _PyMem_DebugFree(void *ctx, void *p);
static void* _PyMem_DebugRealloc(void *ctx, void *ptr, size_t size);
+static void _PyMem_DebugFree(void *ctx, void *p);
static void _PyObject_DebugDumpAddress(const void *p);
static void _PyMem_DebugCheckAddress(char api_id, const void *p);
-#endif
#if defined(__has_feature) /* Clang */
#if __has_feature(address_sanitizer) /* is ASAN enabled? */
#define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
- __attribute__((no_address_safety_analysis)) \
- __attribute__ ((noinline))
+ __attribute__((no_address_safety_analysis))
#else
#define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
#endif
#else
#if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */
#define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
- __attribute__((no_address_safety_analysis)) \
- __attribute__ ((noinline))
+ __attribute__((no_address_safety_analysis))
#else
#define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
#endif
@@ -145,9 +156,8 @@ _PyObject_ArenaFree(void *ctx, void *ptr, size_t size)
#else
# define PYOBJ_FUNCS PYRAW_FUNCS
#endif
-#define PYMEM_FUNCS PYRAW_FUNCS
+#define PYMEM_FUNCS PYOBJ_FUNCS
-#ifdef PYMALLOC_DEBUG
typedef struct {
/* We tag each block with an API ID in order to tag API violations */
char api_id;
@@ -163,19 +173,21 @@ static struct {
{'o', {NULL, PYOBJ_FUNCS}}
};
-#define PYDBG_FUNCS _PyMem_DebugMalloc, _PyMem_DebugCalloc, _PyMem_DebugRealloc, _PyMem_DebugFree
-#endif
+#define PYRAWDBG_FUNCS \
+ _PyMem_DebugRawMalloc, _PyMem_DebugRawCalloc, _PyMem_DebugRawRealloc, _PyMem_DebugRawFree
+#define PYDBG_FUNCS \
+ _PyMem_DebugMalloc, _PyMem_DebugCalloc, _PyMem_DebugRealloc, _PyMem_DebugFree
static PyMemAllocatorEx _PyMem_Raw = {
-#ifdef PYMALLOC_DEBUG
- &_PyMem_Debug.raw, PYDBG_FUNCS
+#ifdef Py_DEBUG
+ &_PyMem_Debug.raw, PYRAWDBG_FUNCS
#else
NULL, PYRAW_FUNCS
#endif
};
static PyMemAllocatorEx _PyMem = {
-#ifdef PYMALLOC_DEBUG
+#ifdef Py_DEBUG
&_PyMem_Debug.mem, PYDBG_FUNCS
#else
NULL, PYMEM_FUNCS
@@ -183,16 +195,76 @@ static PyMemAllocatorEx _PyMem = {
};
static PyMemAllocatorEx _PyObject = {
-#ifdef PYMALLOC_DEBUG
+#ifdef Py_DEBUG
&_PyMem_Debug.obj, PYDBG_FUNCS
#else
NULL, PYOBJ_FUNCS
#endif
};
+int
+_PyMem_SetupAllocators(const char *opt)
+{
+ if (opt == NULL || *opt == '\0') {
+ /* PYTHONMALLOC is empty or is not set or ignored (-E/-I command line
+ options): use default allocators */
+#ifdef Py_DEBUG
+# ifdef WITH_PYMALLOC
+ opt = "pymalloc_debug";
+# else
+ opt = "malloc_debug";
+# endif
+#else
+ /* !Py_DEBUG */
+# ifdef WITH_PYMALLOC
+ opt = "pymalloc";
+# else
+ opt = "malloc";
+# endif
+#endif
+ }
+
+ if (strcmp(opt, "debug") == 0) {
+ PyMem_SetupDebugHooks();
+ }
+ else if (strcmp(opt, "malloc") == 0 || strcmp(opt, "malloc_debug") == 0)
+ {
+ PyMemAllocatorEx alloc = {NULL, PYRAW_FUNCS};
+
+ PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
+ PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
+ PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
+
+ if (strcmp(opt, "malloc_debug") == 0)
+ PyMem_SetupDebugHooks();
+ }
+#ifdef WITH_PYMALLOC
+ else if (strcmp(opt, "pymalloc") == 0
+ || strcmp(opt, "pymalloc_debug") == 0)
+ {
+ PyMemAllocatorEx raw_alloc = {NULL, PYRAW_FUNCS};
+ PyMemAllocatorEx mem_alloc = {NULL, PYMEM_FUNCS};
+ PyMemAllocatorEx obj_alloc = {NULL, PYOBJ_FUNCS};
+
+ PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &raw_alloc);
+ PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &mem_alloc);
+ PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &obj_alloc);
+
+ if (strcmp(opt, "pymalloc_debug") == 0)
+ PyMem_SetupDebugHooks();
+ }
+#endif
+ else {
+ /* unknown allocator */
+ return -1;
+ }
+ return 0;
+}
+
#undef PYRAW_FUNCS
#undef PYMEM_FUNCS
#undef PYOBJ_FUNCS
+#undef PYRAWDBG_FUNCS
#undef PYDBG_FUNCS
static PyObjectArenaAllocator _PyObject_Arena = {NULL,
@@ -205,23 +277,46 @@ static PyObjectArenaAllocator _PyObject_Arena = {NULL,
#endif
};
+#ifdef WITH_PYMALLOC
+static int
+_PyMem_DebugEnabled(void)
+{
+ return (_PyObject.malloc == _PyMem_DebugMalloc);
+}
+
+int
+_PyMem_PymallocEnabled(void)
+{
+ if (_PyMem_DebugEnabled()) {
+ return (_PyMem_Debug.obj.alloc.malloc == _PyObject_Malloc);
+ }
+ else {
+ return (_PyObject.malloc == _PyObject_Malloc);
+ }
+}
+#endif
+
void
PyMem_SetupDebugHooks(void)
{
-#ifdef PYMALLOC_DEBUG
PyMemAllocatorEx alloc;
- alloc.malloc = _PyMem_DebugMalloc;
- alloc.calloc = _PyMem_DebugCalloc;
- alloc.realloc = _PyMem_DebugRealloc;
- alloc.free = _PyMem_DebugFree;
+ alloc.malloc = _PyMem_DebugRawMalloc;
+ alloc.calloc = _PyMem_DebugRawCalloc;
+ alloc.realloc = _PyMem_DebugRawRealloc;
+ alloc.free = _PyMem_DebugRawFree;
- if (_PyMem_Raw.malloc != _PyMem_DebugMalloc) {
+ if (_PyMem_Raw.malloc != _PyMem_DebugRawMalloc) {
alloc.ctx = &_PyMem_Debug.raw;
PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &_PyMem_Debug.raw.alloc);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
}
+ alloc.malloc = _PyMem_DebugMalloc;
+ alloc.calloc = _PyMem_DebugCalloc;
+ alloc.realloc = _PyMem_DebugRealloc;
+ alloc.free = _PyMem_DebugFree;
+
if (_PyMem.malloc != _PyMem_DebugMalloc) {
alloc.ctx = &_PyMem_Debug.mem;
PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &_PyMem_Debug.mem.alloc);
@@ -233,7 +328,6 @@ PyMem_SetupDebugHooks(void)
PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &_PyMem_Debug.obj.alloc);
PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
}
-#endif
}
void
@@ -264,7 +358,6 @@ PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
case PYMEM_DOMAIN_OBJ: _PyObject = *allocator; break;
/* ignore unknown domain */
}
-
}
void
@@ -642,24 +735,8 @@ static int running_on_valgrind = -1;
#define SIMPLELOCK_LOCK(lock) /* acquire released lock */
#define SIMPLELOCK_UNLOCK(lock) /* release acquired lock */
-/*
- * Basic types
- * I don't care if these are defined in <sys/types.h> or elsewhere. Axiom.
- */
-#undef uchar
-#define uchar unsigned char /* assuming == 8 bits */
-
-#undef uint
-#define uint unsigned int /* assuming >= 16 bits */
-
-#undef ulong
-#define ulong unsigned long /* assuming >= 32 bits */
-
-#undef uptr
-#define uptr Py_uintptr_t
-
/* When you say memory, my mind reasons in terms of (pointers to) blocks */
-typedef uchar block;
+typedef uint8_t block;
/* Pool for small blocks. */
struct pool_header {
@@ -683,7 +760,7 @@ struct arena_object {
* here to mark an arena_object that doesn't correspond to an
* allocated arena.
*/
- uptr address;
+ uintptr_t address;
/* Pool-aligned pointer to the next pool to be carved off. */
block* pool_address;
@@ -834,7 +911,7 @@ on that C doesn't insert any padding anywhere in a pool_header at or before
the prevpool member.
**************************************************************************** */
-#define PTA(x) ((poolp )((uchar *)&(usedpools[2*(x)]) - 2*sizeof(block *)))
+#define PTA(x) ((poolp )((uint8_t *)&(usedpools[2*(x)]) - 2*sizeof(block *)))
#define PT(x) PTA(x), PTA(x)
static poolp usedpools[2 * ((NB_SMALL_SIZE_CLASSES + 7) / 8) * 8] = {
@@ -949,11 +1026,15 @@ new_arena(void)
struct arena_object* arenaobj;
uint excess; /* number of bytes above pool alignment */
void *address;
+ static int debug_stats = -1;
-#ifdef PYMALLOC_DEBUG
- if (Py_GETENV("PYTHONMALLOCSTATS"))
+ if (debug_stats == -1) {
+ char *opt = Py_GETENV("PYTHONMALLOCSTATS");
+ debug_stats = (opt != NULL && *opt != '\0');
+ }
+ if (debug_stats)
_PyObject_DebugMallocStats(stderr);
-#endif
+
if (unused_arena_objects == NULL) {
uint i;
uint numarenas;
@@ -966,7 +1047,7 @@ new_arena(void)
if (numarenas <= maxarenas)
return NULL; /* overflow */
#if SIZEOF_SIZE_T <= SIZEOF_INT
- if (numarenas > PY_SIZE_MAX / sizeof(*arenas))
+ if (numarenas > SIZE_MAX / sizeof(*arenas))
return NULL; /* overflow */
#endif
nbytes = numarenas * sizeof(*arenas);
@@ -1010,7 +1091,7 @@ new_arena(void)
unused_arena_objects = arenaobj;
return NULL;
}
- arenaobj->address = (uptr)address;
+ arenaobj->address = (uintptr_t)address;
++narenas_currently_allocated;
++ntimes_arena_allocated;
@@ -1033,13 +1114,13 @@ new_arena(void)
}
/*
-Py_ADDRESS_IN_RANGE(P, POOL)
+address_in_range(P, POOL)
Return true if and only if P is an address that was allocated by pymalloc.
POOL must be the pool address associated with P, i.e., POOL = POOL_ADDR(P)
(the caller is asked to compute this because the macro expands POOL more than
once, and for efficiency it's best for the caller to assign POOL_ADDR(P) to a
-variable and pass the latter to the macro; because Py_ADDRESS_IN_RANGE is
+variable and pass the latter to the macro; because address_in_range is
called on every alloc/realloc/free, micro-efficiency is important here).
Tricky: Let B be the arena base address associated with the pool, B =
@@ -1064,7 +1145,7 @@ arenas[(POOL)->arenaindex]. Suppose obmalloc controls P. Then (barring wild
stores, etc), POOL is the correct address of P's pool, AO.address is the
correct base address of the pool's arena, and P must be within ARENA_SIZE of
AO.address. In addition, AO.address is not 0 (no arena can start at address 0
-(NULL)). Therefore Py_ADDRESS_IN_RANGE correctly reports that obmalloc
+(NULL)). Therefore address_in_range correctly reports that obmalloc
controls P.
Now suppose obmalloc does not control P (e.g., P was obtained via a direct
@@ -1105,51 +1186,21 @@ that this test determines whether an arbitrary address is controlled by
obmalloc in a small constant time, independent of the number of arenas
obmalloc controls. Since this test is needed at every entry point, it's
extremely desirable that it be this fast.
-
-Since Py_ADDRESS_IN_RANGE may be reading from memory which was not allocated
-by Python, it is important that (POOL)->arenaindex is read only once, as
-another thread may be concurrently modifying the value without holding the
-GIL. To accomplish this, the arenaindex_temp variable is used to store
-(POOL)->arenaindex for the duration of the Py_ADDRESS_IN_RANGE macro's
-execution. The caller of the macro is responsible for declaring this
-variable.
*/
-#define Py_ADDRESS_IN_RANGE(P, POOL) \
- ((arenaindex_temp = (POOL)->arenaindex) < maxarenas && \
- (uptr)(P) - arenas[arenaindex_temp].address < (uptr)ARENA_SIZE && \
- arenas[arenaindex_temp].address != 0)
-
-
-/* This is only useful when running memory debuggers such as
- * Purify or Valgrind. Uncomment to use.
- *
-#define Py_USING_MEMORY_DEBUGGER
- */
-
-#ifdef Py_USING_MEMORY_DEBUGGER
-
-/* Py_ADDRESS_IN_RANGE may access uninitialized memory by design
- * This leads to thousands of spurious warnings when using
- * Purify or Valgrind. By making a function, we can easily
- * suppress the uninitialized memory reads in this one function.
- * So we won't ignore real errors elsewhere.
- *
- * Disable the macro and use a function.
- */
-
-#undef Py_ADDRESS_IN_RANGE
-
-#if defined(__GNUC__) && ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) || \
- (__GNUC__ >= 4))
-#define Py_NO_INLINE __attribute__((__noinline__))
-#else
-#define Py_NO_INLINE
-#endif
-/* Don't make static, to try to ensure this isn't inlined. */
-int Py_ADDRESS_IN_RANGE(void *P, poolp pool) Py_NO_INLINE;
-#undef Py_NO_INLINE
-#endif
+static bool ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
+address_in_range(void *p, poolp pool)
+{
+ // Since address_in_range may be reading from memory which was not allocated
+ // by Python, it is important that pool->arenaindex is read only once, as
+ // another thread may be concurrently modifying the value without holding
+ // the GIL. The following dance forces the compiler to read pool->arenaindex
+ // only once.
+ uint arenaindex = *((volatile uint *)&pool->arenaindex);
+ return arenaindex < maxarenas &&
+ (uintptr_t)p - arenas[arenaindex].address < ARENA_SIZE &&
+ arenas[arenaindex].address != 0;
+}
/*==========================================================================*/
@@ -1394,7 +1445,6 @@ _PyObject_Calloc(void *ctx, size_t nelem, size_t elsize)
/* free */
-ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
static void
_PyObject_Free(void *ctx, void *p)
{
@@ -1402,9 +1452,6 @@ _PyObject_Free(void *ctx, void *p)
block *lastfree;
poolp next, prev;
uint size;
-#ifndef Py_USING_MEMORY_DEBUGGER
- uint arenaindex_temp;
-#endif
if (p == NULL) /* free(NULL) has no effect */
return;
@@ -1417,7 +1464,7 @@ _PyObject_Free(void *ctx, void *p)
#endif
pool = POOL_ADDR(p);
- if (Py_ADDRESS_IN_RANGE(p, pool)) {
+ if (address_in_range(p, pool)) {
/* We allocated this address. */
LOCK();
/* Link p to the start of the pool's freeblock list. Since
@@ -1623,16 +1670,12 @@ redirect:
* return a non-NULL result.
*/
-ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
static void *
_PyObject_Realloc(void *ctx, void *p, size_t nbytes)
{
void *bp;
poolp pool;
size_t size;
-#ifndef Py_USING_MEMORY_DEBUGGER
- uint arenaindex_temp;
-#endif
if (p == NULL)
return _PyObject_Alloc(0, ctx, 1, nbytes);
@@ -1644,7 +1687,7 @@ _PyObject_Realloc(void *ctx, void *p, size_t nbytes)
#endif
pool = POOL_ADDR(p);
- if (Py_ADDRESS_IN_RANGE(p, pool)) {
+ if (address_in_range(p, pool)) {
/* We're in charge of this block */
size = INDEX2SIZE(pool->szidx);
if (nbytes <= size) {
@@ -1709,7 +1752,7 @@ _Py_GetAllocatedBlocks(void)
#endif /* WITH_PYMALLOC */
-#ifdef PYMALLOC_DEBUG
+
/*==========================================================================*/
/* A x-platform debugging allocator. This doesn't manage memory directly,
* it wraps a real allocator, adding extra debugging info to the memory blocks.
@@ -1743,7 +1786,7 @@ bumpserialno(void)
static size_t
read_size_t(const void *p)
{
- const uchar *q = (const uchar *)p;
+ const uint8_t *q = (const uint8_t *)p;
size_t result = *q++;
int i;
@@ -1758,40 +1801,15 @@ read_size_t(const void *p)
static void
write_size_t(void *p, size_t n)
{
- uchar *q = (uchar *)p + SST - 1;
+ uint8_t *q = (uint8_t *)p + SST - 1;
int i;
for (i = SST; --i >= 0; --q) {
- *q = (uchar)(n & 0xff);
+ *q = (uint8_t)(n & 0xff);
n >>= 8;
}
}
-#ifdef Py_DEBUG
-/* Is target in the list? The list is traversed via the nextpool pointers.
- * The list may be NULL-terminated, or circular. Return 1 if target is in
- * list, else 0.
- */
-static int
-pool_is_in_list(const poolp target, poolp list)
-{
- poolp origlist = list;
- assert(target != NULL);
- if (list == NULL)
- return 0;
- do {
- if (target == list)
- return 1;
- list = list->nextpool;
- } while (list != NULL && list != origlist);
- return 0;
-}
-
-#else
-#define pool_is_in_list(X, Y) 1
-
-#endif /* Py_DEBUG */
-
/* Let S = sizeof(size_t). The debug malloc asks for 4*S extra bytes and
fills them with useful stuff, here calling the underlying malloc's result p:
@@ -1819,11 +1837,11 @@ p[2*S+n+S: 2*S+n+2*S]
*/
static void *
-_PyMem_DebugAlloc(int use_calloc, void *ctx, size_t nbytes)
+_PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
{
debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
- uchar *p; /* base address of malloc'ed block */
- uchar *tail; /* p + 2*SST + nbytes == pointer to tail pad bytes */
+ uint8_t *p; /* base address of malloc'ed block */
+ uint8_t *tail; /* p + 2*SST + nbytes == pointer to tail pad bytes */
size_t total; /* nbytes + 4*SST */
bumpserialno();
@@ -1833,15 +1851,15 @@ _PyMem_DebugAlloc(int use_calloc, void *ctx, size_t nbytes)
return NULL;
if (use_calloc)
- p = (uchar *)api->alloc.calloc(api->alloc.ctx, 1, total);
+ p = (uint8_t *)api->alloc.calloc(api->alloc.ctx, 1, total);
else
- p = (uchar *)api->alloc.malloc(api->alloc.ctx, total);
+ p = (uint8_t *)api->alloc.malloc(api->alloc.ctx, total);
if (p == NULL)
return NULL;
/* at p, write size (SST bytes), id (1 byte), pad (SST-1 bytes) */
write_size_t(p, nbytes);
- p[SST] = (uchar)api->api_id;
+ p[SST] = (uint8_t)api->api_id;
memset(p + SST + 1, FORBIDDENBYTE, SST-1);
if (nbytes > 0 && !use_calloc)
@@ -1856,18 +1874,18 @@ _PyMem_DebugAlloc(int use_calloc, void *ctx, size_t nbytes)
}
static void *
-_PyMem_DebugMalloc(void *ctx, size_t nbytes)
+_PyMem_DebugRawMalloc(void *ctx, size_t nbytes)
{
- return _PyMem_DebugAlloc(0, ctx, nbytes);
+ return _PyMem_DebugRawAlloc(0, ctx, nbytes);
}
static void *
-_PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize)
+_PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize)
{
size_t nbytes;
assert(elsize == 0 || nelem <= PY_SSIZE_T_MAX / elsize);
nbytes = nelem * elsize;
- return _PyMem_DebugAlloc(1, ctx, nbytes);
+ return _PyMem_DebugRawAlloc(1, ctx, nbytes);
}
/* The debug free first checks the 2*SST bytes on each end for sanity (in
@@ -1876,10 +1894,10 @@ _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize)
Then calls the underlying free.
*/
static void
-_PyMem_DebugFree(void *ctx, void *p)
+_PyMem_DebugRawFree(void *ctx, void *p)
{
debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
- uchar *q = (uchar *)p - 2*SST; /* address returned from malloc */
+ uint8_t *q = (uint8_t *)p - 2*SST; /* address returned from malloc */
size_t nbytes;
if (p == NULL)
@@ -1893,17 +1911,17 @@ _PyMem_DebugFree(void *ctx, void *p)
}
static void *
-_PyMem_DebugRealloc(void *ctx, void *p, size_t nbytes)
+_PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
{
debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
- uchar *q = (uchar *)p, *oldq;
- uchar *tail;
+ uint8_t *q = (uint8_t *)p, *oldq;
+ uint8_t *tail;
size_t total; /* nbytes + 4*SST */
size_t original_nbytes;
int i;
if (p == NULL)
- return _PyMem_DebugAlloc(0, ctx, nbytes);
+ return _PyMem_DebugRawAlloc(0, ctx, nbytes);
_PyMem_DebugCheckAddress(api->api_id, p);
bumpserialno();
@@ -1918,7 +1936,7 @@ _PyMem_DebugRealloc(void *ctx, void *p, size_t nbytes)
* but we live with that.
*/
oldq = q;
- q = (uchar *)api->alloc.realloc(api->alloc.ctx, q - 2*SST, total);
+ q = (uint8_t *)api->alloc.realloc(api->alloc.ctx, q - 2*SST, total);
if (q == NULL)
return NULL;
@@ -1928,7 +1946,7 @@ _PyMem_DebugRealloc(void *ctx, void *p, size_t nbytes)
}
write_size_t(q, nbytes);
- assert(q[SST] == (uchar)api->api_id);
+ assert(q[SST] == (uint8_t)api->api_id);
for (i = 1; i < SST; ++i)
assert(q[SST + i] == FORBIDDENBYTE);
q += 2*SST;
@@ -1946,6 +1964,44 @@ _PyMem_DebugRealloc(void *ctx, void *p, size_t nbytes)
return q;
}
+static void
+_PyMem_DebugCheckGIL(void)
+{
+#ifdef WITH_THREAD
+ if (!PyGILState_Check())
+ Py_FatalError("Python memory allocator called "
+ "without holding the GIL");
+#endif
+}
+
+static void *
+_PyMem_DebugMalloc(void *ctx, size_t nbytes)
+{
+ _PyMem_DebugCheckGIL();
+ return _PyMem_DebugRawMalloc(ctx, nbytes);
+}
+
+static void *
+_PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize)
+{
+ _PyMem_DebugCheckGIL();
+ return _PyMem_DebugRawCalloc(ctx, nelem, elsize);
+}
+
+static void
+_PyMem_DebugFree(void *ctx, void *ptr)
+{
+ _PyMem_DebugCheckGIL();
+ _PyMem_DebugRawFree(ctx, ptr);
+}
+
+static void *
+_PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
+{
+ _PyMem_DebugCheckGIL();
+ return _PyMem_DebugRawRealloc(ctx, ptr, nbytes);
+}
+
/* Check the forbidden bytes on both ends of the memory allocated for p.
* If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress,
* and call Py_FatalError to kill the program.
@@ -1954,11 +2010,11 @@ _PyMem_DebugRealloc(void *ctx, void *p, size_t nbytes)
static void
_PyMem_DebugCheckAddress(char api, const void *p)
{
- const uchar *q = (const uchar *)p;
+ const uint8_t *q = (const uint8_t *)p;
char msgbuf[64];
char *msg;
size_t nbytes;
- const uchar *tail;
+ const uint8_t *tail;
int i;
char id;
@@ -2007,8 +2063,8 @@ error:
static void
_PyObject_DebugDumpAddress(const void *p)
{
- const uchar *q = (const uchar *)p;
- const uchar *tail;
+ const uint8_t *q = (const uint8_t *)p;
+ const uint8_t *tail;
size_t nbytes, serial;
int i;
int ok;
@@ -2041,7 +2097,7 @@ _PyObject_DebugDumpAddress(const void *p)
fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
FORBIDDENBYTE);
for (i = SST-1; i >= 1; --i) {
- const uchar byte = *(q-i);
+ const uint8_t byte = *(q-i);
fprintf(stderr, " at p-%d: 0x%02x", i, byte);
if (byte != FORBIDDENBYTE)
fputs(" *** OUCH", stderr);
@@ -2069,7 +2125,7 @@ _PyObject_DebugDumpAddress(const void *p)
fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
FORBIDDENBYTE);
for (i = 0; i < SST; ++i) {
- const uchar byte = tail[i];
+ const uint8_t byte = tail[i];
fprintf(stderr, " at tail+%d: 0x%02x",
i, byte);
if (byte != FORBIDDENBYTE)
@@ -2104,9 +2160,12 @@ _PyObject_DebugDumpAddress(const void *p)
}
fputc('\n', stderr);
}
+ fputc('\n', stderr);
+
+ fflush(stderr);
+ _PyMem_DumpTraceback(fileno(stderr), p);
}
-#endif /* PYMALLOC_DEBUG */
static size_t
printone(FILE *out, const char* msg, size_t value)
@@ -2158,8 +2217,30 @@ _PyDebugAllocatorStats(FILE *out,
(void)printone(out, buf2, num_blocks * sizeof_block);
}
+
#ifdef WITH_PYMALLOC
+#ifdef Py_DEBUG
+/* Is target in the list? The list is traversed via the nextpool pointers.
+ * The list may be NULL-terminated, or circular. Return 1 if target is in
+ * list, else 0.
+ */
+static int
+pool_is_in_list(const poolp target, poolp list)
+{
+ poolp origlist = list;
+ assert(target != NULL);
+ if (list == NULL)
+ return 0;
+ do {
+ if (target == list)
+ return 1;
+ list = list->nextpool;
+ } while (list != NULL && list != origlist);
+ return 0;
+}
+#endif
+
/* Print summary info to "out" about the state of pymalloc's structures.
* In Py_DEBUG mode, also perform some expensive internal consistency
* checks.
@@ -2206,34 +2287,35 @@ _PyObject_DebugMallocStats(FILE *out)
*/
for (i = 0; i < maxarenas; ++i) {
uint j;
- uptr base = arenas[i].address;
+ uintptr_t base = arenas[i].address;
/* Skip arenas which are not allocated. */
- if (arenas[i].address == (uptr)NULL)
+ if (arenas[i].address == (uintptr_t)NULL)
continue;
narenas += 1;
numfreepools += arenas[i].nfreepools;
/* round up to pool alignment */
- if (base & (uptr)POOL_SIZE_MASK) {
+ if (base & (uintptr_t)POOL_SIZE_MASK) {
arena_alignment += POOL_SIZE;
- base &= ~(uptr)POOL_SIZE_MASK;
+ base &= ~(uintptr_t)POOL_SIZE_MASK;
base += POOL_SIZE;
}
/* visit every pool in the arena */
- assert(base <= (uptr) arenas[i].pool_address);
- for (j = 0;
- base < (uptr) arenas[i].pool_address;
- ++j, base += POOL_SIZE) {
+ assert(base <= (uintptr_t) arenas[i].pool_address);
+ for (j = 0; base < (uintptr_t) arenas[i].pool_address;
+ ++j, base += POOL_SIZE) {
poolp p = (poolp)base;
const uint sz = p->szidx;
uint freeblocks;
if (p->ref.count == 0) {
/* currently unused */
+#ifdef Py_DEBUG
assert(pool_is_in_list(p, arenas[i].freepools));
+#endif
continue;
}
++numpools[sz];
@@ -2273,9 +2355,8 @@ _PyObject_DebugMallocStats(FILE *out)
quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
}
fputc('\n', out);
-#ifdef PYMALLOC_DEBUG
- (void)printone(out, "# times object malloc called", serialno);
-#endif
+ if (_PyMem_DebugEnabled())
+ (void)printone(out, "# times object malloc called", serialno);
(void)printone(out, "# arenas allocated total", ntimes_arena_allocated);
(void)printone(out, "# arenas reclaimed", ntimes_arena_allocated - narenas);
(void)printone(out, "# arenas highwater mark", narenas_highwater);
@@ -2302,18 +2383,3 @@ _PyObject_DebugMallocStats(FILE *out)
}
#endif /* #ifdef WITH_PYMALLOC */
-
-#ifdef Py_USING_MEMORY_DEBUGGER
-/* Make this function last so gcc won't inline it since the definition is
- * after the reference.
- */
-int
-Py_ADDRESS_IN_RANGE(void *P, poolp pool)
-{
- uint arenaindex_temp = pool->arenaindex;
-
- return arenaindex_temp < maxarenas &&
- (uptr)P - arenas[arenaindex_temp].address < (uptr)ARENA_SIZE &&
- arenas[arenaindex_temp].address != 0;
-}
-#endif
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 73deedf360..f9f1bf362e 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -39,7 +39,7 @@ we've considered:
__getitem__(), get(), etc. accordingly.
The approach with the least performance impact (time and space) is #2,
-mirroring the key order of dict's dk_enties with an array of node pointers.
+mirroring the key order of dict's dk_entries with an array of node pointers.
While lookdict() and friends (dk_lookup) don't give us the index into the
array, we make use of pointer arithmetic to get that index. An alternative
would be to refactor lookdict() to provide the index, explicitly exposing
@@ -536,14 +536,17 @@ static Py_ssize_t
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
{
PyObject **value_addr = NULL;
- PyDictKeyEntry *ep;
PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
+ Py_ssize_t ix;
- ep = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr);
- if (ep == NULL)
+ ix = (keys->dk_lookup)((PyDictObject *)od, key, hash, &value_addr, NULL);
+ if (ix == DKIX_EMPTY) {
+ return keys->dk_nentries; /* index of new entry */
+ }
+ if (ix < 0)
return -1;
/* We use pointer arithmetic to get the entry's index into the table. */
- return ep - keys->dk_entries;
+ return ix;
}
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
@@ -565,7 +568,7 @@ _odict_resize(PyODictObject *od) {
/* Copy the current nodes into the table. */
_odict_FOREACH(od, node) {
i = _odict_get_index_raw(od, _odictnode_KEY(node),
- _odictnode_HASH(node));
+ _odictnode_HASH(node));
if (i < 0) {
PyMem_FREE(fast_nodes);
return -1;
@@ -1424,14 +1427,13 @@ static PyMethodDef odict_methods[] = {
* OrderedDict members
*/
-/* tp_members */
+/* tp_getset */
-static PyMemberDef odict_members[] = {
- {"__dict__", T_OBJECT, offsetof(PyODictObject, od_inst_dict), READONLY},
- {0}
+static PyGetSetDef odict_getset[] = {
+ {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
+ {NULL}
};
-
/* ----------------------------------------------
* OrderedDict type slot methods
*/
@@ -1463,7 +1465,7 @@ odict_dealloc(PyODictObject *self)
++tstate->trash_delete_nesting;
Py_TRASHCAN_SAFE_END(self)
-};
+}
/* tp_repr */
@@ -1540,7 +1542,7 @@ Done:
Py_XDECREF(pieces);
Py_ReprLeave((PyObject *)self);
return result;
-};
+}
/* tp_doc */
@@ -1612,7 +1614,7 @@ odict_richcompare(PyObject *v, PyObject *w, int op)
} else {
Py_RETURN_NOTIMPLEMENTED;
}
-};
+}
/* tp_iter */
@@ -1620,7 +1622,7 @@ static PyObject *
odict_iter(PyODictObject *od)
{
return odictiter_new(od, _odict_ITER_KEYS);
-};
+}
/* tp_init */
@@ -1646,27 +1648,19 @@ odict_init(PyObject *self, PyObject *args, PyObject *kwds)
Py_DECREF(res);
return 0;
}
-};
+}
/* tp_new */
static PyObject *
odict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyObject *dict;
PyODictObject *od;
- dict = PyDict_New();
- if (dict == NULL)
- return NULL;
-
od = (PyODictObject *)PyDict_Type.tp_new(type, args, kwds);
- if (od == NULL) {
- Py_DECREF(dict);
+ if (od == NULL)
return NULL;
- }
- od->od_inst_dict = dict;
/* type constructor fills the memory with zeros (see
PyType_GenericAlloc()), there is no need to set them to zero again */
if (_odict_resize(od) < 0) {
@@ -1708,8 +1702,8 @@ PyTypeObject PyODict_Type = {
(getiterfunc)odict_iter, /* tp_iter */
0, /* tp_iternext */
odict_methods, /* tp_methods */
- odict_members, /* tp_members */
- 0, /* tp_getset */
+ 0, /* tp_members */
+ odict_getset, /* tp_getset */
&PyDict_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
@@ -1729,7 +1723,7 @@ PyTypeObject PyODict_Type = {
PyObject *
PyODict_New(void) {
return odict_new(&PyODict_Type, NULL, NULL);
-};
+}
static int
_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
@@ -1747,7 +1741,7 @@ _PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
}
}
return res;
-};
+}
int
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
@@ -1756,7 +1750,7 @@ PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
if (hash == -1)
return -1;
return _PyODict_SetItem_KnownHash(od, key, value, hash);
-};
+}
int
PyODict_DelItem(PyObject *od, PyObject *key)
@@ -1769,7 +1763,7 @@ PyODict_DelItem(PyObject *od, PyObject *key)
if (res < 0)
return -1;
return _PyDict_DelItem_KnownHash(od, key, hash);
-};
+}
/* -------------------------------------------
@@ -2362,8 +2356,7 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
PyObject *other = PyTuple_GET_ITEM(args, 0); /* borrowed reference */
assert(other != NULL);
Py_INCREF(other);
- if (PyDict_CheckExact(other) ||
- _PyObject_HasAttrId(other, &PyId_items)) { /* never fails */
+ if PyDict_CheckExact(other) {
PyObject *items;
if (PyDict_CheckExact(other))
items = PyDict_Items(other);
@@ -2406,6 +2399,20 @@ mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
if (res != 0 || PyErr_Occurred())
return NULL;
}
+ else if (_PyObject_HasAttrId(other, &PyId_items)) { /* never fails */
+ PyObject *items;
+ if (PyDict_CheckExact(other))
+ items = PyDict_Items(other);
+ else
+ items = _PyObject_CallMethodId(other, &PyId_items, NULL);
+ Py_DECREF(other);
+ if (items == NULL)
+ return NULL;
+ res = mutablemapping_add_pairs(self, items);
+ Py_DECREF(items);
+ if (res == -1)
+ return NULL;
+ }
else {
res = mutablemapping_add_pairs(self, other);
Py_DECREF(other);
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 899697aa3a..8449fc7a24 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -6,7 +6,7 @@
/* Support objects whose length is > PY_SSIZE_T_MAX.
This could be sped up for small PyLongs if they fit in a Py_ssize_t.
- This only matters on Win64. Though we could use PY_LONG_LONG which
+ This only matters on Win64. Though we could use long long which
would presumably help perf.
*/
@@ -29,17 +29,10 @@ validate_step(PyObject *step)
return PyLong_FromLong(1);
step = PyNumber_Index(step);
- if (step) {
- Py_ssize_t istep = PyNumber_AsSsize_t(step, NULL);
- if (istep == -1 && PyErr_Occurred()) {
- /* Ignore OverflowError, we know the value isn't 0. */
- PyErr_Clear();
- }
- else if (istep == 0) {
- PyErr_SetString(PyExc_ValueError,
- "range() arg 3 must not be zero");
- Py_CLEAR(step);
- }
+ if (step && _PyLong_Sign(step) == 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "range() arg 3 must not be zero");
+ Py_CLEAR(step);
}
return step;
@@ -129,9 +122,9 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
return (PyObject *) obj;
/* Failed to create object, release attributes */
- Py_XDECREF(start);
- Py_XDECREF(stop);
- Py_XDECREF(step);
+ Py_DECREF(start);
+ Py_DECREF(stop);
+ Py_DECREF(step);
return NULL;
}
@@ -196,7 +189,7 @@ compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
/* if (lo >= hi), return length of 0. */
cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE);
if (cmp_result != 0) {
- Py_XDECREF(step);
+ Py_DECREF(step);
if (cmp_result < 0)
return NULL;
return PyLong_FromLong(0);
@@ -225,9 +218,9 @@ compute_range_length(PyObject *start, PyObject *stop, PyObject *step)
return result;
Fail:
+ Py_DECREF(step);
Py_XDECREF(tmp2);
Py_XDECREF(diff);
- Py_XDECREF(step);
Py_XDECREF(tmp1);
Py_XDECREF(one);
return NULL;
@@ -937,6 +930,13 @@ rangeiter_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
long start, stop, step;
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "range_iterator(): creating instances of range_iterator "
+ "by calling range_iterator type is deprecated",
+ 1)) {
+ return NULL;
+ }
+
if (!_PyArg_NoKeywords("range_iterator()", kw)) {
return NULL;
}
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 4ef692db33..fdb9d3600d 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -26,7 +26,6 @@
#include "Python.h"
#include "structmember.h"
-#include "stringlib/eq.h"
/* Object used as dummy key to fill deleted entries */
static PyObject _dummy_struct;
@@ -48,19 +47,20 @@ static PyObject _dummy_struct;
static setentry *
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
{
- setentry *table = so->table;
- setentry *freeslot = NULL;
+ setentry *table;
setentry *entry;
- size_t perturb = hash;
+ size_t perturb;
size_t mask = so->mask;
size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
size_t j;
int cmp;
- entry = &table[i];
+ entry = &so->table[i];
if (entry->key == NULL)
return entry;
+ perturb = hash;
+
while (1) {
if (entry->hash == hash) {
PyObject *startkey = entry->key;
@@ -70,8 +70,9 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
return entry;
if (PyUnicode_CheckExact(startkey)
&& PyUnicode_CheckExact(key)
- && unicode_eq(startkey, key))
+ && _PyUnicode_EQ(startkey, key))
return entry;
+ table = so->table;
Py_INCREF(startkey);
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
Py_DECREF(startkey);
@@ -83,14 +84,12 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
return entry;
mask = so->mask; /* help avoid a register spill */
}
- if (entry->hash == -1 && freeslot == NULL)
- freeslot = entry;
if (i + LINEAR_PROBES <= mask) {
for (j = 0 ; j < LINEAR_PROBES ; j++) {
entry++;
- if (entry->key == NULL)
- goto found_null;
+ if (entry->hash == 0 && entry->key == NULL)
+ return entry;
if (entry->hash == hash) {
PyObject *startkey = entry->key;
assert(startkey != dummy);
@@ -98,8 +97,9 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
return entry;
if (PyUnicode_CheckExact(startkey)
&& PyUnicode_CheckExact(key)
- && unicode_eq(startkey, key))
+ && _PyUnicode_EQ(startkey, key))
return entry;
+ table = so->table;
Py_INCREF(startkey);
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
Py_DECREF(startkey);
@@ -111,7 +111,104 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
return entry;
mask = so->mask;
}
- if (entry->hash == -1 && freeslot == NULL)
+ }
+ }
+
+ perturb >>= PERTURB_SHIFT;
+ i = (i * 5 + 1 + perturb) & mask;
+
+ entry = &so->table[i];
+ if (entry->key == NULL)
+ return entry;
+ }
+}
+
+static int set_table_resize(PySetObject *, Py_ssize_t);
+
+static int
+set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
+{
+ setentry *table;
+ setentry *freeslot;
+ setentry *entry;
+ size_t perturb;
+ size_t mask;
+ size_t i; /* Unsigned for defined overflow behavior */
+ size_t j;
+ int cmp;
+
+ /* Pre-increment is necessary to prevent arbitrary code in the rich
+ comparison from deallocating the key just before the insertion. */
+ Py_INCREF(key);
+
+ restart:
+
+ mask = so->mask;
+ i = (size_t)hash & mask;
+
+ entry = &so->table[i];
+ if (entry->key == NULL)
+ goto found_unused;
+
+ freeslot = NULL;
+ perturb = hash;
+
+ while (1) {
+ if (entry->hash == hash) {
+ PyObject *startkey = entry->key;
+ /* startkey cannot be a dummy because the dummy hash field is -1 */
+ assert(startkey != dummy);
+ if (startkey == key)
+ goto found_active;
+ if (PyUnicode_CheckExact(startkey)
+ && PyUnicode_CheckExact(key)
+ && _PyUnicode_EQ(startkey, key))
+ goto found_active;
+ table = so->table;
+ Py_INCREF(startkey);
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
+ Py_DECREF(startkey);
+ if (cmp > 0) /* likely */
+ goto found_active;
+ if (cmp < 0)
+ goto comparison_error;
+ /* Continuing the search from the current entry only makes
+ sense if the table and entry are unchanged; otherwise,
+ we have to restart from the beginning */
+ if (table != so->table || entry->key != startkey)
+ goto restart;
+ mask = so->mask; /* help avoid a register spill */
+ }
+ else if (entry->hash == -1 && freeslot == NULL)
+ freeslot = entry;
+
+ if (i + LINEAR_PROBES <= mask) {
+ for (j = 0 ; j < LINEAR_PROBES ; j++) {
+ entry++;
+ if (entry->hash == 0 && entry->key == NULL)
+ goto found_unused_or_dummy;
+ if (entry->hash == hash) {
+ PyObject *startkey = entry->key;
+ assert(startkey != dummy);
+ if (startkey == key)
+ goto found_active;
+ if (PyUnicode_CheckExact(startkey)
+ && PyUnicode_CheckExact(key)
+ && _PyUnicode_EQ(startkey, key))
+ goto found_active;
+ table = so->table;
+ Py_INCREF(startkey);
+ cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
+ Py_DECREF(startkey);
+ if (cmp > 0)
+ goto found_active;
+ if (cmp < 0)
+ goto comparison_error;
+ if (table != so->table || entry->key != startkey)
+ goto restart;
+ mask = so->mask;
+ }
+ else if (entry->hash == -1 && freeslot == NULL)
freeslot = entry;
}
}
@@ -119,29 +216,51 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
perturb >>= PERTURB_SHIFT;
i = (i * 5 + 1 + perturb) & mask;
- entry = &table[i];
+ entry = &so->table[i];
if (entry->key == NULL)
- goto found_null;
+ goto found_unused_or_dummy;
}
- found_null:
- return freeslot == NULL ? entry : freeslot;
+
+ found_unused_or_dummy:
+ if (freeslot == NULL)
+ goto found_unused;
+ so->used++;
+ freeslot->key = key;
+ freeslot->hash = hash;
+ return 0;
+
+ found_unused:
+ so->fill++;
+ so->used++;
+ entry->key = key;
+ entry->hash = hash;
+ if ((size_t)so->fill*3 < mask*2)
+ return 0;
+ return set_table_resize(so, so->used);
+
+ found_active:
+ Py_DECREF(key);
+ return 0;
+
+ comparison_error:
+ Py_DECREF(key);
+ return -1;
}
/*
Internal routine used by set_table_resize() to insert an item which is
known to be absent from the set. This routine also assumes that
the set contains no deleted entries. Besides the performance benefit,
-using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209).
-Note that no refcounts are changed by this routine; if needed, the caller
-is responsible for incref'ing `key`.
+there is also safety benefit since using set_add_entry() risks making
+a callback in the middle of a set_table_resize(), see issue 1456209.
+The caller is responsible for updating the key's reference count and
+the setobject's fill and used fields.
*/
static void
-set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)
+set_insert_clean(setentry *table, size_t mask, PyObject *key, Py_hash_t hash)
{
- setentry *table = so->table;
setentry *entry;
size_t perturb = hash;
- size_t mask = (size_t)so->mask;
size_t i = (size_t)hash & mask;
size_t j;
@@ -162,45 +281,11 @@ set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)
found_null:
entry->key = key;
entry->hash = hash;
- so->fill++;
- so->used++;
}
/* ======== End logic for probing the hash table ========================== */
/* ======================================================================== */
-
-/*
-Internal routine to insert a new key into the table.
-Used by the public insert routine.
-Eats a reference to key.
-*/
-static int
-set_insert_key(PySetObject *so, PyObject *key, Py_hash_t hash)
-{
- setentry *entry;
-
- entry = set_lookkey(so, key, hash);
- if (entry == NULL)
- return -1;
- if (entry->key == NULL) {
- /* UNUSED */
- entry->key = key;
- entry->hash = hash;
- so->fill++;
- so->used++;
- } else if (entry->key == dummy) {
- /* DUMMY */
- entry->key = key;
- entry->hash = hash;
- so->used++;
- } else {
- /* ACTIVE */
- Py_DECREF(key);
- }
- return 0;
-}
-
/*
Restructure the table by allocating a new table and reinserting all
keys again. When entries have been deleted, the new table may
@@ -213,10 +298,13 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
setentry *oldtable, *newtable, *entry;
Py_ssize_t oldfill = so->fill;
Py_ssize_t oldused = so->used;
+ Py_ssize_t oldmask = so->mask;
+ size_t newmask;
int is_oldtable_malloced;
setentry small_copy[PySet_MINSIZE];
assert(minused >= 0);
+ minused = (minused > 50000) ? minused * 2 : minused * 4;
/* Find the smallest table size > minused. */
/* XXX speed-up with intrinsics */
@@ -264,25 +352,24 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
/* Make the set empty, using the new table. */
assert(newtable != oldtable);
memset(newtable, 0, sizeof(setentry) * newsize);
- so->fill = 0;
- so->used = 0;
+ so->fill = oldused;
+ so->used = oldused;
so->mask = newsize - 1;
so->table = newtable;
/* Copy the data over; this is refcount-neutral for active entries;
dummy entries aren't copied over, of course */
+ newmask = (size_t)so->mask;
if (oldfill == oldused) {
- for (entry = oldtable; oldused > 0; entry++) {
+ for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
if (entry->key != NULL) {
- oldused--;
- set_insert_clean(so, entry->key, entry->hash);
+ set_insert_clean(newtable, newmask, entry->key, entry->hash);
}
}
} else {
- for (entry = oldtable; oldused > 0; entry++) {
+ for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
if (entry->key != NULL && entry->key != dummy) {
- oldused--;
- set_insert_clean(so, entry->key, entry->hash);
+ set_insert_clean(newtable, newmask, entry->key, entry->hash);
}
}
}
@@ -292,31 +379,42 @@ set_table_resize(PySetObject *so, Py_ssize_t minused)
return 0;
}
-/* CAUTION: set_add_key/entry() must guarantee it won't resize the table */
+static int
+set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
+{
+ setentry *entry;
+
+ entry = set_lookkey(so, key, hash);
+ if (entry != NULL)
+ return entry->key != NULL;
+ return -1;
+}
+
+#define DISCARD_NOTFOUND 0
+#define DISCARD_FOUND 1
static int
-set_add_entry(PySetObject *so, setentry *entry)
+set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
{
- Py_ssize_t n_used;
- PyObject *key = entry->key;
- Py_hash_t hash = entry->hash;
+ setentry *entry;
+ PyObject *old_key;
- assert(so->fill <= so->mask); /* at least one empty slot */
- n_used = so->used;
- Py_INCREF(key);
- if (set_insert_key(so, key, hash)) {
- Py_DECREF(key);
+ entry = set_lookkey(so, key, hash);
+ if (entry == NULL)
return -1;
- }
- if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))
- return 0;
- return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
+ if (entry->key == NULL)
+ return DISCARD_NOTFOUND;
+ old_key = entry->key;
+ entry->key = dummy;
+ entry->hash = -1;
+ so->used--;
+ Py_DECREF(old_key);
+ return DISCARD_FOUND;
}
static int
set_add_key(PySetObject *so, PyObject *key)
{
- setentry entry;
Py_hash_t hash;
if (!PyUnicode_CheckExact(key) ||
@@ -325,50 +423,35 @@ set_add_key(PySetObject *so, PyObject *key)
if (hash == -1)
return -1;
}
- entry.key = key;
- entry.hash = hash;
- return set_add_entry(so, &entry);
+ return set_add_entry(so, key, hash);
}
-#define DISCARD_NOTFOUND 0
-#define DISCARD_FOUND 1
-
static int
-set_discard_entry(PySetObject *so, setentry *oldentry)
+set_contains_key(PySetObject *so, PyObject *key)
{
- setentry *entry;
- PyObject *old_key;
+ Py_hash_t hash;
- entry = set_lookkey(so, oldentry->key, oldentry->hash);
- if (entry == NULL)
- return -1;
- if (entry->key == NULL || entry->key == dummy)
- return DISCARD_NOTFOUND;
- old_key = entry->key;
- entry->key = dummy;
- entry->hash = -1;
- so->used--;
- Py_DECREF(old_key);
- return DISCARD_FOUND;
+ if (!PyUnicode_CheckExact(key) ||
+ (hash = ((PyASCIIObject *) key)->hash) == -1) {
+ hash = PyObject_Hash(key);
+ if (hash == -1)
+ return -1;
+ }
+ return set_contains_entry(so, key, hash);
}
static int
set_discard_key(PySetObject *so, PyObject *key)
{
- setentry entry;
Py_hash_t hash;
- assert (PyAnySet_Check(so));
-
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyASCIIObject *) key)->hash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return -1;
}
- entry.key = key;
- entry.hash = hash;
- return set_discard_entry(so, &entry);
+ return set_discard_entry(so, key, hash);
}
static void
@@ -449,20 +532,22 @@ set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
{
Py_ssize_t i;
Py_ssize_t mask;
- setentry *table;
+ setentry *entry;
assert (PyAnySet_Check(so));
i = *pos_ptr;
assert(i >= 0);
- table = so->table;
mask = so->mask;
- while (i <= mask && (table[i].key == NULL || table[i].key == dummy))
+ entry = &so->table[i];
+ while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
i++;
+ entry++;
+ }
*pos_ptr = i+1;
if (i > mask)
return 0;
- assert(table[i].key != NULL);
- *entry_ptr = &table[i];
+ assert(entry != NULL);
+ *entry_ptr = entry;
return 1;
}
@@ -560,8 +645,8 @@ set_merge(PySetObject *so, PyObject *otherset)
* incrementally resizing as we insert new keys. Expect
* that there will be no (or few) overlapping keys.
*/
- if ((so->fill + other->used)*3 >= (so->mask+1)*2) {
- if (set_table_resize(so, (so->used + other->used)*2) != 0)
+ if ((so->fill + other->used)*3 >= so->mask*2) {
+ if (set_table_resize(so, so->used + other->used) != 0)
return -1;
}
so_entry = so->table;
@@ -586,11 +671,15 @@ set_merge(PySetObject *so, PyObject *otherset)
/* If our table is empty, we can use set_insert_clean() */
if (so->fill == 0) {
- for (i = 0; i <= other->mask; i++, other_entry++) {
+ setentry *newtable = so->table;
+ size_t newmask = (size_t)so->mask;
+ so->fill = other->used;
+ so->used = other->used;
+ for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
key = other_entry->key;
if (key != NULL && key != dummy) {
Py_INCREF(key);
- set_insert_clean(so, key, other_entry->hash);
+ set_insert_clean(newtable, newmask, key, other_entry->hash);
}
}
return 0;
@@ -601,46 +690,13 @@ set_merge(PySetObject *so, PyObject *otherset)
other_entry = &other->table[i];
key = other_entry->key;
if (key != NULL && key != dummy) {
- Py_INCREF(key);
- if (set_insert_key(so, key, other_entry->hash)) {
- Py_DECREF(key);
+ if (set_add_entry(so, key, other_entry->hash))
return -1;
- }
}
}
return 0;
}
-static int
-set_contains_entry(PySetObject *so, setentry *entry)
-{
- PyObject *key;
- setentry *lu_entry;
-
- lu_entry = set_lookkey(so, entry->key, entry->hash);
- if (lu_entry == NULL)
- return -1;
- key = lu_entry->key;
- return key != NULL && key != dummy;
-}
-
-static int
-set_contains_key(PySetObject *so, PyObject *key)
-{
- setentry entry;
- Py_hash_t hash;
-
- if (!PyUnicode_CheckExact(key) ||
- (hash = ((PyASCIIObject *) key)->hash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- entry.key = key;
- entry.hash = hash;
- return set_contains_entry(so, &entry);
-}
-
static PyObject *
set_pop(PySetObject *so)
{
@@ -682,43 +738,64 @@ set_traverse(PySetObject *so, visitproc visit, void *arg)
return 0;
}
-static Py_hash_t
-frozenset_hash(PyObject *self)
+/* Work to increase the bit dispersion for closely spaced hash values.
+ This is important because some use cases have many combinations of a
+ small number of elements with nearby hashes so that many distinct
+ combinations collapse to only a handful of distinct hash values. */
+
+static Py_uhash_t
+_shuffle_bits(Py_uhash_t h)
{
- /* Most of the constants in this hash algorithm are randomly choosen
- large primes with "interesting bit patterns" and that passed
- tests for good collision statistics on a variety of problematic
- datasets such as:
+ return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
+}
- ps = []
- for r in range(21):
- ps += itertools.combinations(range(20), r)
- num_distinct_hashes = len({hash(frozenset(s)) for s in ps})
+/* Most of the constants in this hash algorithm are randomly chosen
+ large primes with "interesting bit patterns" and that passed tests
+ for good collision statistics on a variety of problematic datasets
+ including powersets and graph structures (such as David Eppstein's
+ graph recipes in Lib/test/test_set.py) */
- */
+static Py_hash_t
+frozenset_hash(PyObject *self)
+{
PySetObject *so = (PySetObject *)self;
- Py_uhash_t h, hash = 1927868237UL;
+ Py_uhash_t hash = 0;
setentry *entry;
- Py_ssize_t pos = 0;
if (so->hash != -1)
return so->hash;
- hash *= (Py_uhash_t)PySet_GET_SIZE(self) + 1;
- while (set_next(so, &pos, &entry)) {
- /* Work to increase the bit dispersion for closely spaced hash
- values. This is important because some use cases have many
- combinations of a small number of elements with nearby
- hashes so that many distinct combinations collapse to only
- a handful of distinct hash values. */
- h = entry->hash;
- hash ^= ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
- }
- /* Make the final result spread-out in a different pattern
- than the algorithm for tuples or other python objects. */
+ /* Xor-in shuffled bits from every entry's hash field because xor is
+ commutative and a frozenset hash should be independent of order.
+
+ For speed, include null entries and dummy entries and then
+ subtract out their effect afterwards so that the final hash
+ depends only on active entries. This allows the code to be
+ vectorized by the compiler and it saves the unpredictable
+ branches that would arise when trying to exclude null and dummy
+ entries on every iteration. */
+
+ for (entry = so->table; entry <= &so->table[so->mask]; entry++)
+ hash ^= _shuffle_bits(entry->hash);
+
+ /* Remove the effect of an odd number of NULL entries */
+ if ((so->mask + 1 - so->fill) & 1)
+ hash ^= _shuffle_bits(0);
+
+ /* Remove the effect of an odd number of dummy entries */
+ if ((so->fill - so->used) & 1)
+ hash ^= _shuffle_bits(-1);
+
+ /* Factor in the number of active entries */
+ hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
+
+ /* Disperse patterns arising in nested frozensets */
hash = hash * 69069U + 907133923UL;
+
+ /* -1 is reserved as an error code */
if (hash == (Py_uhash_t)-1)
hash = 590923713UL;
+
so->hash = hash;
return hash;
}
@@ -865,7 +942,7 @@ PyTypeObject PySetIter_Type = {
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)setiter_traverse, /* tp_traverse */
0, /* tp_clear */
@@ -910,18 +987,14 @@ set_update_internal(PySetObject *so, PyObject *other)
* incrementally resizing as we insert new keys. Expect
* that there will be no (or few) overlapping keys.
*/
- if (dictsize == -1)
+ if (dictsize < 0)
return -1;
- if ((so->fill + dictsize)*3 >= (so->mask+1)*2) {
- if (set_table_resize(so, (so->used + dictsize)*2) != 0)
+ if ((so->fill + dictsize)*3 >= so->mask*2) {
+ if (set_table_resize(so, so->used + dictsize) != 0)
return -1;
}
while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
- setentry an_entry;
-
- an_entry.hash = hash;
- an_entry.key = key;
- if (set_add_entry(so, &an_entry))
+ if (set_add_entry(so, key, hash))
return -1;
}
return 0;
@@ -970,9 +1043,8 @@ PyDoc_STRVAR(update_doc,
static PyObject *
make_new_set(PyTypeObject *type, PyObject *iterable)
{
- PySetObject *so = NULL;
+ PySetObject *so;
- /* create PySetObject structure */
so = (PySetObject *)type->tp_alloc(type, 0);
if (so == NULL)
return NULL;
@@ -1015,7 +1087,8 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *iterable = NULL, *result;
- if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset()", kwds))
+ if (kwds != NULL && type == &PyFrozenSet_Type
+ && !_PyArg_NoKeywords("frozenset()", kwds))
return NULL;
if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
@@ -1042,24 +1115,9 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return emptyfrozenset;
}
-int
-PySet_ClearFreeList(void)
-{
- return 0;
-}
-
-void
-PySet_Fini(void)
-{
- Py_CLEAR(emptyfrozenset);
-}
-
static PyObject *
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- if (type == &PySet_Type && !_PyArg_NoKeywords("set()", kwds))
- return NULL;
-
return make_new_set(type, NULL);
}
@@ -1201,6 +1259,8 @@ set_intersection(PySetObject *so, PyObject *other)
{
PySetObject *result;
PyObject *key, *it, *tmp;
+ Py_hash_t hash;
+ int rv;
if ((PyObject *)so == other)
return set_copy(so);
@@ -1220,13 +1280,15 @@ set_intersection(PySetObject *so, PyObject *other)
}
while (set_next((PySetObject *)other, &pos, &entry)) {
- int rv = set_contains_entry(so, entry);
- if (rv == -1) {
+ key = entry->key;
+ hash = entry->hash;
+ rv = set_contains_entry(so, key, hash);
+ if (rv < 0) {
Py_DECREF(result);
return NULL;
}
if (rv) {
- if (set_add_entry(result, entry)) {
+ if (set_add_entry(result, key, hash)) {
Py_DECREF(result);
return NULL;
}
@@ -1242,32 +1304,15 @@ set_intersection(PySetObject *so, PyObject *other)
}
while ((key = PyIter_Next(it)) != NULL) {
- int rv;
- setentry entry;
- Py_hash_t hash = PyObject_Hash(key);
-
- if (hash == -1) {
- Py_DECREF(it);
- Py_DECREF(result);
- Py_DECREF(key);
- return NULL;
- }
- entry.hash = hash;
- entry.key = key;
- rv = set_contains_entry(so, &entry);
- if (rv == -1) {
- Py_DECREF(it);
- Py_DECREF(result);
- Py_DECREF(key);
- return NULL;
- }
+ hash = PyObject_Hash(key);
+ if (hash == -1)
+ goto error;
+ rv = set_contains_entry(so, key, hash);
+ if (rv < 0)
+ goto error;
if (rv) {
- if (set_add_entry(result, &entry)) {
- Py_DECREF(it);
- Py_DECREF(result);
- Py_DECREF(key);
- return NULL;
- }
+ if (set_add_entry(result, key, hash))
+ goto error;
}
Py_DECREF(key);
}
@@ -1277,6 +1322,11 @@ set_intersection(PySetObject *so, PyObject *other)
return NULL;
}
return (PyObject *)result;
+ error:
+ Py_DECREF(it);
+ Py_DECREF(result);
+ Py_DECREF(key);
+ return NULL;
}
static PyObject *
@@ -1363,6 +1413,7 @@ static PyObject *
set_isdisjoint(PySetObject *so, PyObject *other)
{
PyObject *key, *it, *tmp;
+ int rv;
if ((PyObject *)so == other) {
if (PySet_GET_SIZE(so) == 0)
@@ -1381,8 +1432,8 @@ set_isdisjoint(PySetObject *so, PyObject *other)
other = tmp;
}
while (set_next((PySetObject *)other, &pos, &entry)) {
- int rv = set_contains_entry(so, entry);
- if (rv == -1)
+ rv = set_contains_entry(so, entry->key, entry->hash);
+ if (rv < 0)
return NULL;
if (rv)
Py_RETURN_FALSE;
@@ -1395,8 +1446,6 @@ set_isdisjoint(PySetObject *so, PyObject *other)
return NULL;
while ((key = PyIter_Next(it)) != NULL) {
- int rv;
- setentry entry;
Py_hash_t hash = PyObject_Hash(key);
if (hash == -1) {
@@ -1404,11 +1453,9 @@ set_isdisjoint(PySetObject *so, PyObject *other)
Py_DECREF(it);
return NULL;
}
- entry.hash = hash;
- entry.key = key;
- rv = set_contains_entry(so, &entry);
+ rv = set_contains_entry(so, key, hash);
Py_DECREF(key);
- if (rv == -1) {
+ if (rv < 0) {
Py_DECREF(it);
return NULL;
}
@@ -1429,6 +1476,10 @@ PyDoc_STRVAR(isdisjoint_doc,
static int
set_difference_update_internal(PySetObject *so, PyObject *other)
{
+ if (PySet_GET_SIZE(so) == 0) {
+ return 0;
+ }
+
if ((PyObject *)so == other)
return set_clear_internal(so);
@@ -1437,7 +1488,7 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
Py_ssize_t pos = 0;
while (set_next((PySetObject *)other, &pos, &entry))
- if (set_discard_entry(so, entry) == -1)
+ if (set_discard_entry(so, entry->key, entry->hash) < 0)
return -1;
} else {
PyObject *key, *it;
@@ -1446,7 +1497,7 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
return -1;
while ((key = PyIter_Next(it)) != NULL) {
- if (set_discard_key(so, key) == -1) {
+ if (set_discard_key(so, key) < 0) {
Py_DECREF(it);
Py_DECREF(key);
return -1;
@@ -1457,10 +1508,10 @@ set_difference_update_internal(PySetObject *so, PyObject *other)
if (PyErr_Occurred())
return -1;
}
- /* If more than 1/5 are dummies, then resize them away. */
- if ((so->fill - so->used) * 5 < so->mask)
+ /* If more than 1/4th are dummies, then resize them away. */
+ if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
return 0;
- return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
+ return set_table_resize(so, so->used);
}
static PyObject *
@@ -1487,7 +1538,7 @@ set_copy_and_difference(PySetObject *so, PyObject *other)
result = set_copy(so);
if (result == NULL)
return NULL;
- if (set_difference_update_internal((PySetObject *) result, other) != -1)
+ if (set_difference_update_internal((PySetObject *) result, other) == 0)
return result;
Py_DECREF(result);
return NULL;
@@ -1497,8 +1548,15 @@ static PyObject *
set_difference(PySetObject *so, PyObject *other)
{
PyObject *result;
+ PyObject *key;
+ Py_hash_t hash;
setentry *entry;
Py_ssize_t pos = 0;
+ int rv;
+
+ if (PySet_GET_SIZE(so) == 0) {
+ return set_copy(so);
+ }
if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) {
return set_copy_and_difference(so, other);
@@ -1516,17 +1574,15 @@ set_difference(PySetObject *so, PyObject *other)
if (PyDict_CheckExact(other)) {
while (set_next(so, &pos, &entry)) {
- setentry entrycopy;
- int rv;
- entrycopy.hash = entry->hash;
- entrycopy.key = entry->key;
- rv = _PyDict_Contains(other, entry->key, entry->hash);
+ key = entry->key;
+ hash = entry->hash;
+ rv = _PyDict_Contains(other, key, hash);
if (rv < 0) {
Py_DECREF(result);
return NULL;
}
if (!rv) {
- if (set_add_entry((PySetObject *)result, &entrycopy)) {
+ if (set_add_entry((PySetObject *)result, key, hash)) {
Py_DECREF(result);
return NULL;
}
@@ -1537,13 +1593,15 @@ set_difference(PySetObject *so, PyObject *other)
/* Iterate over so, checking for common elements in other. */
while (set_next(so, &pos, &entry)) {
- int rv = set_contains_entry((PySetObject *)other, entry);
- if (rv == -1) {
+ key = entry->key;
+ hash = entry->hash;
+ rv = set_contains_entry((PySetObject *)other, key, hash);
+ if (rv < 0) {
Py_DECREF(result);
return NULL;
}
if (!rv) {
- if (set_add_entry((PySetObject *)result, entry)) {
+ if (set_add_entry((PySetObject *)result, key, hash)) {
Py_DECREF(result);
return NULL;
}
@@ -1605,29 +1663,24 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other)
PySetObject *otherset;
PyObject *key;
Py_ssize_t pos = 0;
+ Py_hash_t hash;
setentry *entry;
+ int rv;
if ((PyObject *)so == other)
return set_clear(so);
if (PyDict_CheckExact(other)) {
PyObject *value;
- int rv;
- Py_hash_t hash;
while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
- setentry an_entry;
-
Py_INCREF(key);
- an_entry.hash = hash;
- an_entry.key = key;
-
- rv = set_discard_entry(so, &an_entry);
- if (rv == -1) {
+ rv = set_discard_entry(so, key, hash);
+ if (rv < 0) {
Py_DECREF(key);
return NULL;
}
if (rv == DISCARD_NOTFOUND) {
- if (set_add_entry(so, &an_entry)) {
+ if (set_add_entry(so, key, hash)) {
Py_DECREF(key);
return NULL;
}
@@ -1647,13 +1700,15 @@ set_symmetric_difference_update(PySetObject *so, PyObject *other)
}
while (set_next(otherset, &pos, &entry)) {
- int rv = set_discard_entry(so, entry);
- if (rv == -1) {
+ key = entry->key;
+ hash = entry->hash;
+ rv = set_discard_entry(so, key, hash);
+ if (rv < 0) {
Py_DECREF(otherset);
return NULL;
}
if (rv == DISCARD_NOTFOUND) {
- if (set_add_entry(so, entry)) {
+ if (set_add_entry(so, key, hash)) {
Py_DECREF(otherset);
return NULL;
}
@@ -1715,6 +1770,7 @@ set_issubset(PySetObject *so, PyObject *other)
{
setentry *entry;
Py_ssize_t pos = 0;
+ int rv;
if (!PyAnySet_Check(other)) {
PyObject *tmp, *result;
@@ -1729,8 +1785,8 @@ set_issubset(PySetObject *so, PyObject *other)
Py_RETURN_FALSE;
while (set_next(so, &pos, &entry)) {
- int rv = set_contains_entry((PySetObject *)other, entry);
- if (rv == -1)
+ rv = set_contains_entry((PySetObject *)other, entry->key, entry->hash);
+ if (rv < 0)
return NULL;
if (!rv)
Py_RETURN_FALSE;
@@ -1821,7 +1877,7 @@ set_contains(PySetObject *so, PyObject *key)
int rv;
rv = set_contains_key(so, key);
- if (rv == -1) {
+ if (rv < 0) {
if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
return -1;
PyErr_Clear();
@@ -1840,7 +1896,7 @@ set_direct_contains(PySetObject *so, PyObject *key)
long result;
result = set_contains(so, key);
- if (result == -1)
+ if (result < 0)
return NULL;
return PyBool_FromLong(result);
}
@@ -1854,7 +1910,7 @@ set_remove(PySetObject *so, PyObject *key)
int rv;
rv = set_discard_key(so, key);
- if (rv == -1) {
+ if (rv < 0) {
if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
return NULL;
PyErr_Clear();
@@ -1863,7 +1919,7 @@ set_remove(PySetObject *so, PyObject *key)
return NULL;
rv = set_discard_key(so, tmpkey);
Py_DECREF(tmpkey);
- if (rv == -1)
+ if (rv < 0)
return NULL;
}
@@ -1886,7 +1942,7 @@ set_discard(PySetObject *so, PyObject *key)
int rv;
rv = set_discard_key(so, key);
- if (rv == -1) {
+ if (rv < 0) {
if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
return NULL;
PyErr_Clear();
@@ -1895,7 +1951,7 @@ set_discard(PySetObject *so, PyObject *key)
return NULL;
rv = set_discard_key(so, tmpkey);
Py_DECREF(tmpkey);
- if (rv == -1)
+ if (rv < 0)
return NULL;
}
Py_RETURN_NONE;
@@ -1949,13 +2005,12 @@ set_init(PySetObject *self, PyObject *args, PyObject *kwds)
{
PyObject *iterable = NULL;
- if (!PyAnySet_Check(self))
- return -1;
- if (PySet_Check(self) && !_PyArg_NoKeywords("set()", kwds))
+ if (kwds != NULL && !_PyArg_NoKeywords("set()", kwds))
return -1;
if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
return -1;
- set_clear_internal(self);
+ if (self->fill)
+ set_clear_internal(self);
self->hash = -1;
if (iterable == NULL)
return 0;
@@ -2122,7 +2177,7 @@ static PyMethodDef frozenset_methods[] = {
copy_doc},
{"difference", (PyCFunction)set_difference_multi, METH_VARARGS,
difference_doc},
- {"intersection",(PyCFunction)set_intersection_multi, METH_VARARGS,
+ {"intersection", (PyCFunction)set_intersection_multi, METH_VARARGS,
intersection_doc},
{"isdisjoint", (PyCFunction)set_isdisjoint, METH_O,
isdisjoint_doc},
@@ -2193,7 +2248,7 @@ PyTypeObject PyFrozenSet_Type = {
(traverseproc)set_traverse, /* tp_traverse */
(inquiry)set_clear_internal, /* tp_clear */
(richcmpfunc)set_richcompare, /* tp_richcompare */
- offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
+ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
(getiterfunc)set_iter, /* tp_iter */
0, /* tp_iternext */
frozenset_methods, /* tp_methods */
@@ -2277,6 +2332,18 @@ PySet_Add(PyObject *anyset, PyObject *key)
}
int
+PySet_ClearFreeList(void)
+{
+ return 0;
+}
+
+void
+PySet_Fini(void)
+{
+ Py_CLEAR(emptyfrozenset);
+}
+
+int
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
{
setentry *entry;
@@ -2399,7 +2466,7 @@ test_c_api(PySetObject *so)
/* Exercise direct iteration */
i = 0, count = 0;
while (_PySet_NextEntry((PyObject *)dup, &i, &x, &hash)) {
- s = _PyUnicode_AsString(x);
+ s = PyUnicode_AsUTF8(x);
assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c'));
count++;
}
diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h
index 0fc6b582d2..43f2f3266f 100644
--- a/Objects/stringlib/codecs.h
+++ b/Objects/stringlib/codecs.h
@@ -1,6 +1,8 @@
/* stringlib: codec implementations */
-#if STRINGLIB_IS_UNICODE
+#if !STRINGLIB_IS_UNICODE
+# error "codecs.h is specific to Unicode"
+#endif
/* Mask to quickly check whether a C 'long' contains a
non-ASCII, UTF8-encoded char. */
@@ -260,53 +262,35 @@ STRINGLIB(utf8_encoder)(PyObject *unicode,
Py_ssize_t size,
const char *errors)
{
-#define MAX_SHORT_UNICHARS 300 /* largest size we'll do on the stack */
-
- Py_ssize_t i; /* index into s of next input byte */
- PyObject *result; /* result string object */
+ Py_ssize_t i; /* index into data of next input character */
char *p; /* next free byte in output buffer */
- Py_ssize_t nallocated; /* number of result bytes allocated */
- Py_ssize_t nneeded; /* number of result bytes needed */
#if STRINGLIB_SIZEOF_CHAR > 1
- PyObject *errorHandler = NULL;
+ PyObject *error_handler_obj = NULL;
PyObject *exc = NULL;
PyObject *rep = NULL;
+ _Py_error_handler error_handler = _Py_ERROR_UNKNOWN;
#endif
#if STRINGLIB_SIZEOF_CHAR == 1
const Py_ssize_t max_char_size = 2;
- char stackbuf[MAX_SHORT_UNICHARS * 2];
#elif STRINGLIB_SIZEOF_CHAR == 2
const Py_ssize_t max_char_size = 3;
- char stackbuf[MAX_SHORT_UNICHARS * 3];
#else /* STRINGLIB_SIZEOF_CHAR == 4 */
const Py_ssize_t max_char_size = 4;
- char stackbuf[MAX_SHORT_UNICHARS * 4];
#endif
+ _PyBytesWriter writer;
assert(size >= 0);
+ _PyBytesWriter_Init(&writer);
- if (size <= MAX_SHORT_UNICHARS) {
- /* Write into the stack buffer; nallocated can't overflow.
- * At the end, we'll allocate exactly as much heap space as it
- * turns out we need.
- */
- nallocated = Py_SAFE_DOWNCAST(sizeof(stackbuf), size_t, int);
- result = NULL; /* will allocate after we're done */
- p = stackbuf;
- }
- else {
- if (size > PY_SSIZE_T_MAX / max_char_size) {
- /* integer overflow */
- return PyErr_NoMemory();
- }
- /* Overallocate on the heap, and give the excess back at the end. */
- nallocated = size * max_char_size;
- result = PyBytes_FromStringAndSize(NULL, nallocated);
- if (result == NULL)
- return NULL;
- p = PyBytes_AS_STRING(result);
+ if (size > PY_SSIZE_T_MAX / max_char_size) {
+ /* integer overflow */
+ return PyErr_NoMemory();
}
+ p = _PyBytesWriter_Alloc(&writer, size * max_char_size);
+ if (p == NULL)
+ return NULL;
+
for (i = 0; i < size;) {
Py_UCS4 ch = data[i++];
@@ -326,72 +310,117 @@ STRINGLIB(utf8_encoder)(PyObject *unicode,
}
#if STRINGLIB_SIZEOF_CHAR > 1
else if (Py_UNICODE_IS_SURROGATE(ch)) {
- Py_ssize_t newpos;
- Py_ssize_t repsize, k, startpos;
+ Py_ssize_t startpos, endpos, newpos;
+ Py_ssize_t k;
+ if (error_handler == _Py_ERROR_UNKNOWN) {
+ error_handler = get_error_handler(errors);
+ }
+
startpos = i-1;
- rep = unicode_encode_call_errorhandler(
- errors, &errorHandler, "utf-8", "surrogates not allowed",
- unicode, &exc, startpos, startpos+1, &newpos);
- if (!rep)
- goto error;
-
- if (PyBytes_Check(rep))
- repsize = PyBytes_GET_SIZE(rep);
- else
- repsize = PyUnicode_GET_LENGTH(rep);
+ endpos = startpos+1;
+
+ while ((endpos < size) && Py_UNICODE_IS_SURROGATE(data[endpos]))
+ endpos++;
+
+ /* Only overallocate the buffer if it's not the last write */
+ writer.overallocate = (endpos < size);
+
+ switch (error_handler)
+ {
+ case _Py_ERROR_REPLACE:
+ memset(p, '?', endpos - startpos);
+ p += (endpos - startpos);
+ /* fall through the ignore handler */
+ case _Py_ERROR_IGNORE:
+ i += (endpos - startpos - 1);
+ break;
- if (repsize > max_char_size) {
- Py_ssize_t offset;
+ case _Py_ERROR_SURROGATEPASS:
+ for (k=startpos; k<endpos; k++) {
+ ch = data[k];
+ *p++ = (char)(0xe0 | (ch >> 12));
+ *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
+ *p++ = (char)(0x80 | (ch & 0x3f));
+ }
+ i += (endpos - startpos - 1);
+ break;
- if (result == NULL)
- offset = p - stackbuf;
- else
- offset = p - PyBytes_AS_STRING(result);
+ case _Py_ERROR_BACKSLASHREPLACE:
+ /* subtract preallocated bytes */
+ writer.min_size -= max_char_size * (endpos - startpos);
+ p = backslashreplace(&writer, p,
+ unicode, startpos, endpos);
+ if (p == NULL)
+ goto error;
+ i += (endpos - startpos - 1);
+ break;
- if (nallocated > PY_SSIZE_T_MAX - repsize + max_char_size) {
- /* integer overflow */
- PyErr_NoMemory();
+ case _Py_ERROR_XMLCHARREFREPLACE:
+ /* subtract preallocated bytes */
+ writer.min_size -= max_char_size * (endpos - startpos);
+ p = xmlcharrefreplace(&writer, p,
+ unicode, startpos, endpos);
+ if (p == NULL)
goto error;
+ i += (endpos - startpos - 1);
+ break;
+
+ case _Py_ERROR_SURROGATEESCAPE:
+ for (k=startpos; k<endpos; k++) {
+ ch = data[k];
+ if (!(0xDC80 <= ch && ch <= 0xDCFF))
+ break;
+ *p++ = (char)(ch & 0xff);
}
- nallocated += repsize - max_char_size;
- if (result != NULL) {
- if (_PyBytes_Resize(&result, nallocated) < 0)
- goto error;
- } else {
- result = PyBytes_FromStringAndSize(NULL, nallocated);
- if (result == NULL)
- goto error;
- Py_MEMCPY(PyBytes_AS_STRING(result), stackbuf, offset);
+ if (k >= endpos) {
+ i += (endpos - startpos - 1);
+ break;
}
- p = PyBytes_AS_STRING(result) + offset;
- }
+ startpos = k;
+ assert(startpos < endpos);
+ /* fall through the default handler */
+ default:
+ rep = unicode_encode_call_errorhandler(
+ errors, &error_handler_obj, "utf-8", "surrogates not allowed",
+ unicode, &exc, startpos, endpos, &newpos);
+ if (!rep)
+ goto error;
- if (PyBytes_Check(rep)) {
- char *prep = PyBytes_AS_STRING(rep);
- for(k = repsize; k > 0; k--)
- *p++ = *prep++;
- } else /* rep is unicode */ {
- enum PyUnicode_Kind repkind;
- void *repdata;
+ /* subtract preallocated bytes */
+ writer.min_size -= max_char_size * (newpos - startpos);
- if (PyUnicode_READY(rep) < 0)
- goto error;
- repkind = PyUnicode_KIND(rep);
- repdata = PyUnicode_DATA(rep);
-
- for(k=0; k<repsize; k++) {
- Py_UCS4 c = PyUnicode_READ(repkind, repdata, k);
- if (0x80 <= c) {
- raise_encode_exception(&exc, "utf-8",
- unicode,
- i-1, i,
+ if (PyBytes_Check(rep)) {
+ p = _PyBytesWriter_WriteBytes(&writer, p,
+ PyBytes_AS_STRING(rep),
+ PyBytes_GET_SIZE(rep));
+ }
+ else {
+ /* rep is unicode */
+ if (PyUnicode_READY(rep) < 0)
+ goto error;
+
+ if (!PyUnicode_IS_ASCII(rep)) {
+ raise_encode_exception(&exc, "utf-8", unicode,
+ startpos, endpos,
"surrogates not allowed");
goto error;
}
- *p++ = (char)c;
+
+ p = _PyBytesWriter_WriteBytes(&writer, p,
+ PyUnicode_DATA(rep),
+ PyUnicode_GET_LENGTH(rep));
}
+
+ if (p == NULL)
+ goto error;
+ Py_CLEAR(rep);
+
+ i = newpos;
}
- Py_CLEAR(rep);
+
+ /* If overallocation was disabled, ensure that it was the last
+ write. Otherwise, we missed an optimization */
+ assert(writer.overallocate || i == size);
}
else
#if STRINGLIB_SIZEOF_CHAR > 2
@@ -416,35 +445,20 @@ STRINGLIB(utf8_encoder)(PyObject *unicode,
#endif /* STRINGLIB_SIZEOF_CHAR > 1 */
}
- if (result == NULL) {
- /* This was stack allocated. */
- nneeded = p - stackbuf;
- assert(nneeded <= nallocated);
- result = PyBytes_FromStringAndSize(stackbuf, nneeded);
- }
- else {
- /* Cut back to size actually needed. */
- nneeded = p - PyBytes_AS_STRING(result);
- assert(nneeded <= nallocated);
- _PyBytes_Resize(&result, nneeded);
- }
-
#if STRINGLIB_SIZEOF_CHAR > 1
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
#endif
- return result;
+ return _PyBytesWriter_Finish(&writer, p);
#if STRINGLIB_SIZEOF_CHAR > 1
error:
Py_XDECREF(rep);
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
- Py_XDECREF(result);
+ _PyBytesWriter_Dealloc(&writer);
return NULL;
#endif
-
-#undef MAX_SHORT_UNICHARS
}
/* The pattern for constructing UCS2-repeated masks. */
@@ -806,5 +820,3 @@ STRINGLIB(utf32_encode)(const STRINGLIB_CHAR *in,
#undef SWAB4
#endif
-
-#endif /* STRINGLIB_IS_UNICODE */
diff --git a/Objects/stringlib/ctype.h b/Objects/stringlib/ctype.h
index 739cf3d9eb..f0546256ed 100644
--- a/Objects/stringlib/ctype.h
+++ b/Objects/stringlib/ctype.h
@@ -1,5 +1,6 @@
-/* NOTE: this API is -ONLY- for use with single byte character strings. */
-/* Do not use it with Unicode. */
+#if STRINGLIB_IS_UNICODE
+# error "ctype.h only compatible with byte-wise strings"
+#endif
#include "bytes_methods.h"
diff --git a/Objects/stringlib/fastsearch.h b/Objects/stringlib/fastsearch.h
index cda68e77c8..98165ad114 100644
--- a/Objects/stringlib/fastsearch.h
+++ b/Objects/stringlib/fastsearch.h
@@ -32,52 +32,98 @@
#define STRINGLIB_BLOOM(mask, ch) \
((mask & (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1)))))
-
Py_LOCAL_INLINE(Py_ssize_t)
-STRINGLIB(fastsearch_memchr_1char)(const STRINGLIB_CHAR* s, Py_ssize_t n,
- STRINGLIB_CHAR ch, unsigned char needle,
- int mode)
+STRINGLIB(find_char)(const STRINGLIB_CHAR* s, Py_ssize_t n, STRINGLIB_CHAR ch)
{
- if (mode == FAST_SEARCH) {
- const STRINGLIB_CHAR *ptr = s;
- const STRINGLIB_CHAR *e = s + n;
- while (ptr < e) {
- void *candidate = memchr((const void *) ptr, needle, (e - ptr) * sizeof(STRINGLIB_CHAR));
- if (candidate == NULL)
- return -1;
- ptr = (const STRINGLIB_CHAR *) _Py_ALIGN_DOWN(candidate, sizeof(STRINGLIB_CHAR));
- if (sizeof(STRINGLIB_CHAR) == 1 || *ptr == ch)
- return (ptr - s);
- /* False positive */
- ptr++;
- }
+ const STRINGLIB_CHAR *p, *e;
+
+ p = s;
+ e = s + n;
+ if (n > 10) {
+#if STRINGLIB_SIZEOF_CHAR == 1
+ p = memchr(s, ch, n);
+ if (p != NULL)
+ return (p - s);
return -1;
+#else
+ /* use memchr if we can choose a needle without two many likely
+ false positives */
+ unsigned char needle = ch & 0xff;
+ /* If looking for a multiple of 256, we'd have too
+ many false positives looking for the '\0' byte in UCS2
+ and UCS4 representations. */
+ if (needle != 0) {
+ while (p < e) {
+ void *candidate = memchr(p, needle,
+ (e - p) * sizeof(STRINGLIB_CHAR));
+ if (candidate == NULL)
+ return -1;
+ p = (const STRINGLIB_CHAR *)
+ _Py_ALIGN_DOWN(candidate, sizeof(STRINGLIB_CHAR));
+ if (*p == ch)
+ return (p - s);
+ /* False positive */
+ p++;
+ }
+ return -1;
+ }
+#endif
}
+ while (p < e) {
+ if (*p == ch)
+ return (p - s);
+ p++;
+ }
+ return -1;
+}
+
+Py_LOCAL_INLINE(Py_ssize_t)
+STRINGLIB(rfind_char)(const STRINGLIB_CHAR* s, Py_ssize_t n, STRINGLIB_CHAR ch)
+{
+ const STRINGLIB_CHAR *p;
#ifdef HAVE_MEMRCHR
/* memrchr() is a GNU extension, available since glibc 2.1.91.
it doesn't seem as optimized as memchr(), but is still quite
- faster than our hand-written loop in FASTSEARCH below */
- else if (mode == FAST_RSEARCH) {
- while (n > 0) {
- const STRINGLIB_CHAR *found;
- void *candidate = memrchr((const void *) s, needle, n * sizeof(STRINGLIB_CHAR));
- if (candidate == NULL)
- return -1;
- found = (const STRINGLIB_CHAR *) _Py_ALIGN_DOWN(candidate, sizeof(STRINGLIB_CHAR));
- n = found - s;
- if (sizeof(STRINGLIB_CHAR) == 1 || *found == ch)
- return n;
- /* False positive */
- }
+ faster than our hand-written loop below */
+
+ if (n > 10) {
+#if STRINGLIB_SIZEOF_CHAR == 1
+ p = memrchr(s, ch, n);
+ if (p != NULL)
+ return (p - s);
return -1;
- }
+#else
+ /* use memrchr if we can choose a needle without two many likely
+ false positives */
+ unsigned char needle = ch & 0xff;
+ /* If looking for a multiple of 256, we'd have too
+ many false positives looking for the '\0' byte in UCS2
+ and UCS4 representations. */
+ if (needle != 0) {
+ while (n > 0) {
+ void *candidate = memrchr(s, needle,
+ n * sizeof(STRINGLIB_CHAR));
+ if (candidate == NULL)
+ return -1;
+ p = (const STRINGLIB_CHAR *)
+ _Py_ALIGN_DOWN(candidate, sizeof(STRINGLIB_CHAR));
+ n = p - s;
+ if (*p == ch)
+ return n;
+ /* False positive */
+ }
+ return -1;
+ }
#endif
- else {
- assert(0); /* Should never get here */
- return 0;
}
-
-#undef DO_MEMCHR
+#endif /* HAVE_MEMRCHR */
+ p = s + n;
+ while (p > s) {
+ p--;
+ if (*p == ch)
+ return (p - s);
+ }
+ return -1;
}
Py_LOCAL_INLINE(Py_ssize_t)
@@ -99,25 +145,11 @@ FASTSEARCH(const STRINGLIB_CHAR* s, Py_ssize_t n,
if (m <= 0)
return -1;
/* use special case for 1-character strings */
- if (n > 10 && (mode == FAST_SEARCH
-#ifdef HAVE_MEMRCHR
- || mode == FAST_RSEARCH
-#endif
- )) {
- /* use memchr if we can choose a needle without two many likely
- false positives */
- unsigned char needle;
- needle = p[0] & 0xff;
-#if STRINGLIB_SIZEOF_CHAR > 1
- /* If looking for a multiple of 256, we'd have too
- many false positives looking for the '\0' byte in UCS2
- and UCS4 representations. */
- if (needle != 0)
-#endif
- return STRINGLIB(fastsearch_memchr_1char)
- (s, n, p[0], needle, mode);
- }
- if (mode == FAST_COUNT) {
+ if (mode == FAST_SEARCH)
+ return STRINGLIB(find_char)(s, n, p[0]);
+ else if (mode == FAST_RSEARCH)
+ return STRINGLIB(rfind_char)(s, n, p[0]);
+ else { /* FAST_COUNT */
for (i = 0; i < n; i++)
if (s[i] == p[0]) {
count++;
@@ -125,14 +157,6 @@ FASTSEARCH(const STRINGLIB_CHAR* s, Py_ssize_t n,
return maxcount;
}
return count;
- } else if (mode == FAST_SEARCH) {
- for (i = 0; i < n; i++)
- if (s[i] == p[0])
- return i;
- } else { /* FAST_RSEARCH */
- for (i = n - 1; i > -1; i--)
- if (s[i] == p[0])
- return i;
}
return -1;
}
diff --git a/Objects/stringlib/find.h b/Objects/stringlib/find.h
index 14815f6e62..509b929739 100644
--- a/Objects/stringlib/find.h
+++ b/Objects/stringlib/find.h
@@ -117,85 +117,3 @@ STRINGLIB(parse_args_finds)(const char * function_name, PyObject *args,
}
#undef FORMAT_BUFFER_SIZE
-
-#if STRINGLIB_IS_UNICODE
-
-/*
-Wraps stringlib_parse_args_finds() and additionally ensures that the
-first argument is a unicode object.
-
-Note that we receive a pointer to the pointer of the substring object,
-so when we create that object in this function we don't DECREF it,
-because it continues living in the caller functions (those functions,
-after finishing using the substring, must DECREF it).
-*/
-
-Py_LOCAL_INLINE(int)
-STRINGLIB(parse_args_finds_unicode)(const char * function_name, PyObject *args,
- PyObject **substring,
- Py_ssize_t *start, Py_ssize_t *end)
-{
- PyObject *tmp_substring;
-
- if(STRINGLIB(parse_args_finds)(function_name, args, &tmp_substring,
- start, end)) {
- tmp_substring = PyUnicode_FromObject(tmp_substring);
- if (!tmp_substring)
- return 0;
- *substring = tmp_substring;
- return 1;
- }
- return 0;
-}
-
-#else /* !STRINGLIB_IS_UNICODE */
-
-/*
-Wraps stringlib_parse_args_finds() and additionally checks whether the
-first argument is an integer in range(0, 256).
-
-If this is the case, writes the integer value to the byte parameter
-and sets subobj to NULL. Otherwise, sets the first argument to subobj
-and doesn't touch byte. The other parameters are similar to those of
-stringlib_parse_args_finds().
-*/
-
-Py_LOCAL_INLINE(int)
-STRINGLIB(parse_args_finds_byte)(const char *function_name, PyObject *args,
- PyObject **subobj, char *byte,
- Py_ssize_t *start, Py_ssize_t *end)
-{
- PyObject *tmp_subobj;
- Py_ssize_t ival;
- PyObject *err;
-
- if(!STRINGLIB(parse_args_finds)(function_name, args, &tmp_subobj,
- start, end))
- return 0;
-
- if (!PyNumber_Check(tmp_subobj)) {
- *subobj = tmp_subobj;
- return 1;
- }
-
- ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
- if (ival == -1) {
- err = PyErr_Occurred();
- if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
- PyErr_Clear();
- *subobj = tmp_subobj;
- return 1;
- }
- }
-
- if (ival < 0 || ival > 255) {
- PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
- return 0;
- }
-
- *subobj = NULL;
- *byte = (char)ival;
- return 1;
-}
-
-#endif /* STRINGLIB_IS_UNICODE */
diff --git a/Objects/stringlib/find_max_char.h b/Objects/stringlib/find_max_char.h
index eb3fe886e2..8ccbc30944 100644
--- a/Objects/stringlib/find_max_char.h
+++ b/Objects/stringlib/find_max_char.h
@@ -1,6 +1,8 @@
/* Finding the optimal width of unicode characters in a buffer */
-#if STRINGLIB_IS_UNICODE
+#if !STRINGLIB_IS_UNICODE
+# error "find_max_char.h is specific to Unicode"
+#endif
/* Mask to quickly check whether a C 'long' contains a
non-ASCII, UTF8-encoded char. */
@@ -129,5 +131,4 @@ STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end)
#undef MAX_CHAR_UCS4
#endif /* STRINGLIB_SIZEOF_CHAR == 1 */
-#endif /* STRINGLIB_IS_UNICODE */
diff --git a/Objects/stringlib/join.h b/Objects/stringlib/join.h
index cbf81be170..6f314e1524 100644
--- a/Objects/stringlib/join.h
+++ b/Objects/stringlib/join.h
@@ -1,6 +1,6 @@
/* stringlib: bytes joining implementation */
-#if STRINGLIB_SIZEOF_CHAR != 1
+#if STRINGLIB_IS_UNICODE
#error join.h only compatible with byte-wise strings
#endif
@@ -107,7 +107,7 @@ STRINGLIB(bytes_join)(PyObject *sep, PyObject *iterable)
for (i = 0; i < nbufs; i++) {
Py_ssize_t n = buffers[i].len;
char *q = buffers[i].buf;
- Py_MEMCPY(p, q, n);
+ memcpy(p, q, n);
p += n;
}
goto done;
@@ -116,12 +116,12 @@ STRINGLIB(bytes_join)(PyObject *sep, PyObject *iterable)
Py_ssize_t n;
char *q;
if (i) {
- Py_MEMCPY(p, sepstr, seplen);
+ memcpy(p, sepstr, seplen);
p += seplen;
}
n = buffers[i].len;
q = buffers[i].buf;
- Py_MEMCPY(p, q, n);
+ memcpy(p, q, n);
p += n;
}
goto done;
diff --git a/Objects/stringlib/localeutil.h b/Objects/stringlib/localeutil.h
index 6e2f07342c..df501ed05c 100644
--- a/Objects/stringlib/localeutil.h
+++ b/Objects/stringlib/localeutil.h
@@ -2,8 +2,8 @@
#include <locale.h>
-#ifndef STRINGLIB_IS_UNICODE
-# error "localeutil is specific to Unicode"
+#if !STRINGLIB_IS_UNICODE
+# error "localeutil.h is specific to Unicode"
#endif
typedef struct {
diff --git a/Objects/stringlib/transmogrify.h b/Objects/stringlib/transmogrify.h
index b559b5356b..a314572a72 100644
--- a/Objects/stringlib/transmogrify.h
+++ b/Objects/stringlib/transmogrify.h
@@ -1,14 +1,21 @@
-/* NOTE: this API is -ONLY- for use with single byte character strings. */
-/* Do not use it with Unicode. */
+#if STRINGLIB_IS_UNICODE
+# error "transmogrify.h only compatible with byte-wise strings"
+#endif
/* the more complicated methods. parts of these should be pulled out into the
shared code in bytes_methods.c to cut down on duplicate code bloat. */
-PyDoc_STRVAR(expandtabs__doc__,
-"B.expandtabs(tabsize=8) -> copy of B\n\
-\n\
-Return a copy of B where all tab characters are expanded using spaces.\n\
-If tabsize is not given, a tab size of 8 characters is assumed.");
+static inline PyObject *
+return_self(PyObject *self)
+{
+#if !STRINGLIB_MUTABLE
+ if (STRINGLIB_CHECK_EXACT(self)) {
+ Py_INCREF(self);
+ return self;
+ }
+#endif
+ return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
+}
static PyObject*
stringlib_expandtabs(PyObject *self, PyObject *args, PyObject *kwds)
@@ -83,7 +90,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
-Py_LOCAL_INLINE(PyObject *)
+static inline PyObject *
pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
{
PyObject *u;
@@ -93,39 +100,25 @@ pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
if (right < 0)
right = 0;
- if (left == 0 && right == 0 && STRINGLIB_CHECK_EXACT(self)) {
-#if STRINGLIB_MUTABLE
- /* We're defined as returning a copy; If the object is mutable
- * that means we must make an identical copy. */
- return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
-#else
- Py_INCREF(self);
- return (PyObject *)self;
-#endif /* STRINGLIB_MUTABLE */
+ if (left == 0 && right == 0) {
+ return return_self(self);
}
- u = STRINGLIB_NEW(NULL,
- left + STRINGLIB_LEN(self) + right);
+ u = STRINGLIB_NEW(NULL, left + STRINGLIB_LEN(self) + right);
if (u) {
if (left)
memset(STRINGLIB_STR(u), fill, left);
- Py_MEMCPY(STRINGLIB_STR(u) + left,
- STRINGLIB_STR(self),
- STRINGLIB_LEN(self));
+ memcpy(STRINGLIB_STR(u) + left,
+ STRINGLIB_STR(self),
+ STRINGLIB_LEN(self));
if (right)
memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
- fill, right);
+ fill, right);
}
return u;
}
-PyDoc_STRVAR(ljust__doc__,
-"B.ljust(width[, fillchar]) -> copy of B\n"
-"\n"
-"Return B left justified in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space).");
-
static PyObject *
stringlib_ljust(PyObject *self, PyObject *args)
{
@@ -135,27 +128,14 @@ stringlib_ljust(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
return NULL;
- if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
-#if STRINGLIB_MUTABLE
- /* We're defined as returning a copy; If the object is mutable
- * that means we must make an identical copy. */
- return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
-#else
- Py_INCREF(self);
- return (PyObject*) self;
-#endif
+ if (STRINGLIB_LEN(self) >= width) {
+ return return_self(self);
}
return pad(self, 0, width - STRINGLIB_LEN(self), fillchar);
}
-PyDoc_STRVAR(rjust__doc__,
-"B.rjust(width[, fillchar]) -> copy of B\n"
-"\n"
-"Return B right justified in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space)");
-
static PyObject *
stringlib_rjust(PyObject *self, PyObject *args)
{
@@ -165,27 +145,14 @@ stringlib_rjust(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))
return NULL;
- if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
-#if STRINGLIB_MUTABLE
- /* We're defined as returning a copy; If the object is mutable
- * that means we must make an identical copy. */
- return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
-#else
- Py_INCREF(self);
- return (PyObject*) self;
-#endif
+ if (STRINGLIB_LEN(self) >= width) {
+ return return_self(self);
}
return pad(self, width - STRINGLIB_LEN(self), 0, fillchar);
}
-PyDoc_STRVAR(center__doc__,
-"B.center(width[, fillchar]) -> copy of B\n"
-"\n"
-"Return B centered in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space).");
-
static PyObject *
stringlib_center(PyObject *self, PyObject *args)
{
@@ -196,15 +163,8 @@ stringlib_center(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))
return NULL;
- if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
-#if STRINGLIB_MUTABLE
- /* We're defined as returning a copy; If the object is mutable
- * that means we must make an identical copy. */
- return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
-#else
- Py_INCREF(self);
- return (PyObject*) self;
-#endif
+ if (STRINGLIB_LEN(self) >= width) {
+ return return_self(self);
}
marg = width - STRINGLIB_LEN(self);
@@ -213,12 +173,6 @@ stringlib_center(PyObject *self, PyObject *args)
return pad(self, left, marg - left, fillchar);
}
-PyDoc_STRVAR(zfill__doc__,
-"B.zfill(width) -> copy of B\n"
-"\n"
-"Pad a numeric string B with zeros on the left, to fill a field\n"
-"of the specified width. B is never truncated.");
-
static PyObject *
stringlib_zfill(PyObject *self, PyObject *args)
{
@@ -231,21 +185,7 @@ stringlib_zfill(PyObject *self, PyObject *args)
return NULL;
if (STRINGLIB_LEN(self) >= width) {
- if (STRINGLIB_CHECK_EXACT(self)) {
-#if STRINGLIB_MUTABLE
- /* We're defined as returning a copy; If the object is mutable
- * that means we must make an identical copy. */
- return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
-#else
- Py_INCREF(self);
- return (PyObject*) self;
-#endif
- }
- else
- return STRINGLIB_NEW(
- STRINGLIB_STR(self),
- STRINGLIB_LEN(self)
- );
+ return return_self(self);
}
fill = width - STRINGLIB_LEN(self);
@@ -262,5 +202,500 @@ stringlib_zfill(PyObject *self, PyObject *args)
p[fill] = '0';
}
- return (PyObject*) s;
+ return s;
+}
+
+
+/* find and count characters and substrings */
+
+#define findchar(target, target_len, c) \
+ ((char *)memchr((const void *)(target), c, target_len))
+
+
+static Py_ssize_t
+countchar(const char *target, Py_ssize_t target_len, char c,
+ Py_ssize_t maxcount)
+{
+ Py_ssize_t count = 0;
+ const char *start = target;
+ const char *end = target + target_len;
+
+ while ((start = findchar(start, end - start, c)) != NULL) {
+ count++;
+ if (count >= maxcount)
+ break;
+ start += 1;
+ }
+ return count;
+}
+
+
+/* Algorithms for different cases of string replacement */
+
+/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
+static PyObject *
+stringlib_replace_interleave(PyObject *self,
+ const char *to_s, Py_ssize_t to_len,
+ Py_ssize_t maxcount)
+{
+ const char *self_s;
+ char *result_s;
+ Py_ssize_t self_len, result_len;
+ Py_ssize_t count, i;
+ PyObject *result;
+
+ self_len = STRINGLIB_LEN(self);
+
+ /* 1 at the end plus 1 after every character;
+ count = min(maxcount, self_len + 1) */
+ if (maxcount <= self_len) {
+ count = maxcount;
+ }
+ else {
+ /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */
+ count = self_len + 1;
+ }
+
+ /* Check for overflow */
+ /* result_len = count * to_len + self_len; */
+ assert(count > 0);
+ if (to_len > (PY_SSIZE_T_MAX - self_len) / count) {
+ PyErr_SetString(PyExc_OverflowError,
+ "replace bytes are too long");
+ return NULL;
+ }
+ result_len = count * to_len + self_len;
+ result = STRINGLIB_NEW(NULL, result_len);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ self_s = STRINGLIB_STR(self);
+ result_s = STRINGLIB_STR(result);
+
+ if (to_len > 1) {
+ /* Lay the first one down (guaranteed this will occur) */
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ count -= 1;
+
+ for (i = 0; i < count; i++) {
+ *result_s++ = *self_s++;
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ }
+ }
+ else {
+ result_s[0] = to_s[0];
+ result_s += to_len;
+ count -= 1;
+ for (i = 0; i < count; i++) {
+ *result_s++ = *self_s++;
+ result_s[0] = to_s[0];
+ result_s += to_len;
+ }
+ }
+
+ /* Copy the rest of the original string */
+ memcpy(result_s, self_s, self_len - i);
+
+ return result;
+}
+
+/* Special case for deleting a single character */
+/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
+static PyObject *
+stringlib_replace_delete_single_character(PyObject *self,
+ char from_c, Py_ssize_t maxcount)
+{
+ const char *self_s, *start, *next, *end;
+ char *result_s;
+ Py_ssize_t self_len, result_len;
+ Py_ssize_t count;
+ PyObject *result;
+
+ self_len = STRINGLIB_LEN(self);
+ self_s = STRINGLIB_STR(self);
+
+ count = countchar(self_s, self_len, from_c, maxcount);
+ if (count == 0) {
+ return return_self(self);
+ }
+
+ result_len = self_len - count; /* from_len == 1 */
+ assert(result_len>=0);
+
+ result = STRINGLIB_NEW(NULL, result_len);
+ if (result == NULL) {
+ return NULL;
+ }
+ result_s = STRINGLIB_STR(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ next = findchar(start, end - start, from_c);
+ if (next == NULL)
+ break;
+ memcpy(result_s, start, next - start);
+ result_s += (next - start);
+ start = next + 1;
+ }
+ memcpy(result_s, start, end - start);
+
+ return result;
+}
+
+/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
+
+static PyObject *
+stringlib_replace_delete_substring(PyObject *self,
+ const char *from_s, Py_ssize_t from_len,
+ Py_ssize_t maxcount)
+{
+ const char *self_s, *start, *next, *end;
+ char *result_s;
+ Py_ssize_t self_len, result_len;
+ Py_ssize_t count, offset;
+ PyObject *result;
+
+ self_len = STRINGLIB_LEN(self);
+ self_s = STRINGLIB_STR(self);
+
+ count = stringlib_count(self_s, self_len,
+ from_s, from_len,
+ maxcount);
+
+ if (count == 0) {
+ /* no matches */
+ return return_self(self);
+ }
+
+ result_len = self_len - (count * from_len);
+ assert (result_len>=0);
+
+ result = STRINGLIB_NEW(NULL, result_len);
+ if (result == NULL) {
+ return NULL;
+ }
+ result_s = STRINGLIB_STR(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ offset = stringlib_find(start, end - start,
+ from_s, from_len,
+ 0);
+ if (offset == -1)
+ break;
+ next = start + offset;
+
+ memcpy(result_s, start, next - start);
+
+ result_s += (next - start);
+ start = next + from_len;
+ }
+ memcpy(result_s, start, end - start);
+ return result;
+}
+
+/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
+static PyObject *
+stringlib_replace_single_character_in_place(PyObject *self,
+ char from_c, char to_c,
+ Py_ssize_t maxcount)
+{
+ const char *self_s, *end;
+ char *result_s, *start, *next;
+ Py_ssize_t self_len;
+ PyObject *result;
+
+ /* The result string will be the same size */
+ self_s = STRINGLIB_STR(self);
+ self_len = STRINGLIB_LEN(self);
+
+ next = findchar(self_s, self_len, from_c);
+
+ if (next == NULL) {
+ /* No matches; return the original bytes */
+ return return_self(self);
+ }
+
+ /* Need to make a new bytes */
+ result = STRINGLIB_NEW(NULL, self_len);
+ if (result == NULL) {
+ return NULL;
+ }
+ result_s = STRINGLIB_STR(result);
+ memcpy(result_s, self_s, self_len);
+
+ /* change everything in-place, starting with this one */
+ start = result_s + (next - self_s);
+ *start = to_c;
+ start++;
+ end = result_s + self_len;
+
+ while (--maxcount > 0) {
+ next = findchar(start, end - start, from_c);
+ if (next == NULL)
+ break;
+ *next = to_c;
+ start = next + 1;
+ }
+
+ return result;
}
+
+/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
+static PyObject *
+stringlib_replace_substring_in_place(PyObject *self,
+ const char *from_s, Py_ssize_t from_len,
+ const char *to_s, Py_ssize_t to_len,
+ Py_ssize_t maxcount)
+{
+ const char *self_s, *end;
+ char *result_s, *start;
+ Py_ssize_t self_len, offset;
+ PyObject *result;
+
+ /* The result bytes will be the same size */
+
+ self_s = STRINGLIB_STR(self);
+ self_len = STRINGLIB_LEN(self);
+
+ offset = stringlib_find(self_s, self_len,
+ from_s, from_len,
+ 0);
+ if (offset == -1) {
+ /* No matches; return the original bytes */
+ return return_self(self);
+ }
+
+ /* Need to make a new bytes */
+ result = STRINGLIB_NEW(NULL, self_len);
+ if (result == NULL) {
+ return NULL;
+ }
+ result_s = STRINGLIB_STR(result);
+ memcpy(result_s, self_s, self_len);
+
+ /* change everything in-place, starting with this one */
+ start = result_s + offset;
+ memcpy(start, to_s, from_len);
+ start += from_len;
+ end = result_s + self_len;
+
+ while ( --maxcount > 0) {
+ offset = stringlib_find(start, end - start,
+ from_s, from_len,
+ 0);
+ if (offset == -1)
+ break;
+ memcpy(start + offset, to_s, from_len);
+ start += offset + from_len;
+ }
+
+ return result;
+}
+
+/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
+static PyObject *
+stringlib_replace_single_character(PyObject *self,
+ char from_c,
+ const char *to_s, Py_ssize_t to_len,
+ Py_ssize_t maxcount)
+{
+ const char *self_s, *start, *next, *end;
+ char *result_s;
+ Py_ssize_t self_len, result_len;
+ Py_ssize_t count;
+ PyObject *result;
+
+ self_s = STRINGLIB_STR(self);
+ self_len = STRINGLIB_LEN(self);
+
+ count = countchar(self_s, self_len, from_c, maxcount);
+ if (count == 0) {
+ /* no matches, return unchanged */
+ return return_self(self);
+ }
+
+ /* use the difference between current and new, hence the "-1" */
+ /* result_len = self_len + count * (to_len-1) */
+ assert(count > 0);
+ if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) {
+ PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
+ return NULL;
+ }
+ result_len = self_len + count * (to_len - 1);
+
+ result = STRINGLIB_NEW(NULL, result_len);
+ if (result == NULL) {
+ return NULL;
+ }
+ result_s = STRINGLIB_STR(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ next = findchar(start, end - start, from_c);
+ if (next == NULL)
+ break;
+
+ if (next == start) {
+ /* replace with the 'to' */
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start += 1;
+ } else {
+ /* copy the unchanged old then the 'to' */
+ memcpy(result_s, start, next - start);
+ result_s += (next - start);
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start = next + 1;
+ }
+ }
+ /* Copy the remainder of the remaining bytes */
+ memcpy(result_s, start, end - start);
+
+ return result;
+}
+
+/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
+static PyObject *
+stringlib_replace_substring(PyObject *self,
+ const char *from_s, Py_ssize_t from_len,
+ const char *to_s, Py_ssize_t to_len,
+ Py_ssize_t maxcount)
+{
+ const char *self_s, *start, *next, *end;
+ char *result_s;
+ Py_ssize_t self_len, result_len;
+ Py_ssize_t count, offset;
+ PyObject *result;
+
+ self_s = STRINGLIB_STR(self);
+ self_len = STRINGLIB_LEN(self);
+
+ count = stringlib_count(self_s, self_len,
+ from_s, from_len,
+ maxcount);
+
+ if (count == 0) {
+ /* no matches, return unchanged */
+ return return_self(self);
+ }
+
+ /* Check for overflow */
+ /* result_len = self_len + count * (to_len-from_len) */
+ assert(count > 0);
+ if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) {
+ PyErr_SetString(PyExc_OverflowError, "replace bytes is too long");
+ return NULL;
+ }
+ result_len = self_len + count * (to_len - from_len);
+
+ result = STRINGLIB_NEW(NULL, result_len);
+ if (result == NULL) {
+ return NULL;
+ }
+ result_s = STRINGLIB_STR(result);
+
+ start = self_s;
+ end = self_s + self_len;
+ while (count-- > 0) {
+ offset = stringlib_find(start, end - start,
+ from_s, from_len,
+ 0);
+ if (offset == -1)
+ break;
+ next = start + offset;
+ if (next == start) {
+ /* replace with the 'to' */
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start += from_len;
+ } else {
+ /* copy the unchanged old then the 'to' */
+ memcpy(result_s, start, next - start);
+ result_s += (next - start);
+ memcpy(result_s, to_s, to_len);
+ result_s += to_len;
+ start = next + from_len;
+ }
+ }
+ /* Copy the remainder of the remaining bytes */
+ memcpy(result_s, start, end - start);
+
+ return result;
+}
+
+
+static PyObject *
+stringlib_replace(PyObject *self,
+ const char *from_s, Py_ssize_t from_len,
+ const char *to_s, Py_ssize_t to_len,
+ Py_ssize_t maxcount)
+{
+ if (maxcount < 0) {
+ maxcount = PY_SSIZE_T_MAX;
+ } else if (maxcount == 0 || STRINGLIB_LEN(self) == 0) {
+ /* nothing to do; return the original bytes */
+ return return_self(self);
+ }
+
+ /* Handle zero-length special cases */
+ if (from_len == 0) {
+ if (to_len == 0) {
+ /* nothing to do; return the original bytes */
+ return return_self(self);
+ }
+ /* insert the 'to' bytes everywhere. */
+ /* >>> b"Python".replace(b"", b".") */
+ /* b'.P.y.t.h.o.n.' */
+ return stringlib_replace_interleave(self, to_s, to_len, maxcount);
+ }
+
+ /* Except for b"".replace(b"", b"A") == b"A" there is no way beyond this */
+ /* point for an empty self bytes to generate a non-empty bytes */
+ /* Special case so the remaining code always gets a non-empty bytes */
+ if (STRINGLIB_LEN(self) == 0) {
+ return return_self(self);
+ }
+
+ if (to_len == 0) {
+ /* delete all occurrences of 'from' bytes */
+ if (from_len == 1) {
+ return stringlib_replace_delete_single_character(
+ self, from_s[0], maxcount);
+ } else {
+ return stringlib_replace_delete_substring(
+ self, from_s, from_len, maxcount);
+ }
+ }
+
+ /* Handle special case where both bytes have the same length */
+
+ if (from_len == to_len) {
+ if (from_len == 1) {
+ return stringlib_replace_single_character_in_place(
+ self, from_s[0], to_s[0], maxcount);
+ } else {
+ return stringlib_replace_substring_in_place(
+ self, from_s, from_len, to_s, to_len, maxcount);
+ }
+ }
+
+ /* Otherwise use the more generic algorithms */
+ if (from_len == 1) {
+ return stringlib_replace_single_character(
+ self, from_s[0], to_s, to_len, maxcount);
+ } else {
+ /* len('from')>=2, len('to')>=1 */
+ return stringlib_replace_substring(
+ self, from_s, from_len, to_s, to_len, maxcount);
+ }
+}
+
+#undef findchar
diff --git a/Objects/stringlib/unicode_format.h b/Objects/stringlib/unicode_format.h
index be09b5f6fa..14fa28ea54 100644
--- a/Objects/stringlib/unicode_format.h
+++ b/Objects/stringlib/unicode_format.h
@@ -67,7 +67,7 @@ SubString_new_object(SubString *str)
return PyUnicode_Substring(str->str, str->start, str->end);
}
-/* return a new string. if str->str is NULL, return None */
+/* return a new string. if str->str is NULL, return a new empty string */
Py_LOCAL_INLINE(PyObject *)
SubString_new_object_or_empty(SubString *str)
{
diff --git a/Objects/structseq.c b/Objects/structseq.c
index 664344be6c..5489aef6d0 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -4,9 +4,9 @@
#include "Python.h"
#include "structmember.h"
-static char visible_length_key[] = "n_sequence_fields";
-static char real_length_key[] = "n_fields";
-static char unnamed_fields_key[] = "n_unnamed_fields";
+static const char visible_length_key[] = "n_sequence_fields";
+static const char real_length_key[] = "n_fields";
+static const char unnamed_fields_key[] = "n_unnamed_fields";
/* Fields with this name have only a field index, not a field name.
They are only allowed for indices < n_visible_fields. */
@@ -16,14 +16,14 @@ _Py_IDENTIFIER(n_fields);
_Py_IDENTIFIER(n_unnamed_fields);
#define VISIBLE_SIZE(op) Py_SIZE(op)
-#define VISIBLE_SIZE_TP(tp) PyLong_AsLong( \
+#define VISIBLE_SIZE_TP(tp) PyLong_AsSsize_t( \
_PyDict_GetItemId((tp)->tp_dict, &PyId_n_sequence_fields))
-#define REAL_SIZE_TP(tp) PyLong_AsLong( \
+#define REAL_SIZE_TP(tp) PyLong_AsSsize_t( \
_PyDict_GetItemId((tp)->tp_dict, &PyId_n_fields))
#define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
-#define UNNAMED_FIELDS_TP(tp) PyLong_AsLong( \
+#define UNNAMED_FIELDS_TP(tp) PyLong_AsSsize_t( \
_PyDict_GetItemId((tp)->tp_dict, &PyId_n_unnamed_fields))
#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
@@ -164,7 +164,8 @@ structseq_repr(PyStructSequence *obj)
#define TYPE_MAXSIZE 100
PyTypeObject *typ = Py_TYPE(obj);
- int i, removelast = 0;
+ Py_ssize_t i;
+ int removelast = 0;
Py_ssize_t len;
char buf[REPR_BUFFER_SIZE];
char *endofbuf, *pbuf = buf;
@@ -193,7 +194,7 @@ structseq_repr(PyStructSequence *obj)
repr = PyObject_Repr(val);
if (repr == NULL)
return NULL;
- crepr = _PyUnicode_AsString(repr);
+ crepr = PyUnicode_AsUTF8(repr);
if (crepr == NULL) {
Py_DECREF(repr);
return NULL;
@@ -236,8 +237,7 @@ structseq_reduce(PyStructSequence* self)
PyObject* tup = NULL;
PyObject* dict = NULL;
PyObject* result;
- Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
- int i;
+ Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields, i;
n_fields = REAL_SIZE(self);
n_visible_fields = VISIBLE_SIZE(self);
@@ -325,7 +325,7 @@ PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
{
PyObject *dict;
PyMemberDef* members;
- int n_members, n_unnamed_members, i, k;
+ Py_ssize_t n_members, n_unnamed_members, i, k;
PyObject *v;
#ifdef Py_TRACE_REFS
@@ -373,9 +373,9 @@ PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
Py_INCREF(type);
dict = type->tp_dict;
-#define SET_DICT_FROM_INT(key, value) \
+#define SET_DICT_FROM_SIZE(key, value) \
do { \
- v = PyLong_FromLong((long) value); \
+ v = PyLong_FromSsize_t(value); \
if (v == NULL) \
return -1; \
if (PyDict_SetItemString(dict, key, v) < 0) { \
@@ -385,9 +385,9 @@ PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc)
Py_DECREF(v); \
} while (0)
- SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
- SET_DICT_FROM_INT(real_length_key, n_members);
- SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);
+ SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
+ SET_DICT_FROM_SIZE(real_length_key, n_members);
+ SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
return 0;
}
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 7920fec2bd..c0ff499e72 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -36,6 +36,16 @@ static Py_ssize_t count_tracked = 0;
static void
show_track(void)
{
+ PyObject *xoptions, *value;
+ _Py_IDENTIFIER(showalloccount);
+
+ xoptions = PySys_GetXOptions();
+ if (xoptions == NULL)
+ return;
+ value = _PyDict_GetItemId(xoptions, &PyId_showalloccount);
+ if (value != Py_True)
+ return;
+
fprintf(stderr, "Tuples created: %" PY_FORMAT_SIZE_T "d\n",
count_tracked + count_untracked);
fprintf(stderr, "Tuples tracked by the GC: %" PY_FORMAT_SIZE_T
@@ -149,7 +159,6 @@ PyTuple_GetItem(PyObject *op, Py_ssize_t i)
int
PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
{
- PyObject *olditem;
PyObject **p;
if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
Py_XDECREF(newitem);
@@ -163,9 +172,7 @@ PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
return -1;
}
p = ((PyTupleObject *)op) -> ob_item + i;
- olditem = *p;
- *p = newitem;
- Py_XDECREF(olditem);
+ Py_XSETREF(*p, newitem);
return 0;
}
@@ -446,9 +453,9 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
return NULL;
}
#define b ((PyTupleObject *)bb)
- size = Py_SIZE(a) + Py_SIZE(b);
- if (size < 0)
+ if (Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b))
return PyErr_NoMemory();
+ size = Py_SIZE(a) + Py_SIZE(b);
np = (PyTupleObject *) PyTuple_New(size);
if (np == NULL) {
return NULL;
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 7b76e5cd4d..329261b037 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -53,10 +53,12 @@ _Py_IDENTIFIER(__doc__);
_Py_IDENTIFIER(__getattribute__);
_Py_IDENTIFIER(__getitem__);
_Py_IDENTIFIER(__hash__);
+_Py_IDENTIFIER(__init_subclass__);
_Py_IDENTIFIER(__len__);
_Py_IDENTIFIER(__module__);
_Py_IDENTIFIER(__name__);
_Py_IDENTIFIER(__new__);
+_Py_IDENTIFIER(__set_name__);
_Py_IDENTIFIER(__setitem__);
_Py_IDENTIFIER(builtins);
@@ -452,27 +454,30 @@ type_set_qualname(PyTypeObject *type, PyObject *value, void *context)
static PyObject *
type_module(PyTypeObject *type, void *context)
{
- char *s;
+ PyObject *mod;
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
- PyObject *mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__);
- if (!mod) {
+ mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__);
+ if (mod == NULL) {
PyErr_Format(PyExc_AttributeError, "__module__");
- return 0;
+ return NULL;
}
- Py_XINCREF(mod);
- return mod;
+ Py_INCREF(mod);
}
else {
- PyObject *name;
- s = strrchr(type->tp_name, '.');
- if (s != NULL)
- return PyUnicode_FromStringAndSize(
+ const char *s = strrchr(type->tp_name, '.');
+ if (s != NULL) {
+ mod = PyUnicode_FromStringAndSize(
type->tp_name, (Py_ssize_t)(s - type->tp_name));
- name = _PyUnicode_FromId(&PyId_builtins);
- Py_XINCREF(name);
- return name;
+ if (mod != NULL)
+ PyUnicode_InternInPlace(&mod);
+ }
+ else {
+ mod = _PyUnicode_FromId(&PyId_builtins);
+ Py_XINCREF(mod);
+ }
}
+ return mod;
}
static int
@@ -500,7 +505,7 @@ type_abstractmethods(PyTypeObject *type, void *context)
PyErr_SetObject(PyExc_AttributeError, message);
return NULL;
}
- Py_XINCREF(mod);
+ Py_INCREF(mod);
return mod;
}
@@ -547,8 +552,8 @@ type_get_bases(PyTypeObject *type, void *context)
static PyTypeObject *best_base(PyObject *);
static int mro_internal(PyTypeObject *, PyObject **);
-Py_LOCAL_INLINE(int) type_is_subtype_base_chain(PyTypeObject *, PyTypeObject *);
-static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, char *);
+static int type_is_subtype_base_chain(PyTypeObject *, PyTypeObject *);
+static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, const char *);
static int add_subclass(PyTypeObject*, PyTypeObject*);
static int add_all_subclasses(PyTypeObject *type, PyObject *bases);
static void remove_subclass(PyTypeObject *, PyTypeObject *);
@@ -888,25 +893,33 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
#endif
obj = type->tp_new(type, args, kwds);
- if (obj != NULL) {
- /* Ugly exception: when the call was type(something),
- don't call tp_init on the result. */
- if (type == &PyType_Type &&
- PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
- (kwds == NULL ||
- (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
- return obj;
- /* If the returned object is not an instance of type,
- it won't be initialized. */
- if (!PyType_IsSubtype(Py_TYPE(obj), type))
- return obj;
- type = Py_TYPE(obj);
- if (type->tp_init != NULL) {
- int res = type->tp_init(obj, args, kwds);
- if (res < 0) {
- Py_DECREF(obj);
- obj = NULL;
- }
+ obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
+ if (obj == NULL)
+ return NULL;
+
+ /* Ugly exception: when the call was type(something),
+ don't call tp_init on the result. */
+ if (type == &PyType_Type &&
+ PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
+ (kwds == NULL ||
+ (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
+ return obj;
+
+ /* If the returned object is not an instance of type,
+ it won't be initialized. */
+ if (!PyType_IsSubtype(Py_TYPE(obj), type))
+ return obj;
+
+ type = Py_TYPE(obj);
+ if (type->tp_init != NULL) {
+ int res = type->tp_init(obj, args, kwds);
+ if (res < 0) {
+ assert(PyErr_Occurred());
+ Py_DECREF(obj);
+ obj = NULL;
+ }
+ else {
+ assert(!PyErr_Occurred());
}
}
return obj;
@@ -1324,7 +1337,7 @@ static PyTypeObject *solid_base(PyTypeObject *type);
/* type test with subclassing support */
-Py_LOCAL_INLINE(int)
+static int
type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b)
{
do {
@@ -1412,36 +1425,38 @@ _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid)
as lookup_method to cache the interned name string object. */
static PyObject *
-call_method(PyObject *o, _Py_Identifier *nameid, char *format, ...)
+call_method(PyObject *o, _Py_Identifier *nameid, const char *format, ...)
{
va_list va;
- PyObject *args, *func = 0, *retval;
- va_start(va, format);
+ PyObject *func = NULL, *retval;
func = lookup_maybe(o, nameid);
if (func == NULL) {
- va_end(va);
if (!PyErr_Occurred())
PyErr_SetObject(PyExc_AttributeError, nameid->object);
return NULL;
}
- if (format && *format)
+ if (format && *format) {
+ PyObject *args;
+
+ va_start(va, format);
args = Py_VaBuildValue(format, va);
- else
- args = PyTuple_New(0);
+ va_end(va);
- va_end(va);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return NULL;
+ }
+ assert(PyTuple_Check(args));
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
+ retval = PyObject_Call(func, args, NULL);
+ Py_DECREF(args);
+ }
+ else {
+ retval = _PyObject_CallNoArg(func);
}
- assert(PyTuple_Check(args));
- retval = PyObject_Call(func, args, NULL);
-
- Py_DECREF(args);
Py_DECREF(func);
return retval;
@@ -1450,36 +1465,38 @@ call_method(PyObject *o, _Py_Identifier *nameid, char *format, ...)
/* Clone of call_method() that returns NotImplemented when the lookup fails. */
static PyObject *
-call_maybe(PyObject *o, _Py_Identifier *nameid, char *format, ...)
+call_maybe(PyObject *o, _Py_Identifier *nameid, const char *format, ...)
{
va_list va;
- PyObject *args, *func = 0, *retval;
- va_start(va, format);
+ PyObject *func = NULL, *retval;
func = lookup_maybe(o, nameid);
if (func == NULL) {
- va_end(va);
if (!PyErr_Occurred())
Py_RETURN_NOTIMPLEMENTED;
return NULL;
}
- if (format && *format)
+ if (format && *format) {
+ PyObject *args;
+
+ va_start(va, format);
args = Py_VaBuildValue(format, va);
- else
- args = PyTuple_New(0);
+ va_end(va);
- va_end(va);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return NULL;
+ }
+ assert(PyTuple_Check(args));
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
+ retval = PyObject_Call(func, args, NULL);
+ Py_DECREF(args);
+ }
+ else {
+ retval = _PyObject_CallNoArg(func);
}
- assert(PyTuple_Check(args));
- retval = PyObject_Call(func, args, NULL);
-
- Py_DECREF(args);
Py_DECREF(func);
return retval;
@@ -1531,7 +1548,6 @@ class_name(PyObject *cls)
PyObject *name = _PyObject_GetAttrId(cls, &PyId___name__);
if (name == NULL) {
PyErr_Clear();
- Py_XDECREF(name);
name = PyObject_Repr(cls);
}
if (name == NULL)
@@ -1610,7 +1626,7 @@ consistent method resolution\norder (MRO) for bases");
PyObject *name = class_name(k);
char *name_str;
if (name != NULL) {
- name_str = _PyUnicode_AsString(name);
+ name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
name_str = "?";
} else
@@ -2025,6 +2041,8 @@ static void object_dealloc(PyObject *);
static int object_init(PyObject *, PyObject *, PyObject *);
static int update_slot(PyTypeObject *, PyObject *);
static void fixup_slot_dispatchers(PyTypeObject *);
+static int set_names(PyTypeObject *);
+static int init_subclass(PyTypeObject *, PyObject *);
/*
* Helpers for __dict__ descriptor. We don't want to expose the dicts
@@ -2089,7 +2107,7 @@ subtype_dict(PyObject *obj, void *context)
static int
subtype_setdict(PyObject *obj, PyObject *value, void *context)
{
- PyObject *dict, **dictptr;
+ PyObject **dictptr;
PyTypeObject *base;
base = get_builtin_base_with_dict(Py_TYPE(obj));
@@ -2120,10 +2138,8 @@ subtype_setdict(PyObject *obj, PyObject *value, void *context)
"not a '%.200s'", Py_TYPE(value)->tp_name);
return -1;
}
- dict = *dictptr;
Py_XINCREF(value);
- *dictptr = value;
- Py_XDECREF(dict);
+ Py_XSETREF(*dictptr, value);
return 0;
}
@@ -2202,7 +2218,8 @@ type_init(PyObject *cls, PyObject *args, PyObject *kwds)
assert(args != NULL && PyTuple_Check(args));
assert(kwds == NULL || PyDict_Check(kwds));
- if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds) != 0) {
+ if (kwds != NULL && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
+ PyDict_Check(kwds) && PyDict_Size(kwds) != 0) {
PyErr_SetString(PyExc_TypeError,
"type.__init__() takes no keyword arguments");
return -1;
@@ -2269,8 +2286,7 @@ static PyObject *
type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{
PyObject *name, *bases = NULL, *orig_dict, *dict = NULL;
- static char *kwlist[] = {"name", "bases", "dict", 0};
- PyObject *qualname, *slots = NULL, *tmp, *newslots;
+ PyObject *qualname, *slots = NULL, *tmp, *newslots, *cell;
PyTypeObject *type = NULL, *base, *tmptype, *winner;
PyHeapTypeObject *et;
PyMemberDef *mp;
@@ -2278,16 +2294,19 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
int j, may_add_dict, may_add_weak, add_dict, add_weak;
_Py_IDENTIFIER(__qualname__);
_Py_IDENTIFIER(__slots__);
+ _Py_IDENTIFIER(__classcell__);
assert(args != NULL && PyTuple_Check(args));
assert(kwds == NULL || PyDict_Check(kwds));
/* Special case: type(x) should return x->ob_type */
- {
+ /* We only want type itself to accept the one-argument form (#27157)
+ Note: We don't call PyType_CheckExact as that also allows subclasses */
+ if (metatype == &PyType_Type) {
const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);
- if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
+ if (nargs == 1 && nkwds == 0) {
PyObject *x = PyTuple_GET_ITEM(args, 0);
Py_INCREF(Py_TYPE(x));
return (PyObject *) Py_TYPE(x);
@@ -2296,7 +2315,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
/* SF bug 475327 -- if that didn't trigger, we need 3
arguments. but PyArg_ParseTupleAndKeywords below may give
a msg saying type() needs exactly 3. */
- if (nargs + nkwds != 3) {
+ if (nargs != 3) {
PyErr_SetString(PyExc_TypeError,
"type() takes 1 or 3 arguments");
return NULL;
@@ -2304,10 +2323,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
}
/* Check arguments: (name, bases, dict) */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "UO!O!:type", kwlist,
- &name,
- &PyTuple_Type, &bases,
- &PyDict_Type, &orig_dict))
+ if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type,
+ &bases, &PyDict_Type, &orig_dict))
return NULL;
/* Determine the proper metatype to deal with this: */
@@ -2544,7 +2561,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
}
et->ht_qualname = qualname ? qualname : et->ht_name;
Py_INCREF(et->ht_qualname);
- if (qualname != NULL && PyDict_DelItem(dict, PyId___qualname__.object) < 0)
+ if (qualname != NULL && _PyDict_DelItemId(dict, &PyId___qualname__) < 0)
goto error;
/* Set tp_doc to a copy of dict['__doc__'], if the latter is there
@@ -2558,7 +2575,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
char *doc_str;
char *tp_doc;
- doc_str = _PyUnicode_AsString(doc);
+ doc_str = PyUnicode_AsUTF8(doc);
if (doc_str == NULL)
goto error;
/* Silently truncate the docstring if it contains null bytes. */
@@ -2587,12 +2604,26 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
Py_DECREF(tmp);
}
+ /* Special-case __init_subclass__: if it's a plain function,
+ make it a classmethod */
+ tmp = _PyDict_GetItemId(dict, &PyId___init_subclass__);
+ if (tmp != NULL && PyFunction_Check(tmp)) {
+ tmp = PyClassMethod_New(tmp);
+ if (tmp == NULL)
+ goto error;
+ if (_PyDict_SetItemId(dict, &PyId___init_subclass__, tmp) < 0) {
+ Py_DECREF(tmp);
+ goto error;
+ }
+ Py_DECREF(tmp);
+ }
+
/* Add descriptors for custom slots from __slots__, or for __dict__ */
mp = PyHeapType_GET_MEMBERS(et);
slotoffset = base->tp_basicsize;
if (et->ht_slots != NULL) {
for (i = 0; i < nslots; i++, mp++) {
- mp->name = _PyUnicode_AsString(
+ mp->name = PyUnicode_AsUTF8(
PyTuple_GET_ITEM(et->ht_slots, i));
if (mp->name == NULL)
goto error;
@@ -2656,6 +2687,21 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
else
type->tp_free = PyObject_Del;
+ /* store type in class' cell if one is supplied */
+ cell = _PyDict_GetItemId(dict, &PyId___classcell__);
+ if (cell != NULL) {
+ /* At least one method requires a reference to its defining class */
+ if (!PyCell_Check(cell)) {
+ PyErr_Format(PyExc_TypeError,
+ "__classcell__ must be a nonlocal cell, not %.200R",
+ Py_TYPE(cell));
+ goto error;
+ }
+ PyCell_Set(cell, (PyObject *) type);
+ _PyDict_DelItemId(dict, &PyId___classcell__);
+ PyErr_Clear();
+ }
+
/* Initialize the rest */
if (PyType_Ready(type) < 0)
goto error;
@@ -2667,6 +2713,12 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
et->ht_cached_keys = _PyDict_NewKeysForClass();
}
+ if (set_names(type) < 0)
+ goto error;
+
+ if (init_subclass(type, kwds) < 0)
+ goto error;
+
Py_DECREF(dict);
return (PyObject *)type;
@@ -2678,7 +2730,7 @@ error:
return NULL;
}
-static short slotoffsets[] = {
+static const short slotoffsets[] = {
-1, /* invalid slot */
#include "typeslots.inc"
};
@@ -2803,13 +2855,16 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
/* Set type.__module__ */
s = strrchr(spec->name, '.');
if (s != NULL) {
+ int err;
modname = PyUnicode_FromStringAndSize(
spec->name, (Py_ssize_t)(s - spec->name));
if (modname == NULL) {
goto fail;
}
- _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname);
+ err = _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname);
Py_DECREF(modname);
+ if (err != 0)
+ goto fail;
} else {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"builtin type %.200s has no __module__ attribute",
@@ -3611,7 +3666,7 @@ same_slots_added(PyTypeObject *a, PyTypeObject *b)
}
static int
-compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, char* attr)
+compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, const char* attr)
{
PyTypeObject *newbase, *oldbase;
@@ -3787,7 +3842,7 @@ import_copyreg(void)
return PyImport_Import(copyreg_str);
}
-Py_LOCAL(PyObject *)
+static PyObject *
_PyType_GetSlotNames(PyTypeObject *cls)
{
PyObject *copyreg;
@@ -3840,7 +3895,7 @@ _PyType_GetSlotNames(PyTypeObject *cls)
return slotnames;
}
-Py_LOCAL(PyObject *)
+static PyObject *
_PyObject_GetState(PyObject *obj, int required)
{
PyObject *state;
@@ -3887,6 +3942,24 @@ _PyObject_GetState(PyObject *obj, int required)
}
assert(slotnames == Py_None || PyList_Check(slotnames));
+ if (required) {
+ Py_ssize_t basicsize = PyBaseObject_Type.tp_basicsize;
+ if (obj->ob_type->tp_dictoffset)
+ basicsize += sizeof(PyObject *);
+ if (obj->ob_type->tp_weaklistoffset)
+ basicsize += sizeof(PyObject *);
+ if (slotnames != Py_None)
+ basicsize += sizeof(PyObject *) * Py_SIZE(slotnames);
+ if (obj->ob_type->tp_basicsize > basicsize) {
+ Py_DECREF(slotnames);
+ Py_DECREF(state);
+ PyErr_Format(PyExc_TypeError,
+ "can't pickle %.200s objects",
+ Py_TYPE(obj)->tp_name);
+ return NULL;
+ }
+ }
+
if (slotnames != Py_None && Py_SIZE(slotnames) > 0) {
PyObject *slots;
Py_ssize_t slotnames_size, i;
@@ -3941,7 +4014,7 @@ _PyObject_GetState(PyObject *obj, int required)
}
/* If we found some slot attributes, pack them in a tuple along
- the orginal attribute dictionary. */
+ the original attribute dictionary. */
if (PyDict_Size(slots) > 0) {
PyObject *state2;
@@ -3968,7 +4041,7 @@ _PyObject_GetState(PyObject *obj, int required)
return state;
}
-Py_LOCAL(int)
+static int
_PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
{
PyObject *getnewargs, *getnewargs_ex;
@@ -4064,7 +4137,7 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs)
return 0;
}
-Py_LOCAL(int)
+static int
_PyObject_GetItemsIter(PyObject *obj, PyObject **listitems,
PyObject **dictitems)
{
@@ -4110,7 +4183,7 @@ _PyObject_GetItemsIter(PyObject *obj, PyObject **listitems,
}
static PyObject *
-reduce_newobj(PyObject *obj, int proto)
+reduce_newobj(PyObject *obj)
{
PyObject *args = NULL, *kwargs = NULL;
PyObject *copyreg;
@@ -4163,7 +4236,7 @@ reduce_newobj(PyObject *obj, int proto)
}
Py_XDECREF(args);
}
- else if (proto >= 4) {
+ else if (args != NULL) {
_Py_IDENTIFIER(__newobj_ex__);
newobj = _PyObject_GetAttrId(copyreg, &PyId___newobj_ex__);
@@ -4182,13 +4255,9 @@ reduce_newobj(PyObject *obj, int proto)
}
}
else {
- PyErr_SetString(PyExc_ValueError,
- "must use protocol 4 or greater to copy this "
- "object; since __getnewargs_ex__ returned "
- "keyword arguments.");
- Py_DECREF(args);
+ /* args == NULL */
Py_DECREF(kwargs);
- Py_DECREF(copyreg);
+ PyErr_BadInternalCall();
return NULL;
}
@@ -4236,7 +4305,7 @@ _common_reduce(PyObject *self, int proto)
PyObject *copyreg, *res;
if (proto >= 2)
- return reduce_newobj(self, proto);
+ return reduce_newobj(self);
copyreg = import_copyreg();
if (!copyreg)
@@ -4319,6 +4388,18 @@ PyDoc_STRVAR(object_subclasshook_doc,
"overrides the normal algorithm (and the outcome is cached).\n");
static PyObject *
+object_init_subclass(PyObject *cls, PyObject *arg)
+{
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(object_init_subclass_doc,
+"This method is called when a class is subclassed.\n"
+"\n"
+"The default implementation does nothing. It may be\n"
+"overridden to extend subclasses.\n");
+
+static PyObject *
object_format(PyObject *self, PyObject *args)
{
PyObject *format_spec;
@@ -4412,6 +4493,8 @@ static PyMethodDef object_methods[] = {
PyDoc_STR("helper for pickle")},
{"__subclasshook__", object_subclasshook, METH_CLASS | METH_VARARGS,
object_subclasshook_doc},
+ {"__init_subclass__", object_init_subclass, METH_CLASS | METH_NOARGS,
+ object_init_subclass_doc},
{"__format__", object_format, METH_VARARGS,
PyDoc_STR("default object formatter")},
{"__sizeof__", object_sizeof, METH_NOARGS,
@@ -5363,7 +5446,7 @@ wrap_delitem(PyObject *self, PyObject *args, void *wrapped)
/* Helper to check for object.__setattr__ or __delattr__ applied to a type.
This is called the Carlo Verre hack after its discoverer. */
static int
-hackcheck(PyObject *self, setattrofunc func, char *what)
+hackcheck(PyObject *self, setattrofunc func, const char *what)
{
PyTypeObject *type = Py_TYPE(self);
while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE)
@@ -5650,7 +5733,7 @@ static PyObject * \
FUNCNAME(PyObject *self) \
{ \
_Py_static_string(id, OPSTR); \
- return call_method(self, &id, "()"); \
+ return call_method(self, &id, NULL); \
}
#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \
@@ -5743,7 +5826,7 @@ FUNCNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \
static Py_ssize_t
slot_sq_length(PyObject *self)
{
- PyObject *res = call_method(self, &PyId___len__, "()");
+ PyObject *res = call_method(self, &PyId___len__, NULL);
Py_ssize_t len;
if (res == NULL)
@@ -5764,38 +5847,39 @@ slot_sq_length(PyObject *self)
static PyObject *
slot_sq_item(PyObject *self, Py_ssize_t i)
{
- PyObject *func, *args = NULL, *ival = NULL, *retval = NULL;
+ PyObject *func, *ival = NULL, *retval = NULL;
descrgetfunc f;
func = _PyType_LookupId(Py_TYPE(self), &PyId___getitem__);
- if (func != NULL) {
- if ((f = Py_TYPE(func)->tp_descr_get) == NULL)
- Py_INCREF(func);
- else {
- func = f(func, self, (PyObject *)(Py_TYPE(self)));
- if (func == NULL) {
- return NULL;
- }
- }
- ival = PyLong_FromSsize_t(i);
- if (ival != NULL) {
- args = PyTuple_New(1);
- if (args != NULL) {
- PyTuple_SET_ITEM(args, 0, ival);
- retval = PyObject_Call(func, args, NULL);
- Py_XDECREF(args);
- Py_XDECREF(func);
- return retval;
- }
- }
- }
- else {
+ if (func == NULL) {
PyObject *getitem_str = _PyUnicode_FromId(&PyId___getitem__);
PyErr_SetObject(PyExc_AttributeError, getitem_str);
+ return NULL;
+ }
+
+ f = Py_TYPE(func)->tp_descr_get;
+ if (f == NULL) {
+ Py_INCREF(func);
}
- Py_XDECREF(args);
- Py_XDECREF(ival);
- Py_XDECREF(func);
+ else {
+ func = f(func, self, (PyObject *)(Py_TYPE(self)));
+ if (func == NULL) {
+ return NULL;
+ }
+ }
+
+ ival = PyLong_FromSsize_t(i);
+ if (ival == NULL) {
+ goto error;
+ }
+
+ retval = _PyObject_CallArg1(func, ival);
+ Py_DECREF(func);
+ Py_DECREF(ival);
+ return retval;
+
+error:
+ Py_DECREF(func);
return NULL;
}
@@ -5817,19 +5901,20 @@ slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)
static int
slot_sq_contains(PyObject *self, PyObject *value)
{
- PyObject *func, *res, *args;
+ PyObject *func, *res;
int result = -1;
_Py_IDENTIFIER(__contains__);
func = lookup_maybe(self, &PyId___contains__);
+ if (func == Py_None) {
+ Py_DECREF(func);
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is not a container",
+ Py_TYPE(self)->tp_name);
+ return -1;
+ }
if (func != NULL) {
- args = PyTuple_Pack(1, value);
- if (args == NULL)
- res = NULL;
- else {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
+ res = _PyObject_CallArg1(func, value);
Py_DECREF(func);
if (res != NULL) {
result = PyObject_IsTrue(res);
@@ -5900,44 +5985,54 @@ SLOT0(slot_nb_absolute, "__abs__")
static int
slot_nb_bool(PyObject *self)
{
- PyObject *func, *args;
- int result = -1;
+ PyObject *func, *value;
+ int result;
int using_len = 0;
_Py_IDENTIFIER(__bool__);
func = lookup_maybe(self, &PyId___bool__);
if (func == NULL) {
- if (PyErr_Occurred())
+ if (PyErr_Occurred()) {
return -1;
+ }
+
func = lookup_maybe(self, &PyId___len__);
- if (func == NULL)
- return PyErr_Occurred() ? -1 : 1;
- using_len = 1;
- }
- args = PyTuple_New(0);
- if (args != NULL) {
- PyObject *temp = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- if (temp != NULL) {
- if (using_len) {
- /* enforced by slot_nb_len */
- result = PyObject_IsTrue(temp);
- }
- else if (PyBool_Check(temp)) {
- result = PyObject_IsTrue(temp);
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "__bool__ should return "
- "bool, returned %s",
- Py_TYPE(temp)->tp_name);
- result = -1;
+ if (func == NULL) {
+ if (PyErr_Occurred()) {
+ return -1;
}
- Py_DECREF(temp);
+ return 1;
}
+ using_len = 1;
+ }
+
+ value = _PyObject_CallNoArg(func);
+ if (value == NULL) {
+ goto error;
+ }
+
+ if (using_len) {
+ /* bool type enforced by slot_nb_len */
+ result = PyObject_IsTrue(value);
}
+ else if (PyBool_Check(value)) {
+ result = PyObject_IsTrue(value);
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "__bool__ should return "
+ "bool, returned %s",
+ Py_TYPE(value)->tp_name);
+ result = -1;
+ }
+
+ Py_DECREF(value);
Py_DECREF(func);
return result;
+
+error:
+ Py_DECREF(func);
+ return -1;
}
@@ -5945,7 +6040,7 @@ static PyObject *
slot_nb_index(PyObject *self)
{
_Py_IDENTIFIER(__index__);
- return call_method(self, &PyId___index__, "()");
+ return call_method(self, &PyId___index__, NULL);
}
@@ -6182,20 +6277,14 @@ static _Py_Identifier name_op[] = {
static PyObject *
slot_tp_richcompare(PyObject *self, PyObject *other, int op)
{
- PyObject *func, *args, *res;
+ PyObject *func, *res;
func = lookup_method(self, &name_op[op]);
if (func == NULL) {
PyErr_Clear();
Py_RETURN_NOTIMPLEMENTED;
}
- args = PyTuple_Pack(1, other);
- if (args == NULL)
- res = NULL;
- else {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
+ res = _PyObject_CallArg1(func, other);
Py_DECREF(func);
return res;
}
@@ -6207,16 +6296,20 @@ slot_tp_iter(PyObject *self)
_Py_IDENTIFIER(__iter__);
func = lookup_method(self, &PyId___iter__);
+ if (func == Py_None) {
+ Py_DECREF(func);
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is not iterable",
+ Py_TYPE(self)->tp_name);
+ return NULL;
+ }
+
if (func != NULL) {
- PyObject *args;
- args = res = PyTuple_New(0);
- if (args != NULL) {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
+ res = _PyObject_CallNoArg(func);
Py_DECREF(func);
return res;
}
+
PyErr_Clear();
func = lookup_method(self, &PyId___getitem__);
if (func == NULL) {
@@ -6233,7 +6326,7 @@ static PyObject *
slot_tp_iternext(PyObject *self)
{
_Py_IDENTIFIER(__next__);
- return call_method(self, &PyId___next__, "()");
+ return call_method(self, &PyId___next__, NULL);
}
static PyObject *
@@ -6302,29 +6395,16 @@ slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
static PyObject *
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyObject *func;
- PyObject *newargs, *x;
- Py_ssize_t i, n;
+ PyObject *func, *result;
func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__);
- if (func == NULL)
- return NULL;
- assert(PyTuple_Check(args));
- n = PyTuple_GET_SIZE(args);
- newargs = PyTuple_New(n+1);
- if (newargs == NULL)
+ if (func == NULL) {
return NULL;
- Py_INCREF(type);
- PyTuple_SET_ITEM(newargs, 0, (PyObject *)type);
- for (i = 0; i < n; i++) {
- x = PyTuple_GET_ITEM(args, i);
- Py_INCREF(x);
- PyTuple_SET_ITEM(newargs, i+1, x);
}
- x = PyObject_Call(func, newargs, kwds);
- Py_DECREF(newargs);
+
+ result = _PyObject_Call_Prepend(func, (PyObject *)type, args, kwds);
Py_DECREF(func);
- return x;
+ return result;
}
static void
@@ -6927,6 +7007,72 @@ update_all_slots(PyTypeObject* type)
}
}
+/* Call __set_name__ on all descriptors in a newly generated type */
+static int
+set_names(PyTypeObject *type)
+{
+ PyObject *names_to_set, *key, *value, *set_name, *tmp;
+ Py_ssize_t i = 0;
+
+ names_to_set = PyDict_Copy(type->tp_dict);
+ if (names_to_set == NULL)
+ return -1;
+
+ while (PyDict_Next(names_to_set, &i, &key, &value)) {
+ set_name = lookup_maybe(value, &PyId___set_name__);
+ if (set_name != NULL) {
+ tmp = PyObject_CallFunctionObjArgs(set_name, type, key, NULL);
+ Py_DECREF(set_name);
+ if (tmp == NULL) {
+ _PyErr_FormatFromCause(PyExc_RuntimeError,
+ "Error calling __set_name__ on '%.100s' instance %R "
+ "in '%.100s'",
+ value->ob_type->tp_name, key, type->tp_name);
+ Py_DECREF(names_to_set);
+ return -1;
+ }
+ else
+ Py_DECREF(tmp);
+ }
+ else if (PyErr_Occurred()) {
+ Py_DECREF(names_to_set);
+ return -1;
+ }
+ }
+
+ Py_DECREF(names_to_set);
+ return 0;
+}
+
+/* Call __init_subclass__ on the parent of a newly generated type */
+static int
+init_subclass(PyTypeObject *type, PyObject *kwds)
+{
+ PyObject *super, *func, *result;
+ PyObject *args[2] = {(PyObject *)type, (PyObject *)type};
+
+ super = _PyObject_FastCall((PyObject *)&PySuper_Type, args, 2);
+ if (super == NULL) {
+ return -1;
+ }
+
+ func = _PyObject_GetAttrId(super, &PyId___init_subclass__);
+ Py_DECREF(super);
+ if (func == NULL) {
+ return -1;
+ }
+
+
+ result = _PyObject_FastCallDict(func, NULL, 0, kwds);
+ Py_DECREF(func);
+ if (result == NULL) {
+ return -1;
+ }
+
+ Py_DECREF(result);
+ return 0;
+}
+
/* recurse_down_subclasses() and update_subclasses() are mutually
recursive functions to call a callback for all subclasses,
but refraining from recursing into subclasses that define 'name'. */
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 64a3760328..a5ae454b49 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -42,6 +42,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "Python.h"
#include "ucnhash.h"
#include "bytes_methods.h"
+#include "stringlib/eq.h"
#ifdef MS_WINDOWS
#include <windows.h>
@@ -162,6 +163,14 @@ extern "C" {
*_to++ = (to_type) *_iter++; \
} while (0)
+#ifdef MS_WINDOWS
+ /* On Windows, overallocate by 50% is the best factor */
+# define OVERALLOCATE_FACTOR 2
+#else
+ /* On Linux, overallocate by 25% is the best factor */
+# define OVERALLOCATE_FACTOR 4
+#endif
+
/* This dictionary holds all interned unicode strings. Note that references
to strings in this dictionary are *not* counted in the string's ob_refcnt.
When the interned string reaches a refcnt of 0 the string deallocation
@@ -195,7 +204,7 @@ static PyObject *unicode_empty = NULL;
} while (0)
/* Forward declaration */
-Py_LOCAL_INLINE(int)
+static inline int
_PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch);
/* List of static strings. */
@@ -263,7 +272,7 @@ raise_encode_exception(PyObject **exceptionObject,
const char *reason);
/* Same for linebreaks */
-static unsigned char ascii_linebreak[] = {
+static const unsigned char ascii_linebreak[] = {
0, 0, 0, 0, 0, 0, 0, 0,
/* 0x000A, * LINE FEED */
/* 0x000B, * LINE TABULATION */
@@ -292,6 +301,45 @@ static unsigned char ascii_linebreak[] = {
#include "clinic/unicodeobject.c.h"
+typedef enum {
+ _Py_ERROR_UNKNOWN=0,
+ _Py_ERROR_STRICT,
+ _Py_ERROR_SURROGATEESCAPE,
+ _Py_ERROR_REPLACE,
+ _Py_ERROR_IGNORE,
+ _Py_ERROR_BACKSLASHREPLACE,
+ _Py_ERROR_SURROGATEPASS,
+ _Py_ERROR_XMLCHARREFREPLACE,
+ _Py_ERROR_OTHER
+} _Py_error_handler;
+
+static _Py_error_handler
+get_error_handler(const char *errors)
+{
+ if (errors == NULL || strcmp(errors, "strict") == 0) {
+ return _Py_ERROR_STRICT;
+ }
+ if (strcmp(errors, "surrogateescape") == 0) {
+ return _Py_ERROR_SURROGATEESCAPE;
+ }
+ if (strcmp(errors, "replace") == 0) {
+ return _Py_ERROR_REPLACE;
+ }
+ if (strcmp(errors, "ignore") == 0) {
+ return _Py_ERROR_IGNORE;
+ }
+ if (strcmp(errors, "backslashreplace") == 0) {
+ return _Py_ERROR_BACKSLASHREPLACE;
+ }
+ if (strcmp(errors, "surrogatepass") == 0) {
+ return _Py_ERROR_SURROGATEPASS;
+ }
+ if (strcmp(errors, "xmlcharrefreplace") == 0) {
+ return _Py_ERROR_XMLCHARREFREPLACE;
+ }
+ return _Py_ERROR_OTHER;
+}
+
/* The max unicode value is always 0x10FFFF while using the PEP-393 API.
This function is kept for backward compatibility with the old API. */
Py_UNICODE
@@ -521,6 +569,129 @@ unicode_result_unchanged(PyObject *unicode)
return _PyUnicode_Copy(unicode);
}
+/* Implementation of the "backslashreplace" error handler for 8-bit encodings:
+ ASCII, Latin1, UTF-8, etc. */
+static char*
+backslashreplace(_PyBytesWriter *writer, char *str,
+ PyObject *unicode, Py_ssize_t collstart, Py_ssize_t collend)
+{
+ Py_ssize_t size, i;
+ Py_UCS4 ch;
+ enum PyUnicode_Kind kind;
+ void *data;
+
+ assert(PyUnicode_IS_READY(unicode));
+ kind = PyUnicode_KIND(unicode);
+ data = PyUnicode_DATA(unicode);
+
+ size = 0;
+ /* determine replacement size */
+ for (i = collstart; i < collend; ++i) {
+ Py_ssize_t incr;
+
+ ch = PyUnicode_READ(kind, data, i);
+ if (ch < 0x100)
+ incr = 2+2;
+ else if (ch < 0x10000)
+ incr = 2+4;
+ else {
+ assert(ch <= MAX_UNICODE);
+ incr = 2+8;
+ }
+ if (size > PY_SSIZE_T_MAX - incr) {
+ PyErr_SetString(PyExc_OverflowError,
+ "encoded result is too long for a Python string");
+ return NULL;
+ }
+ size += incr;
+ }
+
+ str = _PyBytesWriter_Prepare(writer, str, size);
+ if (str == NULL)
+ return NULL;
+
+ /* generate replacement */
+ for (i = collstart; i < collend; ++i) {
+ ch = PyUnicode_READ(kind, data, i);
+ *str++ = '\\';
+ if (ch >= 0x00010000) {
+ *str++ = 'U';
+ *str++ = Py_hexdigits[(ch>>28)&0xf];
+ *str++ = Py_hexdigits[(ch>>24)&0xf];
+ *str++ = Py_hexdigits[(ch>>20)&0xf];
+ *str++ = Py_hexdigits[(ch>>16)&0xf];
+ *str++ = Py_hexdigits[(ch>>12)&0xf];
+ *str++ = Py_hexdigits[(ch>>8)&0xf];
+ }
+ else if (ch >= 0x100) {
+ *str++ = 'u';
+ *str++ = Py_hexdigits[(ch>>12)&0xf];
+ *str++ = Py_hexdigits[(ch>>8)&0xf];
+ }
+ else
+ *str++ = 'x';
+ *str++ = Py_hexdigits[(ch>>4)&0xf];
+ *str++ = Py_hexdigits[ch&0xf];
+ }
+ return str;
+}
+
+/* Implementation of the "xmlcharrefreplace" error handler for 8-bit encodings:
+ ASCII, Latin1, UTF-8, etc. */
+static char*
+xmlcharrefreplace(_PyBytesWriter *writer, char *str,
+ PyObject *unicode, Py_ssize_t collstart, Py_ssize_t collend)
+{
+ Py_ssize_t size, i;
+ Py_UCS4 ch;
+ enum PyUnicode_Kind kind;
+ void *data;
+
+ assert(PyUnicode_IS_READY(unicode));
+ kind = PyUnicode_KIND(unicode);
+ data = PyUnicode_DATA(unicode);
+
+ size = 0;
+ /* determine replacement size */
+ for (i = collstart; i < collend; ++i) {
+ Py_ssize_t incr;
+
+ ch = PyUnicode_READ(kind, data, i);
+ if (ch < 10)
+ incr = 2+1+1;
+ else if (ch < 100)
+ incr = 2+2+1;
+ else if (ch < 1000)
+ incr = 2+3+1;
+ else if (ch < 10000)
+ incr = 2+4+1;
+ else if (ch < 100000)
+ incr = 2+5+1;
+ else if (ch < 1000000)
+ incr = 2+6+1;
+ else {
+ assert(ch <= MAX_UNICODE);
+ incr = 2+7+1;
+ }
+ if (size > PY_SSIZE_T_MAX - incr) {
+ PyErr_SetString(PyExc_OverflowError,
+ "encoded result is too long for a Python string");
+ return NULL;
+ }
+ size += incr;
+ }
+
+ str = _PyBytesWriter_Prepare(writer, str, size);
+ if (str == NULL)
+ return NULL;
+
+ /* generate replacement */
+ for (i = collstart; i < collend; ++i) {
+ str += sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i));
+ }
+ return str;
+}
+
/* --- Bloom Filters ----------------------------------------------------- */
/* stuff to implement simple "bloom filters" for Unicode characters.
@@ -549,7 +720,7 @@ static BLOOM_MASK bloom_linebreak = ~(BLOOM_MASK)0;
((ch) < 128U ? ascii_linebreak[(ch)] : \
(BLOOM(bloom_linebreak, (ch)) && Py_UNICODE_ISLINEBREAK(ch)))
-Py_LOCAL_INLINE(BLOOM_MASK)
+static inline BLOOM_MASK
make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
{
#define BLOOM_UPDATE(TYPE, MASK, PTR, LEN) \
@@ -587,6 +758,18 @@ make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
#undef BLOOM_UPDATE
}
+static int
+ensure_unicode(PyObject *obj)
+{
+ if (!PyUnicode_Check(obj)) {
+ PyErr_Format(PyExc_TypeError,
+ "must be str, not %.100s",
+ Py_TYPE(obj)->tp_name);
+ return -1;
+ }
+ return PyUnicode_READY(obj);
+}
+
/* Compilation of templated routines */
#include "stringlib/asciilib.h"
@@ -643,31 +826,31 @@ make_bloom_mask(int kind, void* ptr, Py_ssize_t len)
static PyObject *
fixup(PyObject *self, Py_UCS4 (*fixfct)(PyObject *s));
-Py_LOCAL_INLINE(Py_ssize_t) findchar(const void *s, int kind,
- Py_ssize_t size, Py_UCS4 ch,
- int direction)
+static inline Py_ssize_t
+findchar(const void *s, int kind,
+ Py_ssize_t size, Py_UCS4 ch,
+ int direction)
{
- int mode = (direction == 1) ? FAST_SEARCH : FAST_RSEARCH;
-
switch (kind) {
case PyUnicode_1BYTE_KIND:
- {
- Py_UCS1 ch1 = (Py_UCS1) ch;
- if (ch1 == ch)
- return ucs1lib_fastsearch((Py_UCS1 *) s, size, &ch1, 1, 0, mode);
- else
- return -1;
- }
+ if ((Py_UCS1) ch != ch)
+ return -1;
+ if (direction > 0)
+ return ucs1lib_find_char((Py_UCS1 *) s, size, (Py_UCS1) ch);
+ else
+ return ucs1lib_rfind_char((Py_UCS1 *) s, size, (Py_UCS1) ch);
case PyUnicode_2BYTE_KIND:
- {
- Py_UCS2 ch2 = (Py_UCS2) ch;
- if (ch2 == ch)
- return ucs2lib_fastsearch((Py_UCS2 *) s, size, &ch2, 1, 0, mode);
- else
- return -1;
- }
+ if ((Py_UCS2) ch != ch)
+ return -1;
+ if (direction > 0)
+ return ucs2lib_find_char((Py_UCS2 *) s, size, (Py_UCS2) ch);
+ else
+ return ucs2lib_rfind_char((Py_UCS2 *) s, size, (Py_UCS2) ch);
case PyUnicode_4BYTE_KIND:
- return ucs4lib_fastsearch((Py_UCS4 *) s, size, &ch, 1, 0, mode);
+ if (direction > 0)
+ return ucs4lib_find_char((Py_UCS4 *) s, size, ch);
+ else
+ return ucs4lib_rfind_char((Py_UCS4 *) s, size, ch);
default:
assert(0);
return -1;
@@ -865,7 +1048,7 @@ resize_copy(PyObject *unicode, Py_ssize_t length)
return NULL;
copy_length = _PyUnicode_WSTR_LENGTH(unicode);
copy_length = Py_MIN(copy_length, length);
- Py_MEMCPY(_PyUnicode_WSTR(w), _PyUnicode_WSTR(unicode),
+ memcpy(_PyUnicode_WSTR(w), _PyUnicode_WSTR(unicode),
copy_length * sizeof(wchar_t));
return w;
}
@@ -1252,7 +1435,7 @@ _copy_characters(PyObject *to, Py_ssize_t to_start,
if (max_char >= 128)
return -1;
}
- Py_MEMCPY((char*)to_data + to_kind * to_start,
+ memcpy((char*)to_data + to_kind * to_start,
(char*)from_data + from_kind * from_start,
to_kind * how_many);
}
@@ -1845,7 +2028,7 @@ PyUnicode_FromUnicode(const Py_UNICODE *u, Py_ssize_t size)
break;
case PyUnicode_2BYTE_KIND:
#if Py_UNICODE_SIZE == 2
- Py_MEMCPY(PyUnicode_2BYTE_DATA(unicode), u, size * 2);
+ memcpy(PyUnicode_2BYTE_DATA(unicode), u, size * 2);
#else
_PyUnicode_CONVERT_BYTES(Py_UNICODE, Py_UCS2,
u, u + size, PyUnicode_2BYTE_DATA(unicode));
@@ -1858,7 +2041,7 @@ PyUnicode_FromUnicode(const Py_UNICODE *u, Py_ssize_t size)
unicode_convert_wchar_to_ucs4(u, u + size, unicode);
#else
assert(num_surrogates == 0);
- Py_MEMCPY(PyUnicode_4BYTE_DATA(unicode), u, size * 4);
+ memcpy(PyUnicode_4BYTE_DATA(unicode), u, size * 4);
#endif
break;
default:
@@ -1960,7 +2143,7 @@ kind_maxchar_limit(unsigned int kind)
}
}
-Py_LOCAL_INLINE(Py_UCS4)
+static inline Py_UCS4
align_maxchar(Py_UCS4 maxchar)
{
if (maxchar <= 127)
@@ -2169,7 +2352,7 @@ _PyUnicode_Copy(PyObject *unicode)
return NULL;
assert(PyUnicode_KIND(copy) == PyUnicode_KIND(unicode));
- Py_MEMCPY(PyUnicode_DATA(copy), PyUnicode_DATA(unicode),
+ memcpy(PyUnicode_DATA(copy), PyUnicode_DATA(unicode),
length * PyUnicode_KIND(unicode));
assert(_PyUnicode_CheckConsistency(copy, 1));
return copy;
@@ -2275,7 +2458,7 @@ as_ucs4(PyObject *string, Py_UCS4 *target, Py_ssize_t targetsize,
}
else {
assert(kind == PyUnicode_4BYTE_KIND);
- Py_MEMCPY(target, data, len * sizeof(Py_UCS4));
+ memcpy(target, data, len * sizeof(Py_UCS4));
}
if (copy_null)
target[len] = 0;
@@ -2458,13 +2641,11 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
longflag = 1;
++f;
}
-#ifdef HAVE_LONG_LONG
else if (f[1] == 'l' &&
(f[2] == 'd' || f[2] == 'u' || f[2] == 'i')) {
longlongflag = 1;
f += 2;
}
-#endif
}
/* handle the size_t flag. */
else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u' || f[1] == 'i')) {
@@ -2502,11 +2683,9 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
if (longflag)
len = sprintf(buffer, "%lu",
va_arg(*vargs, unsigned long));
-#ifdef HAVE_LONG_LONG
else if (longlongflag)
- len = sprintf(buffer, "%" PY_FORMAT_LONG_LONG "u",
- va_arg(*vargs, unsigned PY_LONG_LONG));
-#endif
+ len = sprintf(buffer, "%llu",
+ va_arg(*vargs, unsigned long long));
else if (size_tflag)
len = sprintf(buffer, "%" PY_FORMAT_SIZE_T "u",
va_arg(*vargs, size_t));
@@ -2521,11 +2700,9 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer,
if (longflag)
len = sprintf(buffer, "%li",
va_arg(*vargs, long));
-#ifdef HAVE_LONG_LONG
else if (longlongflag)
- len = sprintf(buffer, "%" PY_FORMAT_LONG_LONG "i",
- va_arg(*vargs, PY_LONG_LONG));
-#endif
+ len = sprintf(buffer, "%lli",
+ va_arg(*vargs, long long));
else if (size_tflag)
len = sprintf(buffer, "%" PY_FORMAT_SIZE_T "i",
va_arg(*vargs, Py_ssize_t));
@@ -2701,9 +2878,8 @@ PyUnicode_FromFormatV(const char *format, va_list vargs)
writer.min_length = strlen(format) + 100;
writer.overallocate = 1;
- /* va_list may be an array (of 1 item) on some platforms (ex: AMD64).
- Copy it to be able to pass a reference to a subfunction. */
- Py_VA_COPY(vargs2, vargs);
+ // Copy varags to be able to pass a reference to a subfunction.
+ va_copy(vargs2, vargs);
for (f = format; *f; ) {
if (*f == '%') {
@@ -2739,9 +2915,11 @@ PyUnicode_FromFormatV(const char *format, va_list vargs)
f = p;
}
}
+ va_end(vargs2);
return _PyUnicodeWriter_Finish(&writer);
fail:
+ va_end(vargs2);
_PyUnicodeWriter_Dealloc(&writer);
return NULL;
}
@@ -2790,7 +2968,7 @@ unicode_aswidechar(PyObject *unicode,
size = res + 1;
else
res = size;
- Py_MEMCPY(w, wstr, size * sizeof(wchar_t));
+ memcpy(w, wstr, size * sizeof(wchar_t));
return res;
}
else
@@ -2907,7 +3085,7 @@ PyUnicode_FromEncodedObject(PyObject *obj,
/* Retrieve a bytes buffer view through the PEP 3118 buffer interface */
if (PyObject_GetBuffer(obj, &buffer, PyBUF_SIMPLE) < 0) {
PyErr_Format(PyExc_TypeError,
- "coercing to str: need a bytes-like object, %.80s found",
+ "decoding to str: need a bytes-like object, %.80s found",
Py_TYPE(obj)->tp_name);
return NULL;
}
@@ -2922,9 +3100,9 @@ PyUnicode_FromEncodedObject(PyObject *obj,
return v;
}
-/* Convert encoding to lower case and replace '_' with '-' in order to
- catch e.g. UTF_8. Return 0 on error (encoding is longer than lower_len-1),
- 1 on success. */
+/* Normalize an encoding name: similar to encodings.normalize_encoding(), but
+ also convert to lowercase. Return 1 on success, or 0 on error (encoding is
+ longer than lower_len-1). */
int
_Py_normalize_encoding(const char *encoding,
char *lower,
@@ -2933,30 +3111,39 @@ _Py_normalize_encoding(const char *encoding,
const char *e;
char *l;
char *l_end;
+ int punct;
+
+ assert(encoding != NULL);
- if (encoding == NULL) {
- /* 6 == strlen("utf-8") + 1 */
- if (lower_len < 6)
- return 0;
- strcpy(lower, "utf-8");
- return 1;
- }
e = encoding;
l = lower;
l_end = &lower[lower_len - 1];
- while (*e) {
- if (l == l_end)
- return 0;
- if (Py_ISUPPER(*e)) {
- *l++ = Py_TOLOWER(*e++);
+ punct = 0;
+ while (1) {
+ char c = *e;
+ if (c == 0) {
+ break;
}
- else if (*e == '_') {
- *l++ = '-';
- e++;
+
+ if (Py_ISALNUM(c) || c == '.') {
+ if (punct && l != lower) {
+ if (l == l_end) {
+ return 0;
+ }
+ *l++ = '_';
+ }
+ punct = 0;
+
+ if (l == l_end) {
+ return 0;
+ }
+ *l++ = Py_TOLOWER(c);
}
else {
- *l++ = *e++;
+ punct = 1;
}
+
+ e++;
}
*l = '\0';
return 1;
@@ -2970,28 +3157,51 @@ PyUnicode_Decode(const char *s,
{
PyObject *buffer = NULL, *unicode;
Py_buffer info;
- char lower[11]; /* Enough for any encoding shortcut */
+ char buflower[11]; /* strlen("iso-8859-1\0") == 11, longest shortcut */
+
+ if (encoding == NULL) {
+ return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL);
+ }
/* Shortcuts for common default encodings */
- if (_Py_normalize_encoding(encoding, lower, sizeof(lower))) {
- if ((strcmp(lower, "utf-8") == 0) ||
- (strcmp(lower, "utf8") == 0))
- return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL);
- else if ((strcmp(lower, "latin-1") == 0) ||
- (strcmp(lower, "latin1") == 0) ||
- (strcmp(lower, "iso-8859-1") == 0) ||
- (strcmp(lower, "iso8859-1") == 0))
- return PyUnicode_DecodeLatin1(s, size, errors);
-#ifdef HAVE_MBCS
- else if (strcmp(lower, "mbcs") == 0)
- return PyUnicode_DecodeMBCS(s, size, errors);
-#endif
- else if (strcmp(lower, "ascii") == 0)
- return PyUnicode_DecodeASCII(s, size, errors);
- else if (strcmp(lower, "utf-16") == 0)
- return PyUnicode_DecodeUTF16(s, size, errors, 0);
- else if (strcmp(lower, "utf-32") == 0)
- return PyUnicode_DecodeUTF32(s, size, errors, 0);
+ if (_Py_normalize_encoding(encoding, buflower, sizeof(buflower))) {
+ char *lower = buflower;
+
+ /* Fast paths */
+ if (lower[0] == 'u' && lower[1] == 't' && lower[2] == 'f') {
+ lower += 3;
+ if (*lower == '_') {
+ /* Match "utf8" and "utf_8" */
+ lower++;
+ }
+
+ if (lower[0] == '8' && lower[1] == 0) {
+ return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL);
+ }
+ else if (lower[0] == '1' && lower[1] == '6' && lower[2] == 0) {
+ return PyUnicode_DecodeUTF16(s, size, errors, 0);
+ }
+ else if (lower[0] == '3' && lower[1] == '2' && lower[2] == 0) {
+ return PyUnicode_DecodeUTF32(s, size, errors, 0);
+ }
+ }
+ else {
+ if (strcmp(lower, "ascii") == 0
+ || strcmp(lower, "us_ascii") == 0) {
+ return PyUnicode_DecodeASCII(s, size, errors);
+ }
+ #ifdef MS_WINDOWS
+ else if (strcmp(lower, "mbcs") == 0) {
+ return PyUnicode_DecodeMBCS(s, size, errors);
+ }
+ #endif
+ else if (strcmp(lower, "latin1") == 0
+ || strcmp(lower, "latin_1") == 0
+ || strcmp(lower, "iso_8859_1") == 0
+ || strcmp(lower, "iso8859_1") == 0) {
+ return PyUnicode_DecodeLatin1(s, size, errors);
+ }
+ }
}
/* Decode via the codec registry */
@@ -3031,6 +3241,11 @@ PyUnicode_AsDecodedObject(PyObject *unicode,
return NULL;
}
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "PyUnicode_AsDecodedObject() is deprecated; "
+ "use PyCodec_Decode() to decode from str", 1) < 0)
+ return NULL;
+
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
@@ -3050,6 +3265,11 @@ PyUnicode_AsDecodedUnicode(PyObject *unicode,
goto onError;
}
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "PyUnicode_AsDecodedUnicode() is deprecated; "
+ "use PyCodec_Decode() to decode from str to str", 1) < 0)
+ return NULL;
+
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
@@ -3100,6 +3320,12 @@ PyUnicode_AsEncodedObject(PyObject *unicode,
goto onError;
}
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "PyUnicode_AsEncodedObject() is deprecated; "
+ "use PyUnicode_AsEncodedString() to encode from str to bytes "
+ "or PyCodec_Encode() for generic encoding", 1) < 0)
+ return NULL;
+
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
@@ -3163,24 +3389,22 @@ wcstombs_errorpos(const wchar_t *wstr)
static int
locale_error_handler(const char *errors, int *surrogateescape)
{
- if (errors == NULL) {
- *surrogateescape = 0;
- return 0;
- }
-
- if (strcmp(errors, "strict") == 0) {
+ _Py_error_handler error_handler = get_error_handler(errors);
+ switch (error_handler)
+ {
+ case _Py_ERROR_STRICT:
*surrogateescape = 0;
return 0;
- }
- if (strcmp(errors, "surrogateescape") == 0) {
+ case _Py_ERROR_SURROGATEESCAPE:
*surrogateescape = 1;
return 0;
+ default:
+ PyErr_Format(PyExc_ValueError,
+ "only 'strict' and 'surrogateescape' error handlers "
+ "are supported, not '%s'",
+ errors);
+ return -1;
}
- PyErr_Format(PyExc_ValueError,
- "only 'strict' and 'surrogateescape' error handlers "
- "are supported, not '%s'",
- errors);
- return -1;
}
PyObject *
@@ -3296,10 +3520,8 @@ encode_error:
PyObject *
PyUnicode_EncodeFSDefault(PyObject *unicode)
{
-#ifdef HAVE_MBCS
- return PyUnicode_EncodeCodePage(CP_ACP, unicode, NULL);
-#elif defined(__APPLE__)
- return _PyUnicode_AsUTF8String(unicode, "surrogateescape");
+#if defined(__APPLE__)
+ return _PyUnicode_AsUTF8String(unicode, Py_FileSystemDefaultEncodeErrors);
#else
PyInterpreterState *interp = PyThreadState_GET()->interp;
/* Bootstrap check: if the filesystem codec is implemented in Python, we
@@ -3314,10 +3536,10 @@ PyUnicode_EncodeFSDefault(PyObject *unicode)
if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) {
return PyUnicode_AsEncodedString(unicode,
Py_FileSystemDefaultEncoding,
- "surrogateescape");
+ Py_FileSystemDefaultEncodeErrors);
}
else {
- return PyUnicode_EncodeLocale(unicode, "surrogateescape");
+ return PyUnicode_EncodeLocale(unicode, Py_FileSystemDefaultEncodeErrors);
}
#endif
}
@@ -3328,34 +3550,56 @@ PyUnicode_AsEncodedString(PyObject *unicode,
const char *errors)
{
PyObject *v;
- char lower[11]; /* Enough for any encoding shortcut */
+ char buflower[11]; /* strlen("iso_8859_1\0") == 11, longest shortcut */
if (!PyUnicode_Check(unicode)) {
PyErr_BadArgument();
return NULL;
}
+ if (encoding == NULL) {
+ return _PyUnicode_AsUTF8String(unicode, errors);
+ }
+
/* Shortcuts for common default encodings */
- if (_Py_normalize_encoding(encoding, lower, sizeof(lower))) {
- if ((strcmp(lower, "utf-8") == 0) ||
- (strcmp(lower, "utf8") == 0))
- {
- if (errors == NULL || strcmp(errors, "strict") == 0)
- return _PyUnicode_AsUTF8String(unicode, NULL);
- else
+ if (_Py_normalize_encoding(encoding, buflower, sizeof(buflower))) {
+ char *lower = buflower;
+
+ /* Fast paths */
+ if (lower[0] == 'u' && lower[1] == 't' && lower[2] == 'f') {
+ lower += 3;
+ if (*lower == '_') {
+ /* Match "utf8" and "utf_8" */
+ lower++;
+ }
+
+ if (lower[0] == '8' && lower[1] == 0) {
return _PyUnicode_AsUTF8String(unicode, errors);
+ }
+ else if (lower[0] == '1' && lower[1] == '6' && lower[2] == 0) {
+ return _PyUnicode_EncodeUTF16(unicode, errors, 0);
+ }
+ else if (lower[0] == '3' && lower[1] == '2' && lower[2] == 0) {
+ return _PyUnicode_EncodeUTF32(unicode, errors, 0);
+ }
}
- else if ((strcmp(lower, "latin-1") == 0) ||
- (strcmp(lower, "latin1") == 0) ||
- (strcmp(lower, "iso-8859-1") == 0) ||
- (strcmp(lower, "iso8859-1") == 0))
- return _PyUnicode_AsLatin1String(unicode, errors);
-#ifdef HAVE_MBCS
- else if (strcmp(lower, "mbcs") == 0)
- return PyUnicode_EncodeCodePage(CP_ACP, unicode, errors);
+ else {
+ if (strcmp(lower, "ascii") == 0
+ || strcmp(lower, "us_ascii") == 0) {
+ return _PyUnicode_AsASCIIString(unicode, errors);
+ }
+#ifdef MS_WINDOWS
+ else if (strcmp(lower, "mbcs") == 0) {
+ return PyUnicode_EncodeCodePage(CP_ACP, unicode, errors);
+ }
#endif
- else if (strcmp(lower, "ascii") == 0)
- return _PyUnicode_AsASCIIString(unicode, errors);
+ else if (strcmp(lower, "latin1") == 0 ||
+ strcmp(lower, "latin_1") == 0 ||
+ strcmp(lower, "iso_8859_1") == 0 ||
+ strcmp(lower, "iso8859_1") == 0) {
+ return _PyUnicode_AsLatin1String(unicode, errors);
+ }
+ }
}
/* Encode via the codec registry */
@@ -3407,6 +3651,11 @@ PyUnicode_AsEncodedUnicode(PyObject *unicode,
goto onError;
}
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "PyUnicode_AsEncodedUnicode() is deprecated; "
+ "use PyCodec_Encode() to encode from str to str", 1) < 0)
+ return NULL;
+
if (encoding == NULL)
encoding = PyUnicode_GetDefaultEncoding();
@@ -3580,10 +3829,8 @@ PyUnicode_DecodeFSDefault(const char *s) {
PyObject*
PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
{
-#ifdef HAVE_MBCS
- return PyUnicode_DecodeMBCS(s, size, NULL);
-#elif defined(__APPLE__)
- return PyUnicode_DecodeUTF8Stateful(s, size, "surrogateescape", NULL);
+#if defined(__APPLE__)
+ return PyUnicode_DecodeUTF8Stateful(s, size, Py_FileSystemDefaultEncodeErrors, NULL);
#else
PyInterpreterState *interp = PyThreadState_GET()->interp;
/* Bootstrap check: if the filesystem codec is implemented in Python, we
@@ -3598,10 +3845,10 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) {
return PyUnicode_Decode(s, size,
Py_FileSystemDefaultEncoding,
- "surrogateescape");
+ Py_FileSystemDefaultEncodeErrors);
}
else {
- return PyUnicode_DecodeLocaleAndSize(s, size, "surrogateescape");
+ return PyUnicode_DecodeLocaleAndSize(s, size, Py_FileSystemDefaultEncodeErrors);
}
#endif
}
@@ -3610,6 +3857,7 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
int
PyUnicode_FSConverter(PyObject* arg, void* addr)
{
+ PyObject *path = NULL;
PyObject *output = NULL;
Py_ssize_t size;
void *data;
@@ -3618,24 +3866,22 @@ PyUnicode_FSConverter(PyObject* arg, void* addr)
*(PyObject**)addr = NULL;
return 1;
}
- if (PyBytes_Check(arg)) {
- output = arg;
- Py_INCREF(output);
+ path = PyOS_FSPath(arg);
+ if (path == NULL) {
+ return 0;
}
- else {
- arg = PyUnicode_FromObject(arg);
- if (!arg)
- return 0;
- output = PyUnicode_EncodeFSDefault(arg);
- Py_DECREF(arg);
- if (!output)
- return 0;
- if (!PyBytes_Check(output)) {
- Py_DECREF(output);
- PyErr_SetString(PyExc_TypeError, "encoder failed to return bytes");
+ if (PyBytes_Check(path)) {
+ output = path;
+ }
+ else { // PyOS_FSPath() guarantees its returned value is bytes or str.
+ output = PyUnicode_EncodeFSDefault(path);
+ Py_DECREF(path);
+ if (!output) {
return 0;
}
+ assert(PyBytes_Check(output));
}
+
size = PyBytes_GET_SIZE(output);
data = PyBytes_AS_STRING(output);
if ((size_t)size != strlen(data)) {
@@ -3651,36 +3897,60 @@ PyUnicode_FSConverter(PyObject* arg, void* addr)
int
PyUnicode_FSDecoder(PyObject* arg, void* addr)
{
+ int is_buffer = 0;
+ PyObject *path = NULL;
PyObject *output = NULL;
if (arg == NULL) {
Py_DECREF(*(PyObject**)addr);
return 1;
}
- if (PyUnicode_Check(arg)) {
- if (PyUnicode_READY(arg) == -1)
+
+ is_buffer = PyObject_CheckBuffer(arg);
+ if (!is_buffer) {
+ path = PyOS_FSPath(arg);
+ if (path == NULL) {
return 0;
- output = arg;
- Py_INCREF(output);
+ }
}
- else if (PyObject_CheckBuffer(arg)) {
- arg = PyBytes_FromObject(arg);
- if (!arg)
+ else {
+ path = arg;
+ Py_INCREF(arg);
+ }
+
+ if (PyUnicode_Check(path)) {
+ if (PyUnicode_READY(path) == -1) {
+ Py_DECREF(path);
return 0;
- output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(arg),
- PyBytes_GET_SIZE(arg));
- Py_DECREF(arg);
- if (!output)
+ }
+ output = path;
+ }
+ else if (PyBytes_Check(path) || is_buffer) {
+ PyObject *path_bytes = NULL;
+
+ if (!PyBytes_Check(path) &&
+ PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "path should be string, bytes, or os.PathLike, not %.200s",
+ Py_TYPE(arg)->tp_name)) {
+ Py_DECREF(path);
return 0;
- if (!PyUnicode_Check(output)) {
- Py_DECREF(output);
- PyErr_SetString(PyExc_TypeError, "decoder failed to return unicode");
+ }
+ path_bytes = PyBytes_FromObject(path);
+ Py_DECREF(path);
+ if (!path_bytes) {
+ return 0;
+ }
+ output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(path_bytes),
+ PyBytes_GET_SIZE(path_bytes));
+ Py_DECREF(path_bytes);
+ if (!output) {
return 0;
}
}
else {
PyErr_Format(PyExc_TypeError,
- "path should be string or bytes, not %.200s",
+ "path should be string, bytes, or os.PathLike, not %.200s",
Py_TYPE(arg)->tp_name);
+ Py_DECREF(path);
return 0;
}
if (PyUnicode_READY(output) == -1) {
@@ -3712,7 +3982,7 @@ PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize)
if (PyUnicode_UTF8(unicode) == NULL) {
assert(!PyUnicode_IS_COMPACT_ASCII(unicode));
- bytes = _PyUnicode_AsUTF8String(unicode, "strict");
+ bytes = _PyUnicode_AsUTF8String(unicode, NULL);
if (bytes == NULL)
return NULL;
_PyUnicode_UTF8(unicode) = PyObject_MALLOC(PyBytes_GET_SIZE(bytes) + 1);
@@ -3722,7 +3992,7 @@ PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize)
return NULL;
}
_PyUnicode_UTF8_LENGTH(unicode) = PyBytes_GET_SIZE(bytes);
- Py_MEMCPY(_PyUnicode_UTF8(unicode),
+ memcpy(_PyUnicode_UTF8(unicode),
PyBytes_AS_STRING(bytes),
_PyUnicode_UTF8_LENGTH(unicode) + 1);
Py_DECREF(bytes);
@@ -3962,7 +4232,7 @@ onError:
Py_CLEAR(*exceptionObject);
}
-#ifdef HAVE_MBCS
+#ifdef MS_WINDOWS
/* error handling callback helper:
build arguments, call the callback and check the arguments,
if no exception occurred, copy the replacement to the output
@@ -3978,7 +4248,7 @@ unicode_decode_call_errorhandler_wchar(
Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr,
PyObject **output, Py_ssize_t *outpos)
{
- static char *argparse = "O!n;decoding error handler must return (str, int) tuple";
+ static const char *argparse = "O!n;decoding error handler must return (str, int) tuple";
PyObject *restuple = NULL;
PyObject *repunicode = NULL;
@@ -4076,7 +4346,7 @@ unicode_decode_call_errorhandler_wchar(
Py_XDECREF(restuple);
return -1;
}
-#endif /* HAVE_MBCS */
+#endif /* MS_WINDOWS */
static int
unicode_decode_call_errorhandler_writer(
@@ -4086,7 +4356,7 @@ unicode_decode_call_errorhandler_writer(
Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr,
_PyUnicodeWriter *writer /* PyObject **output, Py_ssize_t *outpos */)
{
- static char *argparse = "O!n;decoding error handler must return (str, int) tuple";
+ static const char *argparse = "O!n;decoding error handler must return (str, int) tuple";
PyObject *restuple = NULL;
PyObject *repunicode = NULL;
@@ -4692,8 +4962,9 @@ PyUnicode_DecodeUTF8Stateful(const char *s,
Py_ssize_t startinpos;
Py_ssize_t endinpos;
const char *errmsg = "";
- PyObject *errorHandler = NULL;
+ PyObject *error_handler_obj = NULL;
PyObject *exc = NULL;
+ _Py_error_handler error_handler = _Py_ERROR_UNKNOWN;
if (size == 0) {
if (consumed)
@@ -4718,6 +4989,7 @@ PyUnicode_DecodeUTF8Stateful(const char *s,
while (s < end) {
Py_UCS4 ch;
int kind = writer.kind;
+
if (kind == PyUnicode_1BYTE_KIND) {
if (PyUnicode_IS_ASCII(writer.buffer))
ch = asciilib_utf8_decode(&s, end, writer.data, &writer.pos);
@@ -4756,33 +5028,65 @@ PyUnicode_DecodeUTF8Stateful(const char *s,
continue;
}
- if (unicode_decode_call_errorhandler_writer(
- errors, &errorHandler,
- "utf-8", errmsg,
- &starts, &end, &startinpos, &endinpos, &exc, &s,
- &writer))
- goto onError;
+ if (error_handler == _Py_ERROR_UNKNOWN)
+ error_handler = get_error_handler(errors);
+
+ switch (error_handler) {
+ case _Py_ERROR_IGNORE:
+ s += (endinpos - startinpos);
+ break;
+
+ case _Py_ERROR_REPLACE:
+ if (_PyUnicodeWriter_WriteCharInline(&writer, 0xfffd) < 0)
+ goto onError;
+ s += (endinpos - startinpos);
+ break;
+
+ case _Py_ERROR_SURROGATEESCAPE:
+ {
+ Py_ssize_t i;
+
+ if (_PyUnicodeWriter_PrepareKind(&writer, PyUnicode_2BYTE_KIND) < 0)
+ goto onError;
+ for (i=startinpos; i<endinpos; i++) {
+ ch = (Py_UCS4)(unsigned char)(starts[i]);
+ PyUnicode_WRITE(writer.kind, writer.data, writer.pos,
+ ch + 0xdc00);
+ writer.pos++;
+ }
+ s += (endinpos - startinpos);
+ break;
+ }
+
+ default:
+ if (unicode_decode_call_errorhandler_writer(
+ errors, &error_handler_obj,
+ "utf-8", errmsg,
+ &starts, &end, &startinpos, &endinpos, &exc, &s,
+ &writer))
+ goto onError;
+ }
}
End:
if (consumed)
*consumed = s - starts;
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
return _PyUnicodeWriter_Finish(&writer);
onError:
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
_PyUnicodeWriter_Dealloc(&writer);
return NULL;
}
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(__ANDROID__)
/* Simplified UTF-8 decoder using surrogateescape error handler,
- used to decode the command line arguments on Mac OS X.
+ used to decode the command line arguments on Mac OS X and Android.
Return a pointer to a newly allocated wide character string (use
PyMem_RawFree() to free the memory), or NULL on memory allocation error. */
@@ -4833,7 +5137,7 @@ _Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size)
return unicode;
}
-#endif /* __APPLE__ */
+#endif /* __APPLE__ or __ANDROID__ */
/* Primary internal function which creates utf8 encoded bytes objects.
@@ -5065,7 +5369,7 @@ _PyUnicode_EncodeUTF32(PyObject *str,
const void *data;
Py_ssize_t len;
PyObject *v;
- PY_UINT32_T *out;
+ uint32_t *out;
#if PY_LITTLE_ENDIAN
int native_ordering = byteorder <= 0;
#else
@@ -5096,7 +5400,7 @@ _PyUnicode_EncodeUTF32(PyObject *str,
/* output buffer is 4-bytes aligned */
assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(v), 4));
- out = (PY_UINT32_T *)PyBytes_AS_STRING(v);
+ out = (uint32_t *)PyBytes_AS_STRING(v);
if (byteorder == 0)
*out++ = 0xFEFF;
if (len == 0)
@@ -5162,7 +5466,7 @@ _PyUnicode_EncodeUTF32(PyObject *str,
/* four bytes are reserved for each surrogate */
if (moreunits > 1) {
- Py_ssize_t outpos = out - (PY_UINT32_T*) PyBytes_AS_STRING(v);
+ Py_ssize_t outpos = out - (uint32_t*) PyBytes_AS_STRING(v);
Py_ssize_t morebytes = 4 * (moreunits - 1);
if (PyBytes_GET_SIZE(v) > PY_SSIZE_T_MAX - morebytes) {
/* integer overflow */
@@ -5171,11 +5475,11 @@ _PyUnicode_EncodeUTF32(PyObject *str,
}
if (_PyBytes_Resize(&v, PyBytes_GET_SIZE(v) + morebytes) < 0)
goto error;
- out = (PY_UINT32_T*) PyBytes_AS_STRING(v) + outpos;
+ out = (uint32_t*) PyBytes_AS_STRING(v) + outpos;
}
if (PyBytes_Check(rep)) {
- Py_MEMCPY(out, PyBytes_AS_STRING(rep), repsize);
+ memcpy(out, PyBytes_AS_STRING(rep), repsize);
out += moreunits;
} else /* rep is unicode */ {
assert(PyUnicode_KIND(rep) == PyUnicode_1BYTE_KIND);
@@ -5426,36 +5730,45 @@ _PyUnicode_EncodeUTF16(PyObject *str,
if (kind == PyUnicode_4BYTE_KIND) {
const Py_UCS4 *in = (const Py_UCS4 *)data;
const Py_UCS4 *end = in + len;
- while (in < end)
- if (*in++ >= 0x10000)
+ while (in < end) {
+ if (*in++ >= 0x10000) {
pairs++;
+ }
+ }
}
- if (len > PY_SSIZE_T_MAX / 2 - pairs - (byteorder == 0))
+ if (len > PY_SSIZE_T_MAX / 2 - pairs - (byteorder == 0)) {
return PyErr_NoMemory();
+ }
nsize = len + pairs + (byteorder == 0);
v = PyBytes_FromStringAndSize(NULL, nsize * 2);
- if (v == NULL)
+ if (v == NULL) {
return NULL;
+ }
/* output buffer is 2-bytes aligned */
assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(v), 2));
out = (unsigned short *)PyBytes_AS_STRING(v);
- if (byteorder == 0)
+ if (byteorder == 0) {
*out++ = 0xFEFF;
- if (len == 0)
+ }
+ if (len == 0) {
goto done;
+ }
if (kind == PyUnicode_1BYTE_KIND) {
ucs1lib_utf16_encode((const Py_UCS1 *)data, len, &out, native_ordering);
goto done;
}
- if (byteorder < 0)
+ if (byteorder < 0) {
encoding = "utf-16-le";
- else if (byteorder > 0)
+ }
+ else if (byteorder > 0) {
encoding = "utf-16-be";
- else
+ }
+ else {
encoding = "utf-16";
+ }
pos = 0;
while (pos < len) {
@@ -5518,7 +5831,7 @@ _PyUnicode_EncodeUTF16(PyObject *str,
}
if (PyBytes_Check(rep)) {
- Py_MEMCPY(out, PyBytes_AS_STRING(rep), repsize);
+ memcpy(out, PyBytes_AS_STRING(rep), repsize);
out += moreunits;
} else /* rep is unicode */ {
assert(PyUnicode_KIND(rep) == PyUnicode_1BYTE_KIND);
@@ -5571,281 +5884,228 @@ PyUnicode_AsUTF16String(PyObject *unicode)
/* --- Unicode Escape Codec ----------------------------------------------- */
-/* Helper function for PyUnicode_DecodeUnicodeEscape, determines
- if all the escapes in the string make it still a valid ASCII string.
- Returns -1 if any escapes were found which cause the string to
- pop out of ASCII range. Otherwise returns the length of the
- required buffer to hold the string.
- */
-static Py_ssize_t
-length_of_escaped_ascii_string(const char *s, Py_ssize_t size)
-{
- const unsigned char *p = (const unsigned char *)s;
- const unsigned char *end = p + size;
- Py_ssize_t length = 0;
-
- if (size < 0)
- return -1;
-
- for (; p < end; ++p) {
- if (*p > 127) {
- /* Non-ASCII */
- return -1;
- }
- else if (*p != '\\') {
- /* Normal character */
- ++length;
- }
- else {
- /* Backslash-escape, check next char */
- ++p;
- /* Escape sequence reaches till end of string or
- non-ASCII follow-up. */
- if (p >= end || *p > 127)
- return -1;
- switch (*p) {
- case '\n':
- /* backslash + \n result in zero characters */
- break;
- case '\\': case '\'': case '\"':
- case 'b': case 'f': case 't':
- case 'n': case 'r': case 'v': case 'a':
- ++length;
- break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case 'x': case 'u': case 'U': case 'N':
- /* these do not guarantee ASCII characters */
- return -1;
- default:
- /* count the backslash + the other character */
- length += 2;
- }
- }
- }
- return length;
-}
-
static _PyUnicode_Name_CAPI *ucnhash_CAPI = NULL;
PyObject *
-PyUnicode_DecodeUnicodeEscape(const char *s,
- Py_ssize_t size,
- const char *errors)
+_PyUnicode_DecodeUnicodeEscape(const char *s,
+ Py_ssize_t size,
+ const char *errors,
+ const char **first_invalid_escape)
{
const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
_PyUnicodeWriter writer;
const char *end;
- char* message;
- Py_UCS4 chr = 0xffffffff; /* in case 'getcode' messes up */
PyObject *errorHandler = NULL;
PyObject *exc = NULL;
- Py_ssize_t len;
- len = length_of_escaped_ascii_string(s, size);
- if (len == 0)
- _Py_RETURN_UNICODE_EMPTY();
+ // so we can remember if we've seen an invalid escape char or not
+ *first_invalid_escape = NULL;
- /* After length_of_escaped_ascii_string() there are two alternatives,
- either the string is pure ASCII with named escapes like \n, etc.
- and we determined it's exact size (common case)
- or it contains \x, \u, ... escape sequences. then we create a
- legacy wchar string and resize it at the end of this function. */
- _PyUnicodeWriter_Init(&writer);
- if (len > 0) {
- writer.min_length = len;
+ if (size == 0) {
+ _Py_RETURN_UNICODE_EMPTY();
}
- else {
- /* Escaped strings will always be longer than the resulting
- Unicode string, so we start with size here and then reduce the
- length after conversion to the true value.
- (but if the error callback returns a long replacement string
- we'll have to allocate more space) */
- writer.min_length = size;
+ /* Escaped strings will always be longer than the resulting
+ Unicode string, so we start with size here and then reduce the
+ length after conversion to the true value.
+ (but if the error callback returns a long replacement string
+ we'll have to allocate more space) */
+ _PyUnicodeWriter_Init(&writer);
+ writer.min_length = size;
+ if (_PyUnicodeWriter_Prepare(&writer, size, 127) < 0) {
+ goto onError;
}
- if (size == 0)
- return _PyUnicodeWriter_Finish(&writer);
end = s + size;
-
while (s < end) {
- unsigned char c;
- Py_UCS4 x;
- int digits;
+ unsigned char c = (unsigned char) *s++;
+ Py_UCS4 ch;
+ int count;
+ Py_ssize_t startinpos;
+ Py_ssize_t endinpos;
+ const char *message;
+
+#define WRITE_ASCII_CHAR(ch) \
+ do { \
+ assert(ch <= 127); \
+ assert(writer.pos < writer.size); \
+ PyUnicode_WRITE(writer.kind, writer.data, writer.pos++, ch); \
+ } while(0)
+
+#define WRITE_CHAR(ch) \
+ do { \
+ if (ch <= writer.maxchar) { \
+ assert(writer.pos < writer.size); \
+ PyUnicode_WRITE(writer.kind, writer.data, writer.pos++, ch); \
+ } \
+ else if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) { \
+ goto onError; \
+ } \
+ } while(0)
/* Non-escape characters are interpreted as Unicode ordinals */
- if (*s != '\\') {
- x = (unsigned char)*s;
- s++;
- if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0)
- goto onError;
+ if (c != '\\') {
+ WRITE_CHAR(c);
continue;
}
- startinpos = s-starts;
+ startinpos = s - starts - 1;
/* \ - Escapes */
- s++;
- c = *s++;
- if (s > end)
- c = '\0'; /* Invalid after \ */
+ if (s >= end) {
+ message = "\\ at end of string";
+ goto error;
+ }
+ c = (unsigned char) *s++;
+ assert(writer.pos < writer.size);
switch (c) {
/* \x escapes */
-#define WRITECHAR(ch) \
- do { \
- if (_PyUnicodeWriter_WriteCharInline(&writer, (ch)) < 0) \
- goto onError; \
- } while(0)
-
- case '\n': break;
- case '\\': WRITECHAR('\\'); break;
- case '\'': WRITECHAR('\''); break;
- case '\"': WRITECHAR('\"'); break;
- case 'b': WRITECHAR('\b'); break;
+ case '\n': continue;
+ case '\\': WRITE_ASCII_CHAR('\\'); continue;
+ case '\'': WRITE_ASCII_CHAR('\''); continue;
+ case '\"': WRITE_ASCII_CHAR('\"'); continue;
+ case 'b': WRITE_ASCII_CHAR('\b'); continue;
/* FF */
- case 'f': WRITECHAR('\014'); break;
- case 't': WRITECHAR('\t'); break;
- case 'n': WRITECHAR('\n'); break;
- case 'r': WRITECHAR('\r'); break;
+ case 'f': WRITE_ASCII_CHAR('\014'); continue;
+ case 't': WRITE_ASCII_CHAR('\t'); continue;
+ case 'n': WRITE_ASCII_CHAR('\n'); continue;
+ case 'r': WRITE_ASCII_CHAR('\r'); continue;
/* VT */
- case 'v': WRITECHAR('\013'); break;
+ case 'v': WRITE_ASCII_CHAR('\013'); continue;
/* BEL, not classic C */
- case 'a': WRITECHAR('\007'); break;
+ case 'a': WRITE_ASCII_CHAR('\007'); continue;
/* \OOO (octal) escapes */
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
- x = s[-1] - '0';
+ ch = c - '0';
if (s < end && '0' <= *s && *s <= '7') {
- x = (x<<3) + *s++ - '0';
- if (s < end && '0' <= *s && *s <= '7')
- x = (x<<3) + *s++ - '0';
+ ch = (ch<<3) + *s++ - '0';
+ if (s < end && '0' <= *s && *s <= '7') {
+ ch = (ch<<3) + *s++ - '0';
+ }
}
- WRITECHAR(x);
- break;
+ WRITE_CHAR(ch);
+ continue;
/* hex escapes */
/* \xXX */
case 'x':
- digits = 2;
+ count = 2;
message = "truncated \\xXX escape";
goto hexescape;
/* \uXXXX */
case 'u':
- digits = 4;
+ count = 4;
message = "truncated \\uXXXX escape";
goto hexescape;
/* \UXXXXXXXX */
case 'U':
- digits = 8;
+ count = 8;
message = "truncated \\UXXXXXXXX escape";
hexescape:
- chr = 0;
- if (end - s < digits) {
- /* count only hex digits */
- for (; s < end; ++s) {
- c = (unsigned char)*s;
- if (!Py_ISXDIGIT(c))
- goto error;
+ for (ch = 0; count && s < end; ++s, --count) {
+ c = (unsigned char)*s;
+ ch <<= 4;
+ if (c >= '0' && c <= '9') {
+ ch += c - '0';
+ }
+ else if (c >= 'a' && c <= 'f') {
+ ch += c - ('a' - 10);
+ }
+ else if (c >= 'A' && c <= 'F') {
+ ch += c - ('A' - 10);
+ }
+ else {
+ break;
}
- goto error;
}
- for (; digits--; ++s) {
- c = (unsigned char)*s;
- if (!Py_ISXDIGIT(c))
- goto error;
- chr = (chr<<4) & ~0xF;
- if (c >= '0' && c <= '9')
- chr += c - '0';
- else if (c >= 'a' && c <= 'f')
- chr += 10 + c - 'a';
- else
- chr += 10 + c - 'A';
+ if (count) {
+ goto error;
}
- if (chr == 0xffffffff && PyErr_Occurred())
- /* _decoding_error will have already written into the
- target buffer. */
- break;
- store:
- /* when we get here, chr is a 32-bit unicode character */
- message = "illegal Unicode character";
- if (chr > MAX_UNICODE)
+
+ /* when we get here, ch is a 32-bit unicode character */
+ if (ch > MAX_UNICODE) {
+ message = "illegal Unicode character";
goto error;
- WRITECHAR(chr);
- break;
+ }
+
+ WRITE_CHAR(ch);
+ continue;
/* \N{name} */
case 'N':
- message = "malformed \\N character escape";
if (ucnhash_CAPI == NULL) {
/* load the unicode data module */
ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCapsule_Import(
PyUnicodeData_CAPSULE_NAME, 1);
- if (ucnhash_CAPI == NULL)
- goto ucnhashError;
+ if (ucnhash_CAPI == NULL) {
+ PyErr_SetString(
+ PyExc_UnicodeError,
+ "\\N escapes not supported (can't load unicodedata module)"
+ );
+ goto onError;
+ }
}
+
+ message = "malformed \\N character escape";
if (*s == '{') {
- const char *start = s+1;
+ const char *start = ++s;
+ size_t namelen;
/* look for the closing brace */
- while (*s != '}' && s < end)
+ while (s < end && *s != '}')
s++;
- if (s > start && s < end && *s == '}') {
+ namelen = s - start;
+ if (namelen && s < end) {
/* found a name. look it up in the unicode database */
- message = "unknown Unicode character name";
s++;
- if (s - start - 1 <= INT_MAX &&
- ucnhash_CAPI->getcode(NULL, start, (int)(s-start-1),
- &chr, 0))
- goto store;
+ ch = 0xffffffff; /* in case 'getcode' messes up */
+ if (namelen <= INT_MAX &&
+ ucnhash_CAPI->getcode(NULL, start, (int)namelen,
+ &ch, 0)) {
+ assert(ch <= MAX_UNICODE);
+ WRITE_CHAR(ch);
+ continue;
+ }
+ message = "unknown Unicode character name";
}
}
goto error;
default:
- if (s > end) {
- message = "\\ at end of string";
- s--;
- goto error;
- }
- else {
- WRITECHAR('\\');
- WRITECHAR((unsigned char)s[-1]);
+ if (*first_invalid_escape == NULL) {
+ *first_invalid_escape = s-1; /* Back up one char, since we've
+ already incremented s. */
}
- break;
+ WRITE_ASCII_CHAR('\\');
+ WRITE_CHAR(c);
+ continue;
}
- continue;
error:
endinpos = s-starts;
+ writer.min_length = end - s + writer.pos;
if (unicode_decode_call_errorhandler_writer(
errors, &errorHandler,
"unicodeescape", message,
&starts, &end, &startinpos, &endinpos, &exc, &s,
- &writer))
+ &writer)) {
goto onError;
- continue;
+ }
+ if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) {
+ goto onError;
+ }
+
+#undef WRITE_ASCII_CHAR
+#undef WRITE_CHAR
}
-#undef WRITECHAR
Py_XDECREF(errorHandler);
Py_XDECREF(exc);
return _PyUnicodeWriter_Finish(&writer);
- ucnhashError:
- PyErr_SetString(
- PyExc_UnicodeError,
- "\\N escapes not supported (can't load unicodedata module)"
- );
- _PyUnicodeWriter_Dealloc(&writer);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-
onError:
_PyUnicodeWriter_Dealloc(&writer);
Py_XDECREF(errorHandler);
@@ -5853,12 +6113,28 @@ PyUnicode_DecodeUnicodeEscape(const char *s,
return NULL;
}
-/* Return a Unicode-Escape string version of the Unicode object.
-
- If quotes is true, the string is enclosed in u"" or u'' quotes as
- appropriate.
+PyObject *
+PyUnicode_DecodeUnicodeEscape(const char *s,
+ Py_ssize_t size,
+ const char *errors)
+{
+ const char *first_invalid_escape;
+ PyObject *result = _PyUnicode_DecodeUnicodeEscape(s, size, errors,
+ &first_invalid_escape);
+ if (result == NULL)
+ return NULL;
+ if (first_invalid_escape != NULL) {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "invalid escape sequence '\\%c'",
+ *first_invalid_escape) < 0) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ return result;
+}
-*/
+/* Return a Unicode-Escape string version of the Unicode object. */
PyObject *
PyUnicode_AsUnicodeEscapeString(PyObject *unicode)
@@ -5866,9 +6142,9 @@ PyUnicode_AsUnicodeEscapeString(PyObject *unicode)
Py_ssize_t i, len;
PyObject *repr;
char *p;
- int kind;
+ enum PyUnicode_Kind kind;
void *data;
- Py_ssize_t expandsize = 0;
+ Py_ssize_t expandsize;
/* Initial allocation is based on the longest-possible character
escape.
@@ -5882,60 +6158,70 @@ PyUnicode_AsUnicodeEscapeString(PyObject *unicode)
PyErr_BadArgument();
return NULL;
}
- if (PyUnicode_READY(unicode) == -1)
+ if (PyUnicode_READY(unicode) == -1) {
return NULL;
- len = PyUnicode_GET_LENGTH(unicode);
- kind = PyUnicode_KIND(unicode);
- data = PyUnicode_DATA(unicode);
- switch (kind) {
- case PyUnicode_1BYTE_KIND: expandsize = 4; break;
- case PyUnicode_2BYTE_KIND: expandsize = 6; break;
- case PyUnicode_4BYTE_KIND: expandsize = 10; break;
}
- if (len == 0)
+ len = PyUnicode_GET_LENGTH(unicode);
+ if (len == 0) {
return PyBytes_FromStringAndSize(NULL, 0);
+ }
- if (len > (PY_SSIZE_T_MAX - 2 - 1) / expandsize)
+ kind = PyUnicode_KIND(unicode);
+ data = PyUnicode_DATA(unicode);
+ /* 4 byte characters can take up 10 bytes, 2 byte characters can take up 6
+ bytes, and 1 byte characters 4. */
+ expandsize = kind * 2 + 2;
+ if (len > PY_SSIZE_T_MAX / expandsize) {
return PyErr_NoMemory();
-
- repr = PyBytes_FromStringAndSize(NULL,
- 2
- + expandsize*len
- + 1);
- if (repr == NULL)
+ }
+ repr = PyBytes_FromStringAndSize(NULL, expandsize * len);
+ if (repr == NULL) {
return NULL;
+ }
p = PyBytes_AS_STRING(repr);
-
for (i = 0; i < len; i++) {
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
- /* Escape backslashes */
- if (ch == '\\') {
- *p++ = '\\';
- *p++ = (char) ch;
- continue;
- }
+ /* U+0000-U+00ff range */
+ if (ch < 0x100) {
+ if (ch >= ' ' && ch < 127) {
+ if (ch != '\\') {
+ /* Copy printable US ASCII as-is */
+ *p++ = (char) ch;
+ }
+ /* Escape backslashes */
+ else {
+ *p++ = '\\';
+ *p++ = '\\';
+ }
+ }
- /* Map 21-bit characters to '\U00xxxxxx' */
- else if (ch >= 0x10000) {
- assert(ch <= MAX_UNICODE);
- *p++ = '\\';
- *p++ = 'U';
- *p++ = Py_hexdigits[(ch >> 28) & 0x0000000F];
- *p++ = Py_hexdigits[(ch >> 24) & 0x0000000F];
- *p++ = Py_hexdigits[(ch >> 20) & 0x0000000F];
- *p++ = Py_hexdigits[(ch >> 16) & 0x0000000F];
- *p++ = Py_hexdigits[(ch >> 12) & 0x0000000F];
- *p++ = Py_hexdigits[(ch >> 8) & 0x0000000F];
- *p++ = Py_hexdigits[(ch >> 4) & 0x0000000F];
- *p++ = Py_hexdigits[ch & 0x0000000F];
- continue;
- }
+ /* Map special whitespace to '\t', \n', '\r' */
+ else if (ch == '\t') {
+ *p++ = '\\';
+ *p++ = 't';
+ }
+ else if (ch == '\n') {
+ *p++ = '\\';
+ *p++ = 'n';
+ }
+ else if (ch == '\r') {
+ *p++ = '\\';
+ *p++ = 'r';
+ }
- /* Map 16-bit characters to '\uxxxx' */
- if (ch >= 256) {
+ /* Map non-printable US ASCII and 8-bit characters to '\xHH' */
+ else {
+ *p++ = '\\';
+ *p++ = 'x';
+ *p++ = Py_hexdigits[(ch >> 4) & 0x000F];
+ *p++ = Py_hexdigits[ch & 0x000F];
+ }
+ }
+ /* U+0100-U+ffff range: Map 16-bit characters to '\uHHHH' */
+ else if (ch < 0x10000) {
*p++ = '\\';
*p++ = 'u';
*p++ = Py_hexdigits[(ch >> 12) & 0x000F];
@@ -5943,37 +6229,28 @@ PyUnicode_AsUnicodeEscapeString(PyObject *unicode)
*p++ = Py_hexdigits[(ch >> 4) & 0x000F];
*p++ = Py_hexdigits[ch & 0x000F];
}
+ /* U+010000-U+10ffff range: Map 21-bit characters to '\U00HHHHHH' */
+ else {
- /* Map special whitespace to '\t', \n', '\r' */
- else if (ch == '\t') {
- *p++ = '\\';
- *p++ = 't';
- }
- else if (ch == '\n') {
- *p++ = '\\';
- *p++ = 'n';
- }
- else if (ch == '\r') {
- *p++ = '\\';
- *p++ = 'r';
- }
-
- /* Map non-printable US ASCII to '\xhh' */
- else if (ch < ' ' || ch >= 0x7F) {
+ /* Make sure that the first two digits are zero */
+ assert(ch <= MAX_UNICODE && MAX_UNICODE <= 0x10ffff);
*p++ = '\\';
- *p++ = 'x';
- *p++ = Py_hexdigits[(ch >> 4) & 0x000F];
- *p++ = Py_hexdigits[ch & 0x000F];
+ *p++ = 'U';
+ *p++ = '0';
+ *p++ = '0';
+ *p++ = Py_hexdigits[(ch >> 20) & 0x0000000F];
+ *p++ = Py_hexdigits[(ch >> 16) & 0x0000000F];
+ *p++ = Py_hexdigits[(ch >> 12) & 0x0000000F];
+ *p++ = Py_hexdigits[(ch >> 8) & 0x0000000F];
+ *p++ = Py_hexdigits[(ch >> 4) & 0x0000000F];
+ *p++ = Py_hexdigits[ch & 0x0000000F];
}
-
- /* Copy everything else as-is */
- else
- *p++ = (char) ch;
}
assert(p - PyBytes_AS_STRING(repr) > 0);
- if (_PyBytes_Resize(&repr, p - PyBytes_AS_STRING(repr)) < 0)
+ if (_PyBytes_Resize(&repr, p - PyBytes_AS_STRING(repr)) < 0) {
return NULL;
+ }
return repr;
}
@@ -5983,8 +6260,10 @@ PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s,
{
PyObject *result;
PyObject *tmp = PyUnicode_FromUnicode(s, size);
- if (tmp == NULL)
+ if (tmp == NULL) {
return NULL;
+ }
+
result = PyUnicode_AsUnicodeEscapeString(tmp);
Py_DECREF(tmp);
return result;
@@ -5998,95 +6277,107 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s,
const char *errors)
{
const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
_PyUnicodeWriter writer;
const char *end;
- const char *bs;
PyObject *errorHandler = NULL;
PyObject *exc = NULL;
- if (size == 0)
+ if (size == 0) {
_Py_RETURN_UNICODE_EMPTY();
+ }
/* Escaped strings will always be longer than the resulting
Unicode string, so we start with size here and then reduce the
length after conversion to the true value. (But decoding error
handler might have to resize the string) */
_PyUnicodeWriter_Init(&writer);
- writer.min_length = size;
+ writer.min_length = size;
+ if (_PyUnicodeWriter_Prepare(&writer, size, 127) < 0) {
+ goto onError;
+ }
end = s + size;
while (s < end) {
- unsigned char c;
- Py_UCS4 x;
- int i;
+ unsigned char c = (unsigned char) *s++;
+ Py_UCS4 ch;
int count;
+ Py_ssize_t startinpos;
+ Py_ssize_t endinpos;
+ const char *message;
+
+#define WRITE_CHAR(ch) \
+ do { \
+ if (ch <= writer.maxchar) { \
+ assert(writer.pos < writer.size); \
+ PyUnicode_WRITE(writer.kind, writer.data, writer.pos++, ch); \
+ } \
+ else if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) { \
+ goto onError; \
+ } \
+ } while(0)
/* Non-escape characters are interpreted as Unicode ordinals */
- if (*s != '\\') {
- x = (unsigned char)*s++;
- if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0)
- goto onError;
+ if (c != '\\' || s >= end) {
+ WRITE_CHAR(c);
continue;
}
- startinpos = s-starts;
- /* \u-escapes are only interpreted iff the number of leading
- backslashes if odd */
- bs = s;
- for (;s < end;) {
- if (*s != '\\')
- break;
- x = (unsigned char)*s++;
- if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0)
- goto onError;
+ c = (unsigned char) *s++;
+ if (c == 'u') {
+ count = 4;
+ message = "truncated \\uXXXX escape";
+ }
+ else if (c == 'U') {
+ count = 8;
+ message = "truncated \\UXXXXXXXX escape";
}
- if (((s - bs) & 1) == 0 ||
- s >= end ||
- (*s != 'u' && *s != 'U')) {
+ else {
+ assert(writer.pos < writer.size);
+ PyUnicode_WRITE(writer.kind, writer.data, writer.pos++, '\\');
+ WRITE_CHAR(c);
continue;
}
- writer.pos--;
- count = *s=='u' ? 4 : 8;
- s++;
+ startinpos = s - starts - 2;
- /* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */
- for (x = 0, i = 0; i < count; ++i, ++s) {
+ /* \uHHHH with 4 hex digits, \U00HHHHHH with 8 */
+ for (ch = 0; count && s < end; ++s, --count) {
c = (unsigned char)*s;
- if (!Py_ISXDIGIT(c)) {
- endinpos = s-starts;
- if (unicode_decode_call_errorhandler_writer(
- errors, &errorHandler,
- "rawunicodeescape", "truncated \\uXXXX",
- &starts, &end, &startinpos, &endinpos, &exc, &s,
- &writer))
- goto onError;
- goto nextByte;
+ ch <<= 4;
+ if (c >= '0' && c <= '9') {
+ ch += c - '0';
+ }
+ else if (c >= 'a' && c <= 'f') {
+ ch += c - ('a' - 10);
+ }
+ else if (c >= 'A' && c <= 'F') {
+ ch += c - ('A' - 10);
+ }
+ else {
+ break;
}
- x = (x<<4) & ~0xF;
- if (c >= '0' && c <= '9')
- x += c - '0';
- else if (c >= 'a' && c <= 'f')
- x += 10 + c - 'a';
- else
- x += 10 + c - 'A';
}
- if (x <= MAX_UNICODE) {
- if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0)
- goto onError;
+ if (!count) {
+ if (ch <= MAX_UNICODE) {
+ WRITE_CHAR(ch);
+ continue;
+ }
+ message = "\\Uxxxxxxxx out of range";
}
- else {
- endinpos = s-starts;
- if (unicode_decode_call_errorhandler_writer(
- errors, &errorHandler,
- "rawunicodeescape", "\\Uxxxxxxxx out of range",
- &starts, &end, &startinpos, &endinpos, &exc, &s,
- &writer))
- goto onError;
+
+ endinpos = s-starts;
+ writer.min_length = end - s + writer.pos;
+ if (unicode_decode_call_errorhandler_writer(
+ errors, &errorHandler,
+ "rawunicodeescape", message,
+ &starts, &end, &startinpos, &endinpos, &exc, &s,
+ &writer)) {
+ goto onError;
+ }
+ if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) {
+ goto onError;
}
- nextByte:
- ;
+
+#undef WRITE_CHAR
}
Py_XDECREF(errorHandler);
Py_XDECREF(exc);
@@ -6097,6 +6388,7 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s,
Py_XDECREF(errorHandler);
Py_XDECREF(exc);
return NULL;
+
}
@@ -6105,7 +6397,6 @@ PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
{
PyObject *repr;
char *p;
- char *q;
Py_ssize_t expandsize, pos;
int kind;
void *data;
@@ -6115,58 +6406,68 @@ PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
PyErr_BadArgument();
return NULL;
}
- if (PyUnicode_READY(unicode) == -1)
+ if (PyUnicode_READY(unicode) == -1) {
return NULL;
+ }
kind = PyUnicode_KIND(unicode);
data = PyUnicode_DATA(unicode);
len = PyUnicode_GET_LENGTH(unicode);
+ if (kind == PyUnicode_1BYTE_KIND) {
+ return PyBytes_FromStringAndSize(data, len);
+ }
+
/* 4 byte characters can take up 10 bytes, 2 byte characters can take up 6
bytes, and 1 byte characters 4. */
expandsize = kind * 2 + 2;
- if (len > PY_SSIZE_T_MAX / expandsize)
+ if (len > PY_SSIZE_T_MAX / expandsize) {
return PyErr_NoMemory();
-
+ }
repr = PyBytes_FromStringAndSize(NULL, expandsize * len);
- if (repr == NULL)
+ if (repr == NULL) {
return NULL;
- if (len == 0)
+ }
+ if (len == 0) {
return repr;
+ }
- p = q = PyBytes_AS_STRING(repr);
+ p = PyBytes_AS_STRING(repr);
for (pos = 0; pos < len; pos++) {
Py_UCS4 ch = PyUnicode_READ(kind, data, pos);
- /* Map 32-bit characters to '\Uxxxxxxxx' */
- if (ch >= 0x10000) {
- assert(ch <= MAX_UNICODE);
+
+ /* U+0000-U+00ff range: Copy 8-bit characters as-is */
+ if (ch < 0x100) {
+ *p++ = (char) ch;
+ }
+ /* U+0000-U+00ff range: Map 16-bit characters to '\uHHHH' */
+ else if (ch < 0x10000) {
*p++ = '\\';
- *p++ = 'U';
- *p++ = Py_hexdigits[(ch >> 28) & 0xf];
- *p++ = Py_hexdigits[(ch >> 24) & 0xf];
- *p++ = Py_hexdigits[(ch >> 20) & 0xf];
- *p++ = Py_hexdigits[(ch >> 16) & 0xf];
+ *p++ = 'u';
*p++ = Py_hexdigits[(ch >> 12) & 0xf];
*p++ = Py_hexdigits[(ch >> 8) & 0xf];
*p++ = Py_hexdigits[(ch >> 4) & 0xf];
*p++ = Py_hexdigits[ch & 15];
}
- /* Map 16-bit characters to '\uxxxx' */
- else if (ch >= 256) {
+ /* U+010000-U+10ffff range: Map 32-bit characters to '\U00HHHHHH' */
+ else {
+ assert(ch <= MAX_UNICODE && MAX_UNICODE <= 0x10ffff);
*p++ = '\\';
- *p++ = 'u';
+ *p++ = 'U';
+ *p++ = '0';
+ *p++ = '0';
+ *p++ = Py_hexdigits[(ch >> 20) & 0xf];
+ *p++ = Py_hexdigits[(ch >> 16) & 0xf];
*p++ = Py_hexdigits[(ch >> 12) & 0xf];
*p++ = Py_hexdigits[(ch >> 8) & 0xf];
*p++ = Py_hexdigits[(ch >> 4) & 0xf];
*p++ = Py_hexdigits[ch & 15];
}
- /* Copy everything else as-is */
- else
- *p++ = (char) ch;
}
- assert(p > q);
- if (_PyBytes_Resize(&repr, p - q) < 0)
+ assert(p > PyBytes_AS_STRING(repr));
+ if (_PyBytes_Resize(&repr, p - PyBytes_AS_STRING(repr)) < 0) {
return NULL;
+ }
return repr;
}
@@ -6344,7 +6645,7 @@ unicode_encode_call_errorhandler(const char *errors,
Py_ssize_t startpos, Py_ssize_t endpos,
Py_ssize_t *newpos)
{
- static char *argparse = "On;encoding error handler must return (str/bytes, int) tuple";
+ static const char *argparse = "On;encoding error handler must return (str/bytes, int) tuple";
Py_ssize_t len;
PyObject *restuple;
PyObject *resunicode;
@@ -6398,25 +6699,22 @@ unicode_encode_call_errorhandler(const char *errors,
static PyObject *
unicode_encode_ucs1(PyObject *unicode,
const char *errors,
- unsigned int limit)
+ const Py_UCS4 limit)
{
/* input state */
Py_ssize_t pos=0, size;
int kind;
void *data;
- /* output object */
- PyObject *res;
/* pointer into the output */
char *str;
- /* current output position */
- Py_ssize_t ressize;
const char *encoding = (limit == 256) ? "latin-1" : "ascii";
const char *reason = (limit == 256) ? "ordinal not in range(256)" : "ordinal not in range(128)";
- PyObject *errorHandler = NULL;
+ PyObject *error_handler_obj = NULL;
PyObject *exc = NULL;
- /* the following variable is used for caching string comparisons
- * -1=not initialized, 0=unknown, 1=strict, 2=replace, 3=ignore, 4=xmlcharrefreplace */
- int known_errorHandler = -1;
+ _Py_error_handler error_handler = _Py_ERROR_UNKNOWN;
+ PyObject *rep = NULL;
+ /* output object */
+ _PyBytesWriter writer;
if (PyUnicode_READY(unicode) == -1)
return NULL;
@@ -6427,186 +6725,157 @@ unicode_encode_ucs1(PyObject *unicode,
replacements, if we need more, we'll resize */
if (size == 0)
return PyBytes_FromStringAndSize(NULL, 0);
- res = PyBytes_FromStringAndSize(NULL, size);
- if (res == NULL)
+
+ _PyBytesWriter_Init(&writer);
+ str = _PyBytesWriter_Alloc(&writer, size);
+ if (str == NULL)
return NULL;
- str = PyBytes_AS_STRING(res);
- ressize = size;
while (pos < size) {
- Py_UCS4 c = PyUnicode_READ(kind, data, pos);
+ Py_UCS4 ch = PyUnicode_READ(kind, data, pos);
/* can we encode this? */
- if (c<limit) {
+ if (ch < limit) {
/* no overflow check, because we know that the space is enough */
- *str++ = (char)c;
+ *str++ = (char)ch;
++pos;
}
else {
- Py_ssize_t requiredsize;
- PyObject *repunicode;
- Py_ssize_t repsize, newpos, respos, i;
+ Py_ssize_t newpos, i;
/* startpos for collecting unencodable chars */
Py_ssize_t collstart = pos;
- Py_ssize_t collend = pos;
+ Py_ssize_t collend = collstart + 1;
/* find all unecodable characters */
+
while ((collend < size) && (PyUnicode_READ(kind, data, collend) >= limit))
++collend;
+
+ /* Only overallocate the buffer if it's not the last write */
+ writer.overallocate = (collend < size);
+
/* cache callback name lookup (if not done yet, i.e. it's the first error) */
- if (known_errorHandler==-1) {
- if ((errors==NULL) || (!strcmp(errors, "strict")))
- known_errorHandler = 1;
- else if (!strcmp(errors, "replace"))
- known_errorHandler = 2;
- else if (!strcmp(errors, "ignore"))
- known_errorHandler = 3;
- else if (!strcmp(errors, "xmlcharrefreplace"))
- known_errorHandler = 4;
- else
- known_errorHandler = 0;
- }
- switch (known_errorHandler) {
- case 1: /* strict */
+ if (error_handler == _Py_ERROR_UNKNOWN)
+ error_handler = get_error_handler(errors);
+
+ switch (error_handler) {
+ case _Py_ERROR_STRICT:
raise_encode_exception(&exc, encoding, unicode, collstart, collend, reason);
goto onError;
- case 2: /* replace */
- while (collstart++ < collend)
- *str++ = '?'; /* fall through */
- case 3: /* ignore */
+
+ case _Py_ERROR_REPLACE:
+ memset(str, '?', collend - collstart);
+ str += (collend - collstart);
+ /* fall through ignore error handler */
+ case _Py_ERROR_IGNORE:
+ pos = collend;
+ break;
+
+ case _Py_ERROR_BACKSLASHREPLACE:
+ /* subtract preallocated bytes */
+ writer.min_size -= (collend - collstart);
+ str = backslashreplace(&writer, str,
+ unicode, collstart, collend);
+ if (str == NULL)
+ goto onError;
pos = collend;
break;
- case 4: /* xmlcharrefreplace */
- respos = str - PyBytes_AS_STRING(res);
- requiredsize = respos;
- /* determine replacement size */
+
+ case _Py_ERROR_XMLCHARREFREPLACE:
+ /* subtract preallocated bytes */
+ writer.min_size -= (collend - collstart);
+ str = xmlcharrefreplace(&writer, str,
+ unicode, collstart, collend);
+ if (str == NULL)
+ goto onError;
+ pos = collend;
+ break;
+
+ case _Py_ERROR_SURROGATEESCAPE:
for (i = collstart; i < collend; ++i) {
- Py_UCS4 ch = PyUnicode_READ(kind, data, i);
- Py_ssize_t incr;
- if (ch < 10)
- incr = 2+1+1;
- else if (ch < 100)
- incr = 2+2+1;
- else if (ch < 1000)
- incr = 2+3+1;
- else if (ch < 10000)
- incr = 2+4+1;
- else if (ch < 100000)
- incr = 2+5+1;
- else if (ch < 1000000)
- incr = 2+6+1;
- else {
- assert(ch <= MAX_UNICODE);
- incr = 2+7+1;
+ ch = PyUnicode_READ(kind, data, i);
+ if (ch < 0xdc80 || 0xdcff < ch) {
+ /* Not a UTF-8b surrogate */
+ break;
}
- if (requiredsize > PY_SSIZE_T_MAX - incr)
- goto overflow;
- requiredsize += incr;
- }
- if (requiredsize > PY_SSIZE_T_MAX - (size - collend))
- goto overflow;
- requiredsize += size - collend;
- if (requiredsize > ressize) {
- if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize)
- requiredsize = 2*ressize;
- if (_PyBytes_Resize(&res, requiredsize))
- goto onError;
- str = PyBytes_AS_STRING(res) + respos;
- ressize = requiredsize;
- }
- /* generate replacement */
- for (i = collstart; i < collend; ++i) {
- str += sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i));
+ *str++ = (char)(ch - 0xdc00);
+ ++pos;
}
- pos = collend;
- break;
+ if (i >= collend)
+ break;
+ collstart = pos;
+ assert(collstart != collend);
+ /* fallback to general error handling */
+
default:
- repunicode = unicode_encode_call_errorhandler(errors, &errorHandler,
- encoding, reason, unicode, &exc,
- collstart, collend, &newpos);
- if (repunicode == NULL || (PyUnicode_Check(repunicode) &&
- PyUnicode_READY(repunicode) == -1))
+ rep = unicode_encode_call_errorhandler(errors, &error_handler_obj,
+ encoding, reason, unicode, &exc,
+ collstart, collend, &newpos);
+ if (rep == NULL)
goto onError;
- if (PyBytes_Check(repunicode)) {
+
+ /* subtract preallocated bytes */
+ writer.min_size -= 1;
+
+ if (PyBytes_Check(rep)) {
/* Directly copy bytes result to output. */
- repsize = PyBytes_Size(repunicode);
- if (repsize > 1) {
- /* Make room for all additional bytes. */
- respos = str - PyBytes_AS_STRING(res);
- if (ressize > PY_SSIZE_T_MAX - repsize - 1) {
- Py_DECREF(repunicode);
- goto overflow;
- }
- if (_PyBytes_Resize(&res, ressize+repsize-1)) {
- Py_DECREF(repunicode);
- goto onError;
- }
- str = PyBytes_AS_STRING(res) + respos;
- ressize += repsize-1;
- }
- memcpy(str, PyBytes_AsString(repunicode), repsize);
- str += repsize;
- pos = newpos;
- Py_DECREF(repunicode);
- break;
- }
- /* need more space? (at least enough for what we
- have+the replacement+the rest of the string, so
- we won't have to check space for encodable characters) */
- respos = str - PyBytes_AS_STRING(res);
- repsize = PyUnicode_GET_LENGTH(repunicode);
- requiredsize = respos;
- if (requiredsize > PY_SSIZE_T_MAX - repsize)
- goto overflow;
- requiredsize += repsize;
- if (requiredsize > PY_SSIZE_T_MAX - (size - collend))
- goto overflow;
- requiredsize += size - collend;
- if (requiredsize > ressize) {
- if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize)
- requiredsize = 2*ressize;
- if (_PyBytes_Resize(&res, requiredsize)) {
- Py_DECREF(repunicode);
+ str = _PyBytesWriter_WriteBytes(&writer, str,
+ PyBytes_AS_STRING(rep),
+ PyBytes_GET_SIZE(rep));
+ if (str == NULL)
goto onError;
- }
- str = PyBytes_AS_STRING(res) + respos;
- ressize = requiredsize;
}
- /* check if there is anything unencodable in the replacement
- and copy it to the output */
- for (i = 0; repsize-->0; ++i, ++str) {
- c = PyUnicode_READ_CHAR(repunicode, i);
- if (c >= limit) {
- raise_encode_exception(&exc, encoding, unicode,
- pos, pos+1, reason);
- Py_DECREF(repunicode);
+ else {
+ assert(PyUnicode_Check(rep));
+
+ if (PyUnicode_READY(rep) < 0)
goto onError;
+
+ if (PyUnicode_IS_ASCII(rep)) {
+ /* Fast path: all characters are smaller than limit */
+ assert(limit >= 128);
+ assert(PyUnicode_KIND(rep) == PyUnicode_1BYTE_KIND);
+ str = _PyBytesWriter_WriteBytes(&writer, str,
+ PyUnicode_DATA(rep),
+ PyUnicode_GET_LENGTH(rep));
+ }
+ else {
+ Py_ssize_t repsize = PyUnicode_GET_LENGTH(rep);
+
+ str = _PyBytesWriter_Prepare(&writer, str, repsize);
+ if (str == NULL)
+ goto onError;
+
+ /* check if there is anything unencodable in the
+ replacement and copy it to the output */
+ for (i = 0; repsize-->0; ++i, ++str) {
+ ch = PyUnicode_READ_CHAR(rep, i);
+ if (ch >= limit) {
+ raise_encode_exception(&exc, encoding, unicode,
+ pos, pos+1, reason);
+ goto onError;
+ }
+ *str = (char)ch;
+ }
}
- *str = (char)c;
}
pos = newpos;
- Py_DECREF(repunicode);
+ Py_CLEAR(rep);
}
+
+ /* If overallocation was disabled, ensure that it was the last
+ write. Otherwise, we missed an optimization */
+ assert(writer.overallocate || pos == size);
}
}
- /* Resize if we allocated to much */
- size = str - PyBytes_AS_STRING(res);
- if (size < ressize) { /* If this falls res will be NULL */
- assert(size >= 0);
- if (_PyBytes_Resize(&res, size) < 0)
- goto onError;
- }
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
- return res;
-
- overflow:
- PyErr_SetString(PyExc_OverflowError,
- "encoded result is too long for a Python string");
+ return _PyBytesWriter_Finish(&writer, str);
onError:
- Py_XDECREF(res);
- Py_XDECREF(errorHandler);
+ Py_XDECREF(rep);
+ _PyBytesWriter_Dealloc(&writer);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
return NULL;
}
@@ -6666,8 +6935,9 @@ PyUnicode_DecodeASCII(const char *s,
Py_ssize_t endinpos;
Py_ssize_t outpos;
const char *e;
- PyObject *errorHandler = NULL;
+ PyObject *error_handler_obj = NULL;
PyObject *exc = NULL;
+ _Py_error_handler error_handler = _Py_ERROR_UNKNOWN;
if (size == 0)
_Py_RETURN_UNICODE_EMPTY();
@@ -6696,12 +6966,42 @@ PyUnicode_DecodeASCII(const char *s,
PyUnicode_WRITE(kind, data, writer.pos, c);
writer.pos++;
++s;
+ continue;
}
- else {
+
+ /* byte outsize range 0x00..0x7f: call the error handler */
+
+ if (error_handler == _Py_ERROR_UNKNOWN)
+ error_handler = get_error_handler(errors);
+
+ switch (error_handler)
+ {
+ case _Py_ERROR_REPLACE:
+ case _Py_ERROR_SURROGATEESCAPE:
+ /* Fast-path: the error handler only writes one character,
+ but we may switch to UCS2 at the first write */
+ if (_PyUnicodeWriter_PrepareKind(&writer, PyUnicode_2BYTE_KIND) < 0)
+ goto onError;
+ kind = writer.kind;
+ data = writer.data;
+
+ if (error_handler == _Py_ERROR_REPLACE)
+ PyUnicode_WRITE(kind, data, writer.pos, 0xfffd);
+ else
+ PyUnicode_WRITE(kind, data, writer.pos, c + 0xdc00);
+ writer.pos++;
+ ++s;
+ break;
+
+ case _Py_ERROR_IGNORE:
+ ++s;
+ break;
+
+ default:
startinpos = s-starts;
endinpos = startinpos + 1;
if (unicode_decode_call_errorhandler_writer(
- errors, &errorHandler,
+ errors, &error_handler_obj,
"ascii", "ordinal not in range(128)",
&starts, &e, &startinpos, &endinpos, &exc, &s,
&writer))
@@ -6710,13 +7010,13 @@ PyUnicode_DecodeASCII(const char *s,
data = writer.data;
}
}
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
return _PyUnicodeWriter_Finish(&writer);
onError:
_PyUnicodeWriter_Dealloc(&writer);
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
Py_XDECREF(exc);
return NULL;
}
@@ -6759,7 +7059,7 @@ PyUnicode_AsASCIIString(PyObject *unicode)
return _PyUnicode_AsASCIIString(unicode, NULL);
}
-#ifdef HAVE_MBCS
+#ifdef MS_WINDOWS
/* --- MBCS codecs for Windows -------------------------------------------- */
@@ -6771,7 +7071,7 @@ PyUnicode_AsASCIIString(PyObject *unicode)
# define WC_ERR_INVALID_CHARS 0x0080
#endif
-static char*
+static const char*
code_page_name(UINT code_page, PyObject **obj)
{
*obj = NULL;
@@ -6879,7 +7179,7 @@ decode_code_page_errors(UINT code_page,
PyObject *errorHandler = NULL;
PyObject *exc = NULL;
PyObject *encoding_obj = NULL;
- char *encoding;
+ const char *encoding;
DWORD err;
int ret = -1;
@@ -7115,7 +7415,6 @@ encode_code_page_strict(UINT code_page, PyObject **outbytes,
BOOL usedDefaultChar = FALSE;
BOOL *pusedDefaultChar = &usedDefaultChar;
int outsize;
- PyObject *exc = NULL;
wchar_t *p;
Py_ssize_t size;
const DWORD flags = encode_code_page_flags(code_page, NULL);
@@ -7224,7 +7523,7 @@ encode_code_page_errors(UINT code_page, PyObject **outbytes,
PyObject *errorHandler = NULL;
PyObject *exc = NULL;
PyObject *encoding_obj = NULL;
- char *encoding;
+ const char *encoding;
Py_ssize_t newpos, newoutsize;
PyObject *rep;
int ret = -1;
@@ -7479,7 +7778,7 @@ PyUnicode_AsMBCSString(PyObject *unicode)
#undef NEED_RETRY
-#endif /* HAVE_MBCS */
+#endif /* MS_WINDOWS */
/* --- Character Mapping Codec -------------------------------------------- */
@@ -8082,7 +8381,7 @@ static int
charmap_encoding_error(
PyObject *unicode, Py_ssize_t *inpos, PyObject *mapping,
PyObject **exceptionObject,
- int *known_errorHandler, PyObject **errorHandler, const char *errors,
+ _Py_error_handler *error_handler, PyObject **error_handler_obj, const char *errors,
PyObject **res, Py_ssize_t *respos)
{
PyObject *repunicode = NULL; /* initialize to prevent gcc warning */
@@ -8129,23 +8428,15 @@ charmap_encoding_error(
}
/* cache callback name lookup
* (if not done yet, i.e. it's the first error) */
- if (*known_errorHandler==-1) {
- if ((errors==NULL) || (!strcmp(errors, "strict")))
- *known_errorHandler = 1;
- else if (!strcmp(errors, "replace"))
- *known_errorHandler = 2;
- else if (!strcmp(errors, "ignore"))
- *known_errorHandler = 3;
- else if (!strcmp(errors, "xmlcharrefreplace"))
- *known_errorHandler = 4;
- else
- *known_errorHandler = 0;
- }
- switch (*known_errorHandler) {
- case 1: /* strict */
+ if (*error_handler == _Py_ERROR_UNKNOWN)
+ *error_handler = get_error_handler(errors);
+
+ switch (*error_handler) {
+ case _Py_ERROR_STRICT:
raise_encode_exception(exceptionObject, encoding, unicode, collstartpos, collendpos, reason);
return -1;
- case 2: /* replace */
+
+ case _Py_ERROR_REPLACE:
for (collpos = collstartpos; collpos<collendpos; ++collpos) {
x = charmapencode_output('?', mapping, res, respos);
if (x==enc_EXCEPTION) {
@@ -8157,10 +8448,11 @@ charmap_encoding_error(
}
}
/* fall through */
- case 3: /* ignore */
+ case _Py_ERROR_IGNORE:
*inpos = collendpos;
break;
- case 4: /* xmlcharrefreplace */
+
+ case _Py_ERROR_XMLCHARREFREPLACE:
/* generate replacement (temporarily (mis)uses p) */
for (collpos = collstartpos; collpos < collendpos; ++collpos) {
char buffer[2+29+1+1];
@@ -8178,8 +8470,9 @@ charmap_encoding_error(
}
*inpos = collendpos;
break;
+
default:
- repunicode = unicode_encode_call_errorhandler(errors, errorHandler,
+ repunicode = unicode_encode_call_errorhandler(errors, error_handler_obj,
encoding, reason, unicode, exceptionObject,
collstartpos, collendpos, &newpos);
if (repunicode == NULL)
@@ -8242,12 +8535,9 @@ _PyUnicode_EncodeCharmap(PyObject *unicode,
Py_ssize_t size;
/* current output position */
Py_ssize_t respos = 0;
- PyObject *errorHandler = NULL;
+ PyObject *error_handler_obj = NULL;
PyObject *exc = NULL;
- /* the following variable is used for caching string comparisons
- * -1=not initialized, 0=unknown, 1=strict, 2=replace,
- * 3=ignore, 4=xmlcharrefreplace */
- int known_errorHandler = -1;
+ _Py_error_handler error_handler = _Py_ERROR_UNKNOWN;
void *data;
int kind;
@@ -8278,7 +8568,7 @@ _PyUnicode_EncodeCharmap(PyObject *unicode,
if (x==enc_FAILED) { /* unencodable character */
if (charmap_encoding_error(unicode, &inpos, mapping,
&exc,
- &known_errorHandler, &errorHandler, errors,
+ &error_handler, &error_handler_obj, errors,
&res, &respos)) {
goto onError;
}
@@ -8294,13 +8584,13 @@ _PyUnicode_EncodeCharmap(PyObject *unicode,
goto onError;
Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
return res;
onError:
Py_XDECREF(res);
Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
+ Py_XDECREF(error_handler_obj);
return NULL;
}
@@ -8367,7 +8657,7 @@ unicode_translate_call_errorhandler(const char *errors,
Py_ssize_t startpos, Py_ssize_t endpos,
Py_ssize_t *newpos)
{
- static char *argparse = "O!n;translating error handler must return (str, int) tuple";
+ static const char *argparse = "O!n;translating error handler must return (str, int) tuple";
Py_ssize_t i_newpos;
PyObject *restuple;
@@ -8624,7 +8914,7 @@ exit:
return res;
}
-PyObject *
+static PyObject *
_PyUnicode_TranslateCharmap(PyObject *input,
PyObject *mapping,
const char *errors)
@@ -8653,10 +8943,8 @@ _PyUnicode_TranslateCharmap(PyObject *input,
kind = PyUnicode_KIND(input);
size = PyUnicode_GET_LENGTH(input);
- if (size == 0) {
- Py_INCREF(input);
- return input;
- }
+ if (size == 0)
+ return PyUnicode_FromObject(input);
/* allocate enough for a simple 1:1 translation without
replacements, if we need more, we'll resize */
@@ -8767,14 +9055,9 @@ PyUnicode_Translate(PyObject *str,
PyObject *mapping,
const char *errors)
{
- PyObject *result;
-
- str = PyUnicode_FromObject(str);
- if (str == NULL)
+ if (ensure_unicode(str) < 0)
return NULL;
- result = _PyUnicode_TranslateCharmap(str, mapping, errors);
- Py_DECREF(str);
- return result;
+ return _PyUnicode_TranslateCharmap(str, mapping, errors);
}
static Py_UCS4
@@ -8956,9 +9239,10 @@ PyUnicode_EncodeDecimal(Py_UNICODE *s,
}
static Py_ssize_t
-any_find_slice(int direction, PyObject* s1, PyObject* s2,
+any_find_slice(PyObject* s1, PyObject* s2,
Py_ssize_t start,
- Py_ssize_t end)
+ Py_ssize_t end,
+ int direction)
{
int kind1, kind2;
void *buf1, *buf2;
@@ -9127,54 +9411,35 @@ PyUnicode_Count(PyObject *str,
Py_ssize_t end)
{
Py_ssize_t result;
- PyObject* str_obj;
- PyObject* sub_obj;
int kind1, kind2;
void *buf1 = NULL, *buf2 = NULL;
Py_ssize_t len1, len2;
- str_obj = PyUnicode_FromObject(str);
- if (!str_obj)
+ if (ensure_unicode(str) < 0 || ensure_unicode(substr) < 0)
return -1;
- sub_obj = PyUnicode_FromObject(substr);
- if (!sub_obj) {
- Py_DECREF(str_obj);
- return -1;
- }
- if (PyUnicode_READY(sub_obj) == -1 || PyUnicode_READY(str_obj) == -1) {
- Py_DECREF(sub_obj);
- Py_DECREF(str_obj);
- return -1;
- }
- kind1 = PyUnicode_KIND(str_obj);
- kind2 = PyUnicode_KIND(sub_obj);
- if (kind1 < kind2) {
- Py_DECREF(sub_obj);
- Py_DECREF(str_obj);
+ kind1 = PyUnicode_KIND(str);
+ kind2 = PyUnicode_KIND(substr);
+ if (kind1 < kind2)
return 0;
- }
- len1 = PyUnicode_GET_LENGTH(str_obj);
- len2 = PyUnicode_GET_LENGTH(sub_obj);
+ len1 = PyUnicode_GET_LENGTH(str);
+ len2 = PyUnicode_GET_LENGTH(substr);
ADJUST_INDICES(start, end, len1);
- if (end - start < len2) {
- Py_DECREF(sub_obj);
- Py_DECREF(str_obj);
+ if (end - start < len2)
return 0;
- }
- buf1 = PyUnicode_DATA(str_obj);
- buf2 = PyUnicode_DATA(sub_obj);
+ buf1 = PyUnicode_DATA(str);
+ buf2 = PyUnicode_DATA(substr);
if (kind2 != kind1) {
- buf2 = _PyUnicode_AsKind(sub_obj, kind1);
+ buf2 = _PyUnicode_AsKind(substr, kind1);
if (!buf2)
goto onError;
}
switch (kind1) {
case PyUnicode_1BYTE_KIND:
- if (PyUnicode_IS_ASCII(str_obj) && PyUnicode_IS_ASCII(sub_obj))
+ if (PyUnicode_IS_ASCII(str) && PyUnicode_IS_ASCII(substr))
result = asciilib_count(
((Py_UCS1*)buf1) + start, end - start,
buf2, len2, PY_SSIZE_T_MAX
@@ -9201,16 +9466,11 @@ PyUnicode_Count(PyObject *str,
assert(0); result = 0;
}
- Py_DECREF(sub_obj);
- Py_DECREF(str_obj);
-
if (kind2 != kind1)
PyMem_Free(buf2);
return result;
onError:
- Py_DECREF(sub_obj);
- Py_DECREF(str_obj);
if (kind2 != kind1 && buf2)
PyMem_Free(buf2);
return -1;
@@ -9218,35 +9478,15 @@ PyUnicode_Count(PyObject *str,
Py_ssize_t
PyUnicode_Find(PyObject *str,
- PyObject *sub,
+ PyObject *substr,
Py_ssize_t start,
Py_ssize_t end,
int direction)
{
- Py_ssize_t result;
-
- str = PyUnicode_FromObject(str);
- if (!str)
- return -2;
- sub = PyUnicode_FromObject(sub);
- if (!sub) {
- Py_DECREF(str);
- return -2;
- }
- if (PyUnicode_READY(sub) == -1 || PyUnicode_READY(str) == -1) {
- Py_DECREF(sub);
- Py_DECREF(str);
+ if (ensure_unicode(str) < 0 || ensure_unicode(substr) < 0)
return -2;
- }
-
- result = any_find_slice(direction,
- str, sub, start, end
- );
-
- Py_DECREF(str);
- Py_DECREF(sub);
- return result;
+ return any_find_slice(str, substr, start, end, direction);
}
Py_ssize_t
@@ -9349,22 +9589,10 @@ PyUnicode_Tailmatch(PyObject *str,
Py_ssize_t end,
int direction)
{
- Py_ssize_t result;
-
- str = PyUnicode_FromObject(str);
- if (str == NULL)
+ if (ensure_unicode(str) < 0 || ensure_unicode(substr) < 0)
return -1;
- substr = PyUnicode_FromObject(substr);
- if (substr == NULL) {
- Py_DECREF(str);
- return -1;
- }
- result = tailmatch(str, substr,
- start, end, direction);
- Py_DECREF(str);
- Py_DECREF(substr);
- return result;
+ return tailmatch(str, substr, start, end, direction);
}
/* Apply fixfct filter to the Unicode object self and return a
@@ -9666,20 +9894,10 @@ case_operation(PyObject *self,
PyObject *
PyUnicode_Join(PyObject *separator, PyObject *seq)
{
- PyObject *sep = NULL;
- Py_ssize_t seplen;
- PyObject *res = NULL; /* the result */
- PyObject *fseq; /* PySequence_Fast(seq) */
- Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */
+ PyObject *res;
+ PyObject *fseq;
+ Py_ssize_t seqlen;
PyObject **items;
- PyObject *item;
- Py_ssize_t sz, i, res_offset;
- Py_UCS4 maxchar;
- Py_UCS4 item_maxchar;
- int use_memcpy;
- unsigned char *res_data = NULL, *sep_data = NULL;
- PyObject *last_obj;
- unsigned int kind = 0;
fseq = PySequence_Fast(seq, "can only join an iterable");
if (fseq == NULL) {
@@ -9690,21 +9908,39 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
* so we are sure that fseq won't be mutated.
*/
+ items = PySequence_Fast_ITEMS(fseq);
seqlen = PySequence_Fast_GET_SIZE(fseq);
+ res = _PyUnicode_JoinArray(separator, items, seqlen);
+ Py_DECREF(fseq);
+ return res;
+}
+
+PyObject *
+_PyUnicode_JoinArray(PyObject *separator, PyObject **items, Py_ssize_t seqlen)
+{
+ PyObject *res = NULL; /* the result */
+ PyObject *sep = NULL;
+ Py_ssize_t seplen;
+ PyObject *item;
+ Py_ssize_t sz, i, res_offset;
+ Py_UCS4 maxchar;
+ Py_UCS4 item_maxchar;
+ int use_memcpy;
+ unsigned char *res_data = NULL, *sep_data = NULL;
+ PyObject *last_obj;
+ unsigned int kind = 0;
+
/* If empty sequence, return u"". */
if (seqlen == 0) {
- Py_DECREF(fseq);
_Py_RETURN_UNICODE_EMPTY();
}
/* If singleton sequence with an exact Unicode, return that. */
last_obj = NULL;
- items = PySequence_Fast_ITEMS(fseq);
if (seqlen == 1) {
if (PyUnicode_CheckExact(items[0])) {
res = items[0];
Py_INCREF(res);
- Py_DECREF(fseq);
return res;
}
seplen = 0;
@@ -9804,7 +10040,7 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
/* Copy item, and maybe the separator. */
if (i && seplen != 0) {
- Py_MEMCPY(res_data,
+ memcpy(res_data,
sep_data,
kind * seplen);
res_data += kind * seplen;
@@ -9812,7 +10048,7 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
itemlen = PyUnicode_GET_LENGTH(item);
if (itemlen != 0) {
- Py_MEMCPY(res_data,
+ memcpy(res_data,
PyUnicode_DATA(item),
kind * itemlen);
res_data += kind * itemlen;
@@ -9841,13 +10077,11 @@ PyUnicode_Join(PyObject *separator, PyObject *seq)
assert(res_offset == PyUnicode_GET_LENGTH(res));
}
- Py_DECREF(fseq);
Py_XDECREF(sep);
assert(_PyUnicode_CheckConsistency(res, 1));
return res;
onError:
- Py_DECREF(fseq);
Py_XDECREF(sep);
Py_XDECREF(res);
return NULL;
@@ -9972,13 +10206,8 @@ PyUnicode_Splitlines(PyObject *string, int keepends)
{
PyObject *list;
- string = PyUnicode_FromObject(string);
- if (string == NULL)
+ if (ensure_unicode(string) < 0)
return NULL;
- if (PyUnicode_READY(string) == -1) {
- Py_DECREF(string);
- return NULL;
- }
switch (PyUnicode_KIND(string)) {
case PyUnicode_1BYTE_KIND:
@@ -10005,7 +10234,6 @@ PyUnicode_Splitlines(PyObject *string, int keepends)
assert(0);
list = 0;
}
- Py_DECREF(string);
return list;
}
@@ -10566,28 +10794,27 @@ unicode_casefold(PyObject *self)
}
-/* Argument converter. Coerces to a single unicode character */
+/* Argument converter. Accepts a single Unicode character. */
static int
convert_uc(PyObject *obj, void *addr)
{
Py_UCS4 *fillcharloc = (Py_UCS4 *)addr;
- PyObject *uniobj;
- uniobj = PyUnicode_FromObject(obj);
- if (uniobj == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "The fill character cannot be converted to Unicode");
+ if (!PyUnicode_Check(obj)) {
+ PyErr_Format(PyExc_TypeError,
+ "The fill character must be a unicode character, "
+ "not %.100s", Py_TYPE(obj)->tp_name);
return 0;
}
- if (PyUnicode_GET_LENGTH(uniobj) != 1) {
+ if (PyUnicode_READY(obj) < 0)
+ return 0;
+ if (PyUnicode_GET_LENGTH(obj) != 1) {
PyErr_SetString(PyExc_TypeError,
"The fill character must be exactly one character long");
- Py_DECREF(uniobj);
return 0;
}
- *fillcharloc = PyUnicode_READ_CHAR(uniobj, 0);
- Py_DECREF(uniobj);
+ *fillcharloc = PyUnicode_READ_CHAR(obj, 0);
return 1;
}
@@ -10737,7 +10964,7 @@ unicode_compare(PyObject *str1, PyObject *str2)
#undef COMPARE
}
-Py_LOCAL(int)
+static int
unicode_compare_eq(PyObject *str1, PyObject *str2)
{
int kind;
@@ -10781,15 +11008,6 @@ PyUnicode_Compare(PyObject *left, PyObject *right)
}
int
-_PyUnicode_CompareWithId(PyObject *left, _Py_Identifier *right)
-{
- PyObject *right_str = _PyUnicode_FromId(right); /* borrowed */
- if (right_str == NULL)
- return -1;
- return PyUnicode_Compare(left, right_str);
-}
-
-int
PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str)
{
Py_ssize_t i;
@@ -10873,6 +11091,12 @@ _PyUnicode_EqualToASCIIString(PyObject *unicode, const char *str)
{
size_t len;
assert(_PyUnicode_CHECK(unicode));
+ assert(str);
+#ifndef NDEBUG
+ for (const char *p = str; *p; p++) {
+ assert((unsigned char)*p < 128);
+ }
+#endif
if (PyUnicode_READY(unicode) == -1) {
/* Memory error or bad data */
PyErr_Clear();
@@ -10893,6 +11117,11 @@ _PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right)
assert(_PyUnicode_CHECK(left));
assert(right->string);
+#ifndef NDEBUG
+ for (const char *p = right->string; *p; p++) {
+ assert((unsigned char)*p < 128);
+ }
+#endif
if (PyUnicode_READY(left) == -1) {
/* memory error or bad data */
@@ -10990,59 +11219,49 @@ PyUnicode_RichCompare(PyObject *left, PyObject *right, int op)
}
int
-PyUnicode_Contains(PyObject *container, PyObject *element)
+_PyUnicode_EQ(PyObject *aa, PyObject *bb)
+{
+ return unicode_eq(aa, bb);
+}
+
+int
+PyUnicode_Contains(PyObject *str, PyObject *substr)
{
- PyObject *str, *sub;
int kind1, kind2;
void *buf1, *buf2;
Py_ssize_t len1, len2;
int result;
- /* Coerce the two arguments */
- sub = PyUnicode_FromObject(element);
- if (!sub) {
+ if (!PyUnicode_Check(substr)) {
PyErr_Format(PyExc_TypeError,
- "'in <string>' requires string as left operand, not %s",
- element->ob_type->tp_name);
+ "'in <string>' requires string as left operand, not %.100s",
+ Py_TYPE(substr)->tp_name);
return -1;
}
-
- str = PyUnicode_FromObject(container);
- if (!str) {
- Py_DECREF(sub);
+ if (PyUnicode_READY(substr) == -1)
+ return -1;
+ if (ensure_unicode(str) < 0)
return -1;
- }
kind1 = PyUnicode_KIND(str);
- kind2 = PyUnicode_KIND(sub);
- if (kind1 < kind2) {
- Py_DECREF(sub);
- Py_DECREF(str);
+ kind2 = PyUnicode_KIND(substr);
+ if (kind1 < kind2)
return 0;
- }
len1 = PyUnicode_GET_LENGTH(str);
- len2 = PyUnicode_GET_LENGTH(sub);
- if (len1 < len2) {
- Py_DECREF(sub);
- Py_DECREF(str);
+ len2 = PyUnicode_GET_LENGTH(substr);
+ if (len1 < len2)
return 0;
- }
buf1 = PyUnicode_DATA(str);
- buf2 = PyUnicode_DATA(sub);
+ buf2 = PyUnicode_DATA(substr);
if (len2 == 1) {
Py_UCS4 ch = PyUnicode_READ(kind2, buf2, 0);
result = findchar((const char *)buf1, kind1, len1, ch, 1) != -1;
- Py_DECREF(sub);
- Py_DECREF(str);
return result;
}
if (kind2 != kind1) {
- buf2 = _PyUnicode_AsKind(sub, kind1);
- if (!buf2) {
- Py_DECREF(sub);
- Py_DECREF(str);
+ buf2 = _PyUnicode_AsKind(substr, kind1);
+ if (!buf2)
return -1;
- }
}
switch (kind1) {
@@ -11060,9 +11279,6 @@ PyUnicode_Contains(PyObject *container, PyObject *element)
assert(0);
}
- Py_DECREF(str);
- Py_DECREF(sub);
-
if (kind2 != kind1)
PyMem_Free(buf2);
@@ -11074,56 +11290,40 @@ PyUnicode_Contains(PyObject *container, PyObject *element)
PyObject *
PyUnicode_Concat(PyObject *left, PyObject *right)
{
- PyObject *u = NULL, *v = NULL, *w;
+ PyObject *result;
Py_UCS4 maxchar, maxchar2;
- Py_ssize_t u_len, v_len, new_len;
+ Py_ssize_t left_len, right_len, new_len;
- /* Coerce the two arguments */
- u = PyUnicode_FromObject(left);
- if (u == NULL)
- goto onError;
- v = PyUnicode_FromObject(right);
- if (v == NULL)
- goto onError;
+ if (ensure_unicode(left) < 0 || ensure_unicode(right) < 0)
+ return NULL;
/* Shortcuts */
- if (v == unicode_empty) {
- Py_DECREF(v);
- return u;
- }
- if (u == unicode_empty) {
- Py_DECREF(u);
- return v;
- }
+ if (left == unicode_empty)
+ return PyUnicode_FromObject(right);
+ if (right == unicode_empty)
+ return PyUnicode_FromObject(left);
- u_len = PyUnicode_GET_LENGTH(u);
- v_len = PyUnicode_GET_LENGTH(v);
- if (u_len > PY_SSIZE_T_MAX - v_len) {
+ left_len = PyUnicode_GET_LENGTH(left);
+ right_len = PyUnicode_GET_LENGTH(right);
+ if (left_len > PY_SSIZE_T_MAX - right_len) {
PyErr_SetString(PyExc_OverflowError,
"strings are too large to concat");
- goto onError;
+ return NULL;
}
- new_len = u_len + v_len;
+ new_len = left_len + right_len;
- maxchar = PyUnicode_MAX_CHAR_VALUE(u);
- maxchar2 = PyUnicode_MAX_CHAR_VALUE(v);
+ maxchar = PyUnicode_MAX_CHAR_VALUE(left);
+ maxchar2 = PyUnicode_MAX_CHAR_VALUE(right);
maxchar = Py_MAX(maxchar, maxchar2);
/* Concat the two Unicode strings */
- w = PyUnicode_New(new_len, maxchar);
- if (w == NULL)
- goto onError;
- _PyUnicode_FastCopyCharacters(w, 0, u, 0, u_len);
- _PyUnicode_FastCopyCharacters(w, u_len, v, 0, v_len);
- Py_DECREF(u);
- Py_DECREF(v);
- assert(_PyUnicode_CheckConsistency(w, 1));
- return w;
-
- onError:
- Py_XDECREF(u);
- Py_XDECREF(v);
- return NULL;
+ result = PyUnicode_New(new_len, maxchar);
+ if (result == NULL)
+ return NULL;
+ _PyUnicode_FastCopyCharacters(result, 0, left, 0, left_len);
+ _PyUnicode_FastCopyCharacters(result, left_len, right, 0, right_len);
+ assert(_PyUnicode_CheckConsistency(result, 1));
+ return result;
}
void
@@ -11214,6 +11414,25 @@ PyUnicode_AppendAndDel(PyObject **pleft, PyObject *right)
Py_XDECREF(right);
}
+/*
+Wraps stringlib_parse_args_finds() and additionally ensures that the
+first argument is a unicode object.
+*/
+
+static inline int
+parse_args_finds_unicode(const char * function_name, PyObject *args,
+ PyObject **substring,
+ Py_ssize_t *start, Py_ssize_t *end)
+{
+ if(stringlib_parse_args_finds(function_name, args, substring,
+ start, end)) {
+ if (ensure_unicode(*substring) < 0)
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
PyDoc_STRVAR(count__doc__,
"S.count(sub[, start[, end]]) -> int\n\
\n\
@@ -11232,31 +11451,26 @@ unicode_count(PyObject *self, PyObject *args)
void *buf1, *buf2;
Py_ssize_t len1, len2, iresult;
- if (!stringlib_parse_args_finds_unicode("count", args, &substring,
- &start, &end))
+ if (!parse_args_finds_unicode("count", args, &substring, &start, &end))
return NULL;
kind1 = PyUnicode_KIND(self);
kind2 = PyUnicode_KIND(substring);
- if (kind1 < kind2) {
- Py_DECREF(substring);
+ if (kind1 < kind2)
return PyLong_FromLong(0);
- }
+
len1 = PyUnicode_GET_LENGTH(self);
len2 = PyUnicode_GET_LENGTH(substring);
ADJUST_INDICES(start, end, len1);
- if (end - start < len2) {
- Py_DECREF(substring);
+ if (end - start < len2)
return PyLong_FromLong(0);
- }
+
buf1 = PyUnicode_DATA(self);
buf2 = PyUnicode_DATA(substring);
if (kind2 != kind1) {
buf2 = _PyUnicode_AsKind(substring, kind1);
- if (!buf2) {
- Py_DECREF(substring);
+ if (!buf2)
return NULL;
- }
}
switch (kind1) {
case PyUnicode_1BYTE_KIND:
@@ -11286,8 +11500,6 @@ unicode_count(PyObject *self, PyObject *args)
if (kind2 != kind1)
PyMem_Free(buf2);
- Py_DECREF(substring);
-
return result;
}
@@ -11421,22 +11633,13 @@ unicode_find(PyObject *self, PyObject *args)
Py_ssize_t end = 0;
Py_ssize_t result;
- if (!stringlib_parse_args_finds_unicode("find", args, &substring,
- &start, &end))
+ if (!parse_args_finds_unicode("find", args, &substring, &start, &end))
return NULL;
- if (PyUnicode_READY(self) == -1) {
- Py_DECREF(substring);
- return NULL;
- }
- if (PyUnicode_READY(substring) == -1) {
- Py_DECREF(substring);
+ if (PyUnicode_READY(self) == -1)
return NULL;
- }
-
- result = any_find_slice(1, self, substring, start, end);
- Py_DECREF(substring);
+ result = any_find_slice(self, substring, start, end, 1);
if (result == -2)
return NULL;
@@ -11509,22 +11712,13 @@ unicode_index(PyObject *self, PyObject *args)
Py_ssize_t start = 0;
Py_ssize_t end = 0;
- if (!stringlib_parse_args_finds_unicode("index", args, &substring,
- &start, &end))
+ if (!parse_args_finds_unicode("index", args, &substring, &start, &end))
return NULL;
- if (PyUnicode_READY(self) == -1) {
- Py_DECREF(substring);
- return NULL;
- }
- if (PyUnicode_READY(substring) == -1) {
- Py_DECREF(substring);
+ if (PyUnicode_READY(self) == -1)
return NULL;
- }
- result = any_find_slice(1, self, substring, start, end);
-
- Py_DECREF(substring);
+ result = any_find_slice(self, substring, start, end, 1);
if (result == -2)
return NULL;
@@ -12038,7 +12232,7 @@ unicode_lower(PyObject *self)
#define BOTHSTRIP 2
/* Arrays indexed by above */
-static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"};
+static const char * const stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"};
#define STRIPNAME(i) (stripformat[i]+3)
@@ -12319,11 +12513,11 @@ unicode_repeat(PyObject *str, Py_ssize_t len)
Py_ssize_t done = PyUnicode_GET_LENGTH(str);
const Py_ssize_t char_size = PyUnicode_KIND(str);
char *to = (char *) PyUnicode_DATA(u);
- Py_MEMCPY(to, PyUnicode_DATA(str),
+ memcpy(to, PyUnicode_DATA(str),
PyUnicode_GET_LENGTH(str) * char_size);
while (done < nchars) {
n = (done <= nchars-done) ? done : nchars-done;
- Py_MEMCPY(to + (done * char_size), to, n * char_size);
+ memcpy(to + (done * char_size), to, n * char_size);
done += n;
}
}
@@ -12333,40 +12527,15 @@ unicode_repeat(PyObject *str, Py_ssize_t len)
}
PyObject *
-PyUnicode_Replace(PyObject *obj,
- PyObject *subobj,
- PyObject *replobj,
+PyUnicode_Replace(PyObject *str,
+ PyObject *substr,
+ PyObject *replstr,
Py_ssize_t maxcount)
{
- PyObject *self;
- PyObject *str1;
- PyObject *str2;
- PyObject *result;
-
- self = PyUnicode_FromObject(obj);
- if (self == NULL)
- return NULL;
- str1 = PyUnicode_FromObject(subobj);
- if (str1 == NULL) {
- Py_DECREF(self);
- return NULL;
- }
- str2 = PyUnicode_FromObject(replobj);
- if (str2 == NULL) {
- Py_DECREF(self);
- Py_DECREF(str1);
+ if (ensure_unicode(str) < 0 || ensure_unicode(substr) < 0 ||
+ ensure_unicode(replstr) < 0)
return NULL;
- }
- if (PyUnicode_READY(self) == -1 ||
- PyUnicode_READY(str1) == -1 ||
- PyUnicode_READY(str2) == -1)
- result = NULL;
- else
- result = replace(self, str1, str2, maxcount);
- Py_DECREF(self);
- Py_DECREF(str1);
- Py_DECREF(str2);
- return result;
+ return replace(str, substr, replstr, maxcount);
}
PyDoc_STRVAR(replace__doc__,
@@ -12382,28 +12551,12 @@ unicode_replace(PyObject *self, PyObject *args)
PyObject *str1;
PyObject *str2;
Py_ssize_t maxcount = -1;
- PyObject *result;
- if (!PyArg_ParseTuple(args, "OO|n:replace", &str1, &str2, &maxcount))
+ if (!PyArg_ParseTuple(args, "UU|n:replace", &str1, &str2, &maxcount))
return NULL;
if (PyUnicode_READY(self) == -1)
return NULL;
- str1 = PyUnicode_FromObject(str1);
- if (str1 == NULL)
- return NULL;
- str2 = PyUnicode_FromObject(str2);
- if (str2 == NULL) {
- Py_DECREF(str1);
- return NULL;
- }
- if (PyUnicode_READY(str1) == -1 || PyUnicode_READY(str2) == -1)
- result = NULL;
- else
- result = replace(self, str1, str2, maxcount);
-
- Py_DECREF(str1);
- Py_DECREF(str2);
- return result;
+ return replace(self, str1, str2, maxcount);
}
static PyObject *
@@ -12588,22 +12741,13 @@ unicode_rfind(PyObject *self, PyObject *args)
Py_ssize_t end = 0;
Py_ssize_t result;
- if (!stringlib_parse_args_finds_unicode("rfind", args, &substring,
- &start, &end))
+ if (!parse_args_finds_unicode("rfind", args, &substring, &start, &end))
return NULL;
- if (PyUnicode_READY(self) == -1) {
- Py_DECREF(substring);
- return NULL;
- }
- if (PyUnicode_READY(substring) == -1) {
- Py_DECREF(substring);
+ if (PyUnicode_READY(self) == -1)
return NULL;
- }
-
- result = any_find_slice(-1, self, substring, start, end);
- Py_DECREF(substring);
+ result = any_find_slice(self, substring, start, end, -1);
if (result == -2)
return NULL;
@@ -12625,22 +12769,13 @@ unicode_rindex(PyObject *self, PyObject *args)
Py_ssize_t end = 0;
Py_ssize_t result;
- if (!stringlib_parse_args_finds_unicode("rindex", args, &substring,
- &start, &end))
+ if (!parse_args_finds_unicode("rindex", args, &substring, &start, &end))
return NULL;
- if (PyUnicode_READY(self) == -1) {
- Py_DECREF(substring);
- return NULL;
- }
- if (PyUnicode_READY(substring) == -1) {
- Py_DECREF(substring);
+ if (PyUnicode_READY(self) == -1)
return NULL;
- }
- result = any_find_slice(-1, self, substring, start, end);
-
- Py_DECREF(substring);
+ result = any_find_slice(self, substring, start, end, -1);
if (result == -2)
return NULL;
@@ -12680,24 +12815,10 @@ unicode_rjust(PyObject *self, PyObject *args)
PyObject *
PyUnicode_Split(PyObject *s, PyObject *sep, Py_ssize_t maxsplit)
{
- PyObject *result;
-
- s = PyUnicode_FromObject(s);
- if (s == NULL)
+ if (ensure_unicode(s) < 0 || (sep != NULL && ensure_unicode(sep) < 0))
return NULL;
- if (sep != NULL) {
- sep = PyUnicode_FromObject(sep);
- if (sep == NULL) {
- Py_DECREF(s);
- return NULL;
- }
- }
-
- result = split(s, sep, maxsplit);
- Py_DECREF(s);
- Py_XDECREF(sep);
- return result;
+ return split(s, sep, maxsplit);
}
PyDoc_STRVAR(split__doc__,
@@ -12722,35 +12843,26 @@ unicode_split(PyObject *self, PyObject *args, PyObject *kwds)
if (substring == Py_None)
return split(self, NULL, maxcount);
- else if (PyUnicode_Check(substring))
+
+ if (PyUnicode_Check(substring))
return split(self, substring, maxcount);
- else
- return PyUnicode_Split(self, substring, maxcount);
+
+ PyErr_Format(PyExc_TypeError,
+ "must be str or None, not %.100s",
+ Py_TYPE(substring)->tp_name);
+ return NULL;
}
PyObject *
-PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
+PyUnicode_Partition(PyObject *str_obj, PyObject *sep_obj)
{
- PyObject* str_obj;
- PyObject* sep_obj;
PyObject* out;
int kind1, kind2;
void *buf1, *buf2;
Py_ssize_t len1, len2;
- str_obj = PyUnicode_FromObject(str_in);
- if (!str_obj)
- return NULL;
- sep_obj = PyUnicode_FromObject(sep_in);
- if (!sep_obj) {
- Py_DECREF(str_obj);
+ if (ensure_unicode(str_obj) < 0 || ensure_unicode(sep_obj) < 0)
return NULL;
- }
- if (PyUnicode_READY(sep_obj) == -1 || PyUnicode_READY(str_obj) == -1) {
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
- return NULL;
- }
kind1 = PyUnicode_KIND(str_obj);
kind2 = PyUnicode_KIND(sep_obj);
@@ -12764,8 +12876,6 @@ PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
out = PyTuple_Pack(3, str_obj, unicode_empty, unicode_empty);
Py_DECREF(unicode_empty);
}
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
return out;
}
buf1 = PyUnicode_DATA(str_obj);
@@ -12773,7 +12883,7 @@ PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
if (kind2 != kind1) {
buf2 = _PyUnicode_AsKind(sep_obj, kind1);
if (!buf2)
- goto onError;
+ return NULL;
}
switch (kind1) {
@@ -12794,39 +12904,23 @@ PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
out = 0;
}
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
if (kind2 != kind1)
PyMem_Free(buf2);
return out;
- onError:
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
- if (kind2 != kind1 && buf2)
- PyMem_Free(buf2);
- return NULL;
}
PyObject *
-PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)
+PyUnicode_RPartition(PyObject *str_obj, PyObject *sep_obj)
{
- PyObject* str_obj;
- PyObject* sep_obj;
PyObject* out;
int kind1, kind2;
void *buf1, *buf2;
Py_ssize_t len1, len2;
- str_obj = PyUnicode_FromObject(str_in);
- if (!str_obj)
+ if (ensure_unicode(str_obj) < 0 || ensure_unicode(sep_obj) < 0)
return NULL;
- sep_obj = PyUnicode_FromObject(sep_in);
- if (!sep_obj) {
- Py_DECREF(str_obj);
- return NULL;
- }
kind1 = PyUnicode_KIND(str_obj);
kind2 = PyUnicode_KIND(sep_obj);
@@ -12840,8 +12934,6 @@ PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)
out = PyTuple_Pack(3, unicode_empty, unicode_empty, str_obj);
Py_DECREF(unicode_empty);
}
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
return out;
}
buf1 = PyUnicode_DATA(str_obj);
@@ -12849,7 +12941,7 @@ PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)
if (kind2 != kind1) {
buf2 = _PyUnicode_AsKind(sep_obj, kind1);
if (!buf2)
- goto onError;
+ return NULL;
}
switch (kind1) {
@@ -12870,18 +12962,10 @@ PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)
out = 0;
}
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
if (kind2 != kind1)
PyMem_Free(buf2);
return out;
- onError:
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
- if (kind2 != kind1 && buf2)
- PyMem_Free(buf2);
- return NULL;
}
PyDoc_STRVAR(partition__doc__,
@@ -12913,24 +12997,10 @@ unicode_rpartition(PyObject *self, PyObject *separator)
PyObject *
PyUnicode_RSplit(PyObject *s, PyObject *sep, Py_ssize_t maxsplit)
{
- PyObject *result;
-
- s = PyUnicode_FromObject(s);
- if (s == NULL)
+ if (ensure_unicode(s) < 0 || (sep != NULL && ensure_unicode(sep) < 0))
return NULL;
- if (sep != NULL) {
- sep = PyUnicode_FromObject(sep);
- if (sep == NULL) {
- Py_DECREF(s);
- return NULL;
- }
- }
-
- result = rsplit(s, sep, maxsplit);
- Py_DECREF(s);
- Py_XDECREF(sep);
- return result;
+ return rsplit(s, sep, maxsplit);
}
PyDoc_STRVAR(rsplit__doc__,
@@ -12955,10 +13025,14 @@ unicode_rsplit(PyObject *self, PyObject *args, PyObject *kwds)
if (substring == Py_None)
return rsplit(self, NULL, maxcount);
- else if (PyUnicode_Check(substring))
+
+ if (PyUnicode_Check(substring))
return rsplit(self, substring, maxcount);
- else
- return PyUnicode_RSplit(self, substring, maxcount);
+
+ PyErr_Format(PyExc_TypeError,
+ "must be str or None, not %.100s",
+ Py_TYPE(substring)->tp_name);
+ return NULL;
}
PyDoc_STRVAR(splitlines__doc__,
@@ -13239,11 +13313,15 @@ unicode_startswith(PyObject *self,
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- substring = PyUnicode_FromObject(PyTuple_GET_ITEM(subobj, i));
- if (substring == NULL)
+ substring = PyTuple_GET_ITEM(subobj, i);
+ if (!PyUnicode_Check(substring)) {
+ PyErr_Format(PyExc_TypeError,
+ "tuple for startswith must only contain str, "
+ "not %.100s",
+ Py_TYPE(substring)->tp_name);
return NULL;
+ }
result = tailmatch(self, substring, start, end, -1);
- Py_DECREF(substring);
if (result == -1)
return NULL;
if (result) {
@@ -13253,15 +13331,13 @@ unicode_startswith(PyObject *self,
/* nothing matched */
Py_RETURN_FALSE;
}
- substring = PyUnicode_FromObject(subobj);
- if (substring == NULL) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError, "startswith first arg must be str or "
- "a tuple of str, not %s", Py_TYPE(subobj)->tp_name);
+ if (!PyUnicode_Check(subobj)) {
+ PyErr_Format(PyExc_TypeError,
+ "startswith first arg must be str or "
+ "a tuple of str, not %.100s", Py_TYPE(subobj)->tp_name);
return NULL;
}
- result = tailmatch(self, substring, start, end, -1);
- Py_DECREF(substring);
+ result = tailmatch(self, subobj, start, end, -1);
if (result == -1)
return NULL;
return PyBool_FromLong(result);
@@ -13291,12 +13367,15 @@ unicode_endswith(PyObject *self,
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- substring = PyUnicode_FromObject(
- PyTuple_GET_ITEM(subobj, i));
- if (substring == NULL)
+ substring = PyTuple_GET_ITEM(subobj, i);
+ if (!PyUnicode_Check(substring)) {
+ PyErr_Format(PyExc_TypeError,
+ "tuple for endswith must only contain str, "
+ "not %.100s",
+ Py_TYPE(substring)->tp_name);
return NULL;
+ }
result = tailmatch(self, substring, start, end, +1);
- Py_DECREF(substring);
if (result == -1)
return NULL;
if (result) {
@@ -13305,61 +13384,67 @@ unicode_endswith(PyObject *self,
}
Py_RETURN_FALSE;
}
- substring = PyUnicode_FromObject(subobj);
- if (substring == NULL) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError, "endswith first arg must be str or "
- "a tuple of str, not %s", Py_TYPE(subobj)->tp_name);
+ if (!PyUnicode_Check(subobj)) {
+ PyErr_Format(PyExc_TypeError,
+ "endswith first arg must be str or "
+ "a tuple of str, not %.100s", Py_TYPE(subobj)->tp_name);
return NULL;
}
- result = tailmatch(self, substring, start, end, +1);
- Py_DECREF(substring);
+ result = tailmatch(self, subobj, start, end, +1);
if (result == -1)
return NULL;
return PyBool_FromLong(result);
}
-Py_LOCAL_INLINE(void)
+static inline void
_PyUnicodeWriter_Update(_PyUnicodeWriter *writer)
{
- if (!writer->readonly)
+ writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer);
+ writer->data = PyUnicode_DATA(writer->buffer);
+
+ if (!writer->readonly) {
+ writer->kind = PyUnicode_KIND(writer->buffer);
writer->size = PyUnicode_GET_LENGTH(writer->buffer);
+ }
else {
+ /* use a value smaller than PyUnicode_1BYTE_KIND() so
+ _PyUnicodeWriter_PrepareKind() will copy the buffer. */
+ writer->kind = PyUnicode_WCHAR_KIND;
+ assert(writer->kind <= PyUnicode_1BYTE_KIND);
+
/* Copy-on-write mode: set buffer size to 0 so
* _PyUnicodeWriter_Prepare() will copy (and enlarge) the buffer on
* next write. */
writer->size = 0;
}
- writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer);
- writer->data = PyUnicode_DATA(writer->buffer);
- writer->kind = PyUnicode_KIND(writer->buffer);
}
void
_PyUnicodeWriter_Init(_PyUnicodeWriter *writer)
{
memset(writer, 0, sizeof(*writer));
-#ifdef Py_DEBUG
- writer->kind = 5; /* invalid kind */
-#endif
+
+ /* ASCII is the bare minimum */
writer->min_char = 127;
+
+ /* use a value smaller than PyUnicode_1BYTE_KIND() so
+ _PyUnicodeWriter_PrepareKind() will copy the buffer. */
+ writer->kind = PyUnicode_WCHAR_KIND;
+ assert(writer->kind <= PyUnicode_1BYTE_KIND);
}
int
_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
Py_ssize_t length, Py_UCS4 maxchar)
{
-#ifdef MS_WINDOWS
- /* On Windows, overallocate by 50% is the best factor */
-# define OVERALLOCATE_FACTOR 2
-#else
- /* On Linux, overallocate by 25% is the best factor */
-# define OVERALLOCATE_FACTOR 4
-#endif
Py_ssize_t newlen;
PyObject *newbuffer;
- assert(length > 0);
+ assert(maxchar <= MAX_UNICODE);
+
+ /* ensure that the _PyUnicodeWriter_Prepare macro was used */
+ assert((maxchar > writer->maxchar && length >= 0)
+ || length > 0);
if (length > PY_SSIZE_T_MAX - writer->pos) {
PyErr_NoMemory();
@@ -13425,9 +13510,32 @@ _PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
#undef OVERALLOCATE_FACTOR
}
-Py_LOCAL_INLINE(int)
+int
+_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
+ enum PyUnicode_Kind kind)
+{
+ Py_UCS4 maxchar;
+
+ /* ensure that the _PyUnicodeWriter_PrepareKind macro was used */
+ assert(writer->kind < kind);
+
+ switch (kind)
+ {
+ case PyUnicode_1BYTE_KIND: maxchar = 0xff; break;
+ case PyUnicode_2BYTE_KIND: maxchar = 0xffff; break;
+ case PyUnicode_4BYTE_KIND: maxchar = 0x10ffff; break;
+ default:
+ assert(0 && "invalid kind");
+ return -1;
+ }
+
+ return _PyUnicodeWriter_PrepareInternal(writer, 0, maxchar);
+}
+
+static inline int
_PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch)
{
+ assert(ch <= MAX_UNICODE);
if (_PyUnicodeWriter_Prepare(writer, 1, ch) < 0)
return -1;
PyUnicode_WRITE(writer->kind, writer->data, writer->pos, ch);
@@ -13540,7 +13648,7 @@ _PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
const Py_UCS1 *str = (const Py_UCS1 *)ascii;
Py_UCS1 *data = writer->data;
- Py_MEMCPY(data + writer->pos, str, len);
+ memcpy(data + writer->pos, str, len);
break;
}
case PyUnicode_2BYTE_KIND:
@@ -13585,27 +13693,30 @@ PyObject *
_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
{
PyObject *str;
+
if (writer->pos == 0) {
Py_CLEAR(writer->buffer);
_Py_RETURN_UNICODE_EMPTY();
}
+
+ str = writer->buffer;
+ writer->buffer = NULL;
+
if (writer->readonly) {
- str = writer->buffer;
- writer->buffer = NULL;
assert(PyUnicode_GET_LENGTH(str) == writer->pos);
return str;
}
- if (PyUnicode_GET_LENGTH(writer->buffer) != writer->pos) {
- PyObject *newbuffer;
- newbuffer = resize_compact(writer->buffer, writer->pos);
- if (newbuffer == NULL) {
- Py_CLEAR(writer->buffer);
+
+ if (PyUnicode_GET_LENGTH(str) != writer->pos) {
+ PyObject *str2;
+ str2 = resize_compact(str, writer->pos);
+ if (str2 == NULL) {
+ Py_DECREF(str);
return NULL;
}
- writer->buffer = newbuffer;
+ str = str2;
}
- str = writer->buffer;
- writer->buffer = NULL;
+
assert(_PyUnicode_CheckConsistency(str, 1));
return unicode_result_ready(str);
}
@@ -14747,13 +14858,10 @@ PyUnicode_Format(PyObject *format, PyObject *args)
return NULL;
}
- ctx.fmtstr = PyUnicode_FromObject(format);
- if (ctx.fmtstr == NULL)
- return NULL;
- if (PyUnicode_READY(ctx.fmtstr) == -1) {
- Py_DECREF(ctx.fmtstr);
+ if (ensure_unicode(format) < 0)
return NULL;
- }
+
+ ctx.fmtstr = format;
ctx.fmtdata = PyUnicode_DATA(ctx.fmtstr);
ctx.fmtkind = PyUnicode_KIND(ctx.fmtstr);
ctx.fmtcnt = PyUnicode_GET_LENGTH(ctx.fmtstr);
@@ -14813,11 +14921,9 @@ PyUnicode_Format(PyObject *format, PyObject *args)
if (ctx.args_owned) {
Py_DECREF(ctx.args);
}
- Py_DECREF(ctx.fmtstr);
return _PyUnicodeWriter_Finish(&ctx.writer);
onError:
- Py_DECREF(ctx.fmtstr);
_PyUnicodeWriter_Dealloc(&ctx.writer);
if (ctx.args_owned) {
Py_DECREF(ctx.args);
@@ -14934,7 +15040,7 @@ unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
_PyUnicode_WSTR(self) = (wchar_t *)data;
}
- Py_MEMCPY(data, PyUnicode_DATA(unicode),
+ memcpy(data, PyUnicode_DATA(unicode),
kind * (length + 1));
assert(_PyUnicode_CheckConsistency(self, 1));
#ifdef Py_DEBUG
@@ -15095,26 +15201,18 @@ PyUnicode_InternInPlace(PyObject **p)
return;
}
}
- /* It might be that the GetItem call fails even
- though the key is present in the dictionary,
- namely when this happens during a stack overflow. */
Py_ALLOW_RECURSION
- t = PyDict_GetItem(interned, s);
+ t = PyDict_SetDefault(interned, s, s);
Py_END_ALLOW_RECURSION
-
- if (t) {
- Py_INCREF(t);
- Py_SETREF(*p, t);
+ if (t == NULL) {
+ PyErr_Clear();
return;
}
-
- PyThreadState_GET()->recursion_critical = 1;
- if (PyDict_SetItem(interned, s, s) < 0) {
- PyErr_Clear();
- PyThreadState_GET()->recursion_critical = 0;
+ if (t != s) {
+ Py_INCREF(t);
+ Py_SETREF(*p, t);
return;
}
- PyThreadState_GET()->recursion_critical = 0;
/* The two references in interned are not counted by refcnt.
The deallocator will take care of this */
Py_REFCNT(s) -= 2;
diff --git a/Objects/unicodetype_db.h b/Objects/unicodetype_db.h
index 7c780b6c04..39af9208a8 100644
--- a/Objects/unicodetype_db.h
+++ b/Objects/unicodetype_db.h
@@ -244,109 +244,119 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = {
{16777562, 17826136, 16777562, 0, 0, 26377},
{16777565, 17826139, 16777565, 0, 0, 26377},
{0, 0, 0, 0, 0, 3840},
+ {0, 0, 0, 0, 0, 5888},
+ {16777568, 17826142, 16777568, 0, 0, 26377},
+ {16777571, 17826145, 16777571, 0, 0, 26377},
+ {16777574, 17826148, 16777574, 0, 0, 26377},
+ {16777577, 17826151, 16777577, 0, 0, 26377},
+ {16777580, 17826154, 16777580, 0, 0, 26377},
+ {16777583, 17826157, 16777583, 0, 0, 26377},
+ {16777586, 17826160, 16777586, 0, 0, 26377},
+ {16777589, 17826163, 16777589, 0, 0, 26377},
+ {16777592, 17826166, 16777592, 0, 0, 26377},
{35332, 0, 35332, 0, 0, 9993},
{3814, 0, 3814, 0, 0, 9993},
- {33554785, 18874718, 33554785, 0, 0, 26377},
- {33554790, 18874723, 33554790, 0, 0, 26377},
- {33554795, 18874728, 33554795, 0, 0, 26377},
- {33554800, 18874733, 33554800, 0, 0, 26377},
- {33554805, 18874738, 33554805, 0, 0, 26377},
- {16777593, 17826167, 16777593, 0, 0, 26377},
- {16777597, 18874746, 16777597, 0, 0, 26497},
+ {33554812, 18874745, 33554812, 0, 0, 26377},
+ {33554817, 18874750, 33554817, 0, 0, 26377},
+ {33554822, 18874755, 33554822, 0, 0, 26377},
+ {33554827, 18874760, 33554827, 0, 0, 26377},
+ {33554832, 18874765, 33554832, 0, 0, 26377},
+ {16777620, 17826194, 16777620, 0, 0, 26377},
+ {16777624, 18874773, 16777624, 0, 0, 26497},
{8, 0, 8, 0, 0, 9993},
{0, -8, 0, 0, 0, 10113},
- {33554817, 18874750, 33554817, 0, 0, 26377},
- {50332039, 19923331, 50332039, 0, 0, 26377},
- {50332046, 19923338, 50332046, 0, 0, 26377},
- {50332053, 19923345, 50332053, 0, 0, 26377},
+ {33554844, 18874777, 33554844, 0, 0, 26377},
+ {50332066, 19923358, 50332066, 0, 0, 26377},
+ {50332073, 19923365, 50332073, 0, 0, 26377},
+ {50332080, 19923372, 50332080, 0, 0, 26377},
{74, 0, 74, 0, 0, 9993},
{86, 0, 86, 0, 0, 9993},
{100, 0, 100, 0, 0, 9993},
{128, 0, 128, 0, 0, 9993},
{112, 0, 112, 0, 0, 9993},
{126, 0, 126, 0, 0, 9993},
- {33554843, 18874776, 16777629, 0, 0, 26377},
- {33554849, 18874782, 16777635, 0, 0, 26377},
- {33554855, 18874788, 16777641, 0, 0, 26377},
- {33554861, 18874794, 16777647, 0, 0, 26377},
- {33554867, 18874800, 16777653, 0, 0, 26377},
- {33554873, 18874806, 16777659, 0, 0, 26377},
- {33554879, 18874812, 16777665, 0, 0, 26377},
- {33554885, 18874818, 16777671, 0, 0, 26377},
- {33554891, 18874824, 16777677, 0, 0, 26433},
- {33554897, 18874830, 16777683, 0, 0, 26433},
- {33554903, 18874836, 16777689, 0, 0, 26433},
- {33554909, 18874842, 16777695, 0, 0, 26433},
- {33554915, 18874848, 16777701, 0, 0, 26433},
- {33554921, 18874854, 16777707, 0, 0, 26433},
- {33554927, 18874860, 16777713, 0, 0, 26433},
- {33554933, 18874866, 16777719, 0, 0, 26433},
- {33554939, 18874872, 16777725, 0, 0, 26377},
- {33554945, 18874878, 16777731, 0, 0, 26377},
- {33554951, 18874884, 16777737, 0, 0, 26377},
- {33554957, 18874890, 16777743, 0, 0, 26377},
- {33554963, 18874896, 16777749, 0, 0, 26377},
- {33554969, 18874902, 16777755, 0, 0, 26377},
- {33554975, 18874908, 16777761, 0, 0, 26377},
- {33554981, 18874914, 16777767, 0, 0, 26377},
- {33554987, 18874920, 16777773, 0, 0, 26433},
- {33554993, 18874926, 16777779, 0, 0, 26433},
- {33554999, 18874932, 16777785, 0, 0, 26433},
- {33555005, 18874938, 16777791, 0, 0, 26433},
- {33555011, 18874944, 16777797, 0, 0, 26433},
- {33555017, 18874950, 16777803, 0, 0, 26433},
- {33555023, 18874956, 16777809, 0, 0, 26433},
- {33555029, 18874962, 16777815, 0, 0, 26433},
- {33555035, 18874968, 16777821, 0, 0, 26377},
- {33555041, 18874974, 16777827, 0, 0, 26377},
- {33555047, 18874980, 16777833, 0, 0, 26377},
- {33555053, 18874986, 16777839, 0, 0, 26377},
- {33555059, 18874992, 16777845, 0, 0, 26377},
- {33555065, 18874998, 16777851, 0, 0, 26377},
- {33555071, 18875004, 16777857, 0, 0, 26377},
- {33555077, 18875010, 16777863, 0, 0, 26377},
- {33555083, 18875016, 16777869, 0, 0, 26433},
- {33555089, 18875022, 16777875, 0, 0, 26433},
- {33555095, 18875028, 16777881, 0, 0, 26433},
- {33555101, 18875034, 16777887, 0, 0, 26433},
- {33555107, 18875040, 16777893, 0, 0, 26433},
- {33555113, 18875046, 16777899, 0, 0, 26433},
- {33555119, 18875052, 16777905, 0, 0, 26433},
- {33555125, 18875058, 16777911, 0, 0, 26433},
- {33555131, 18875064, 33555133, 0, 0, 26377},
- {33555138, 18875071, 16777924, 0, 0, 26377},
- {33555144, 18875077, 33555146, 0, 0, 26377},
- {33555151, 18875084, 33555151, 0, 0, 26377},
- {50332373, 19923665, 50332376, 0, 0, 26377},
+ {33554870, 18874803, 16777656, 0, 0, 26377},
+ {33554876, 18874809, 16777662, 0, 0, 26377},
+ {33554882, 18874815, 16777668, 0, 0, 26377},
+ {33554888, 18874821, 16777674, 0, 0, 26377},
+ {33554894, 18874827, 16777680, 0, 0, 26377},
+ {33554900, 18874833, 16777686, 0, 0, 26377},
+ {33554906, 18874839, 16777692, 0, 0, 26377},
+ {33554912, 18874845, 16777698, 0, 0, 26377},
+ {33554918, 18874851, 16777704, 0, 0, 26433},
+ {33554924, 18874857, 16777710, 0, 0, 26433},
+ {33554930, 18874863, 16777716, 0, 0, 26433},
+ {33554936, 18874869, 16777722, 0, 0, 26433},
+ {33554942, 18874875, 16777728, 0, 0, 26433},
+ {33554948, 18874881, 16777734, 0, 0, 26433},
+ {33554954, 18874887, 16777740, 0, 0, 26433},
+ {33554960, 18874893, 16777746, 0, 0, 26433},
+ {33554966, 18874899, 16777752, 0, 0, 26377},
+ {33554972, 18874905, 16777758, 0, 0, 26377},
+ {33554978, 18874911, 16777764, 0, 0, 26377},
+ {33554984, 18874917, 16777770, 0, 0, 26377},
+ {33554990, 18874923, 16777776, 0, 0, 26377},
+ {33554996, 18874929, 16777782, 0, 0, 26377},
+ {33555002, 18874935, 16777788, 0, 0, 26377},
+ {33555008, 18874941, 16777794, 0, 0, 26377},
+ {33555014, 18874947, 16777800, 0, 0, 26433},
+ {33555020, 18874953, 16777806, 0, 0, 26433},
+ {33555026, 18874959, 16777812, 0, 0, 26433},
+ {33555032, 18874965, 16777818, 0, 0, 26433},
+ {33555038, 18874971, 16777824, 0, 0, 26433},
+ {33555044, 18874977, 16777830, 0, 0, 26433},
+ {33555050, 18874983, 16777836, 0, 0, 26433},
+ {33555056, 18874989, 16777842, 0, 0, 26433},
+ {33555062, 18874995, 16777848, 0, 0, 26377},
+ {33555068, 18875001, 16777854, 0, 0, 26377},
+ {33555074, 18875007, 16777860, 0, 0, 26377},
+ {33555080, 18875013, 16777866, 0, 0, 26377},
+ {33555086, 18875019, 16777872, 0, 0, 26377},
+ {33555092, 18875025, 16777878, 0, 0, 26377},
+ {33555098, 18875031, 16777884, 0, 0, 26377},
+ {33555104, 18875037, 16777890, 0, 0, 26377},
+ {33555110, 18875043, 16777896, 0, 0, 26433},
+ {33555116, 18875049, 16777902, 0, 0, 26433},
+ {33555122, 18875055, 16777908, 0, 0, 26433},
+ {33555128, 18875061, 16777914, 0, 0, 26433},
+ {33555134, 18875067, 16777920, 0, 0, 26433},
+ {33555140, 18875073, 16777926, 0, 0, 26433},
+ {33555146, 18875079, 16777932, 0, 0, 26433},
+ {33555152, 18875085, 16777938, 0, 0, 26433},
+ {33555158, 18875091, 33555160, 0, 0, 26377},
+ {33555165, 18875098, 16777951, 0, 0, 26377},
+ {33555171, 18875104, 33555173, 0, 0, 26377},
+ {33555178, 18875111, 33555178, 0, 0, 26377},
+ {50332400, 19923692, 50332403, 0, 0, 26377},
{0, -74, 0, 0, 0, 10113},
- {33555166, 18875099, 16777952, 0, 0, 26433},
- {16777955, 17826529, 16777955, 0, 0, 26377},
- {33555175, 18875108, 33555177, 0, 0, 26377},
- {33555182, 18875115, 16777968, 0, 0, 26377},
- {33555188, 18875121, 33555190, 0, 0, 26377},
- {33555195, 18875128, 33555195, 0, 0, 26377},
- {50332417, 19923709, 50332420, 0, 0, 26377},
+ {33555193, 18875126, 16777979, 0, 0, 26433},
+ {16777982, 17826556, 16777982, 0, 0, 26377},
+ {33555202, 18875135, 33555204, 0, 0, 26377},
+ {33555209, 18875142, 16777995, 0, 0, 26377},
+ {33555215, 18875148, 33555217, 0, 0, 26377},
+ {33555222, 18875155, 33555222, 0, 0, 26377},
+ {50332444, 19923736, 50332447, 0, 0, 26377},
{0, -86, 0, 0, 0, 10113},
- {33555210, 18875143, 16777996, 0, 0, 26433},
- {50332433, 19923725, 50332433, 0, 0, 26377},
- {50332440, 19923732, 50332440, 0, 0, 26377},
- {33555230, 18875163, 33555230, 0, 0, 26377},
- {50332452, 19923744, 50332452, 0, 0, 26377},
+ {33555237, 18875170, 16778023, 0, 0, 26433},
+ {50332460, 19923752, 50332460, 0, 0, 26377},
+ {50332467, 19923759, 50332467, 0, 0, 26377},
+ {33555257, 18875190, 33555257, 0, 0, 26377},
+ {50332479, 19923771, 50332479, 0, 0, 26377},
{0, -100, 0, 0, 0, 10113},
- {50332459, 19923751, 50332459, 0, 0, 26377},
- {50332466, 19923758, 50332466, 0, 0, 26377},
- {33555256, 18875189, 33555256, 0, 0, 26377},
- {33555261, 18875194, 33555261, 0, 0, 26377},
- {50332483, 19923775, 50332483, 0, 0, 26377},
+ {50332486, 19923778, 50332486, 0, 0, 26377},
+ {50332493, 19923785, 50332493, 0, 0, 26377},
+ {33555283, 18875216, 33555283, 0, 0, 26377},
+ {33555288, 18875221, 33555288, 0, 0, 26377},
+ {50332510, 19923802, 50332510, 0, 0, 26377},
{0, -112, 0, 0, 0, 10113},
- {33555273, 18875206, 33555275, 0, 0, 26377},
- {33555280, 18875213, 16778066, 0, 0, 26377},
- {33555286, 18875219, 33555288, 0, 0, 26377},
- {33555293, 18875226, 33555293, 0, 0, 26377},
- {50332515, 19923807, 50332518, 0, 0, 26377},
+ {33555300, 18875233, 33555302, 0, 0, 26377},
+ {33555307, 18875240, 16778093, 0, 0, 26377},
+ {33555313, 18875246, 33555315, 0, 0, 26377},
+ {33555320, 18875253, 33555320, 0, 0, 26377},
+ {50332542, 19923834, 50332545, 0, 0, 26377},
{0, -128, 0, 0, 0, 10113},
{0, -126, 0, 0, 0, 10113},
- {33555308, 18875241, 16778094, 0, 0, 26433},
+ {33555335, 18875268, 16778121, 0, 0, 26433},
{0, 0, 0, 0, 0, 3076},
{0, 0, 0, 0, 4, 3076},
{0, 0, 0, 0, 5, 3076},
@@ -388,15 +398,6 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = {
{0, -42261, 0, 0, 0, 10113},
{0, 928, 0, 0, 0, 10113},
{-928, 0, -928, 0, 0, 9993},
- {16778097, 17826671, 16778097, 0, 0, 26377},
- {16778100, 17826674, 16778100, 0, 0, 26377},
- {16778103, 17826677, 16778103, 0, 0, 26377},
- {16778106, 17826680, 16778106, 0, 0, 26377},
- {16778109, 17826683, 16778109, 0, 0, 26377},
- {16778112, 17826686, 16778112, 0, 0, 26377},
- {16778115, 17826689, 16778115, 0, 0, 26377},
- {16778118, 17826692, 16778118, 0, 0, 26377},
- {16778121, 17826695, 16778121, 0, 0, 26377},
{16778124, 17826698, 16778124, 0, 0, 26377},
{16778127, 17826701, 16778127, 0, 0, 26377},
{16778130, 17826704, 16778130, 0, 0, 26377},
@@ -468,22 +469,33 @@ const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = {
{16778328, 17826902, 16778328, 0, 0, 26377},
{16778331, 17826905, 16778331, 0, 0, 26377},
{16778334, 17826908, 16778334, 0, 0, 26377},
- {33555554, 18875487, 33555556, 0, 0, 26377},
- {33555561, 18875494, 33555563, 0, 0, 26377},
- {33555568, 18875501, 33555570, 0, 0, 26377},
- {50332792, 19924084, 50332795, 0, 0, 26377},
- {50332802, 19924094, 50332805, 0, 0, 26377},
+ {16778337, 17826911, 16778337, 0, 0, 26377},
+ {16778340, 17826914, 16778340, 0, 0, 26377},
+ {16778343, 17826917, 16778343, 0, 0, 26377},
+ {16778346, 17826920, 16778346, 0, 0, 26377},
+ {16778349, 17826923, 16778349, 0, 0, 26377},
+ {16778352, 17826926, 16778352, 0, 0, 26377},
+ {16778355, 17826929, 16778355, 0, 0, 26377},
+ {16778358, 17826932, 16778358, 0, 0, 26377},
+ {16778361, 17826935, 16778361, 0, 0, 26377},
+ {33555581, 18875514, 33555583, 0, 0, 26377},
+ {33555588, 18875521, 33555590, 0, 0, 26377},
{33555595, 18875528, 33555597, 0, 0, 26377},
- {33555602, 18875535, 33555604, 0, 0, 26377},
- {33555609, 18875542, 33555611, 0, 0, 26377},
- {33555616, 18875549, 33555618, 0, 0, 26377},
- {33555623, 18875556, 33555625, 0, 0, 26377},
- {33555630, 18875563, 33555632, 0, 0, 26377},
- {33555637, 18875570, 33555639, 0, 0, 26377},
+ {50332819, 19924111, 50332822, 0, 0, 26377},
+ {50332829, 19924121, 50332832, 0, 0, 26377},
+ {33555622, 18875555, 33555624, 0, 0, 26377},
+ {33555629, 18875562, 33555631, 0, 0, 26377},
+ {33555636, 18875569, 33555638, 0, 0, 26377},
+ {33555643, 18875576, 33555645, 0, 0, 26377},
+ {33555650, 18875583, 33555652, 0, 0, 26377},
+ {33555657, 18875590, 33555659, 0, 0, 26377},
+ {33555664, 18875597, 33555666, 0, 0, 26377},
{0, 0, 0, 0, 0, 1025},
{0, 0, 0, 0, 0, 5633},
{0, 40, 0, 0, 0, 10113},
{-40, 0, -40, 0, 0, 9993},
+ {0, 34, 0, 0, 0, 10113},
+ {-34, 0, -34, 0, 0, 9993},
{0, 0, 0, 0, 0, 9344},
};
@@ -840,6 +852,33 @@ const Py_UCS4 _PyUnicode_ExtendedCase[] = {
5117,
5109,
5109,
+ 7296,
+ 1074,
+ 1042,
+ 7297,
+ 1076,
+ 1044,
+ 7298,
+ 1086,
+ 1054,
+ 7299,
+ 1089,
+ 1057,
+ 7300,
+ 1090,
+ 1058,
+ 7301,
+ 1090,
+ 1058,
+ 7302,
+ 1098,
+ 1066,
+ 7303,
+ 1123,
+ 1122,
+ 7304,
+ 42571,
+ 42570,
7830,
104,
817,
@@ -1736,69 +1775,68 @@ static unsigned char index1[] = {
131, 132, 133, 134, 34, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
145, 146, 147, 148, 149, 150, 151, 145, 34, 34, 152, 145, 153, 154, 155,
156, 157, 158, 159, 160, 161, 162, 145, 145, 163, 145, 145, 145, 164,
- 165, 166, 167, 168, 169, 170, 145, 145, 171, 145, 172, 173, 174, 175,
- 145, 145, 176, 145, 145, 145, 177, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 34, 34, 34, 34, 34, 34, 34, 178, 179, 34, 180, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 34, 34, 34, 34, 34, 34, 34, 34, 181, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 165, 166, 167, 168, 169, 170, 145, 171, 172, 145, 173, 174, 175, 176,
+ 145, 145, 177, 145, 145, 145, 178, 145, 145, 179, 180, 145, 145, 145,
+ 145, 145, 145, 34, 34, 34, 34, 34, 34, 34, 181, 182, 34, 183, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 34, 34, 34, 34, 182, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 34, 34, 34, 34, 34, 34, 34, 34, 184, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 34, 34, 34, 34, 183, 184, 185, 186, 145, 145, 145, 145, 145,
- 145, 187, 188, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 34, 34, 34, 34, 185, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 34, 34, 34, 34, 186, 187, 188, 189, 145, 145, 145, 145, 145,
+ 145, 190, 191, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 192, 34, 34,
+ 34, 34, 34, 193, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 189, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 194, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 190, 191, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 195, 196, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 64, 192,
- 193, 194, 195, 145, 196, 145, 197, 198, 199, 200, 201, 202, 203, 204, 64,
- 64, 64, 64, 205, 206, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 34, 207, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 208,
- 209, 145, 145, 210, 211, 212, 213, 214, 145, 64, 215, 64, 64, 216, 217,
- 64, 218, 219, 220, 221, 222, 223, 224, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 225, 226, 227, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 87, 228, 34, 229, 230, 34, 34, 34, 34, 34,
+ 145, 64, 197, 198, 199, 200, 145, 201, 145, 202, 203, 204, 205, 206, 207,
+ 208, 209, 64, 64, 64, 64, 210, 211, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 212, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 34, 213, 214, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 215, 216, 145, 145, 217, 218, 219, 220, 221, 145, 64, 222, 64,
+ 64, 64, 64, 64, 223, 224, 225, 226, 227, 228, 229, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 230, 231, 232, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 87, 233, 34, 234, 235, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 231, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 232, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 236, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 237, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 233, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 238, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 234, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 239, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 235,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 236, 34, 237, 34,
+ 34, 34, 34, 240, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 241, 34, 242, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 238, 145, 145, 145, 145, 145, 145, 145, 145,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 243, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 34, 231, 34, 34, 239, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 34, 236, 34, 34, 244, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
@@ -2201,7 +2239,8 @@ static unsigned char index1[] = {
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 240, 145, 241, 242, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 245, 145,
+ 246, 247, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
@@ -2237,8 +2276,7 @@ static unsigned char index1[] = {
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+ 145, 145, 145, 145, 145, 145, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
@@ -2274,7 +2312,7 @@ static unsigned char index1[] = {
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 243, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 248,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
@@ -2311,7 +2349,7 @@ static unsigned char index1[] = {
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 243,
+ 127, 127, 127, 127, 127, 127, 127, 248,
};
static unsigned short index2[] = {
@@ -2347,7 +2385,7 @@ static unsigned short index2[] = {
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 20, 20, 20, 20, 20, 20, 65,
30, 31, 66, 67, 68, 68, 30, 31, 69, 70, 71, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 72, 73, 74, 75, 76, 20, 77, 77, 20, 78, 20, 79, 80, 20, 20,
- 20, 77, 81, 20, 82, 20, 83, 84, 20, 85, 86, 20, 87, 88, 20, 20, 86, 20,
+ 20, 77, 81, 20, 82, 20, 83, 84, 20, 85, 86, 84, 87, 88, 20, 20, 86, 20,
89, 90, 20, 20, 91, 20, 20, 20, 20, 20, 20, 20, 92, 20, 20, 93, 20, 20,
93, 20, 20, 20, 94, 93, 95, 96, 96, 97, 20, 20, 20, 20, 20, 98, 20, 55,
20, 20, 20, 20, 20, 20, 20, 20, 99, 100, 20, 20, 20, 20, 20, 20, 20, 20,
@@ -2435,152 +2473,156 @@ static unsigned short index2[] = {
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 21, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25,
+ 18, 25, 55, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 18, 18,
+ 25, 18, 18, 55, 25, 25, 25, 25, 25, 25, 25, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 25, 25, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 102,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 18,
+ 0, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 55, 0, 0, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 0, 0, 0, 55, 55, 55, 55, 0, 0, 25,
+ 55, 18, 18, 18, 25, 25, 25, 25, 0, 0, 18, 18, 0, 0, 18, 18, 25, 55, 0, 0,
+ 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 55, 55, 0, 55, 55, 55, 25, 25, 0, 0, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 55, 55, 5, 5, 27, 27, 27, 27, 27, 27,
+ 5, 5, 0, 0, 0, 0, 0, 25, 25, 18, 0, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
+ 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0,
+ 55, 55, 0, 55, 55, 0, 0, 25, 0, 18, 18, 18, 25, 25, 0, 0, 0, 0, 25, 25,
+ 0, 0, 25, 25, 25, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 0,
+ 55, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 25, 25, 55,
+ 55, 55, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 18, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55,
+ 55, 55, 55, 55, 0, 55, 55, 0, 55, 55, 55, 55, 55, 0, 0, 25, 55, 18, 18,
+ 18, 25, 25, 25, 25, 25, 0, 25, 25, 18, 0, 18, 18, 25, 0, 0, 55, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 5, 5, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0,
+ 0, 25, 18, 18, 0, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 55, 0, 0, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0, 55, 55, 55, 55,
+ 55, 0, 0, 25, 55, 18, 25, 18, 25, 25, 25, 25, 0, 0, 18, 18, 0, 0, 18, 18,
+ 25, 0, 0, 0, 0, 0, 0, 0, 0, 25, 18, 0, 0, 0, 0, 55, 55, 0, 55, 55, 55,
+ 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 55, 27, 27, 27, 27,
+ 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 55, 0, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 55, 55, 55, 0, 55, 55, 55, 55, 0, 0, 0, 55, 55, 0, 55, 0, 55,
+ 55, 0, 0, 0, 55, 55, 0, 0, 0, 55, 55, 55, 0, 0, 0, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 18, 18, 25, 18, 18, 0, 0, 0, 18,
+ 18, 18, 0, 18, 18, 18, 25, 0, 0, 55, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 27, 27,
+ 27, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 25, 18, 18, 18, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 55, 25, 25,
+ 25, 18, 18, 18, 18, 0, 25, 25, 25, 0, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0,
+ 0, 25, 25, 0, 55, 55, 55, 0, 0, 0, 0, 0, 55, 55, 25, 25, 0, 0, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 27, 27, 27, 27, 27,
+ 27, 27, 5, 55, 25, 18, 18, 0, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55,
+ 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0,
+ 55, 55, 55, 55, 55, 0, 0, 25, 55, 18, 25, 18, 18, 18, 18, 18, 0, 25, 18,
+ 18, 0, 18, 18, 25, 25, 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0,
+ 55, 0, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 55,
+ 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 18, 18, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 18, 18,
+ 18, 25, 25, 25, 25, 0, 18, 18, 18, 0, 18, 18, 18, 25, 55, 5, 0, 0, 0, 0,
+ 55, 55, 55, 18, 27, 27, 27, 27, 27, 27, 27, 55, 55, 55, 25, 25, 0, 0, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 5,
+ 55, 55, 55, 55, 55, 55, 0, 0, 18, 18, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 0, 0, 55, 55, 55, 55, 55,
+ 55, 55, 0, 0, 0, 25, 0, 0, 0, 0, 18, 18, 18, 25, 25, 25, 0, 25, 0, 18,
+ 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 0, 0, 18, 18, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 55, 138, 25, 25, 25, 25, 25,
+ 25, 25, 0, 0, 0, 0, 5, 55, 55, 55, 55, 55, 55, 102, 25, 25, 25, 25, 25,
+ 25, 25, 25, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 0, 55, 0, 0, 55, 55, 0, 55, 0, 0, 55, 0,
+ 0, 0, 0, 0, 0, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55,
+ 55, 0, 55, 0, 55, 0, 0, 55, 55, 0, 55, 55, 55, 55, 25, 55, 138, 25, 25,
+ 25, 25, 25, 25, 0, 25, 25, 55, 0, 0, 55, 55, 55, 55, 55, 0, 102, 0, 25,
+ 25, 25, 25, 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 55,
+ 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 25, 5, 5, 5, 5, 5, 5, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 5,
+ 25, 5, 25, 5, 25, 5, 5, 5, 5, 18, 18, 55, 55, 55, 55, 55, 55, 55, 55, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18,
+ 25, 25, 25, 25, 25, 5, 25, 25, 55, 55, 55, 55, 55, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 25, 55, 18, 18, 18,
- 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 18, 18, 25, 18, 18, 55, 25, 25,
- 25, 25, 25, 25, 25, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 5, 5,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 102, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 18, 0, 55, 55, 55, 55, 55, 55,
- 55, 55, 0, 0, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55,
- 55, 0, 55, 0, 0, 0, 55, 55, 55, 55, 0, 0, 25, 55, 18, 18, 18, 25, 25, 25,
- 25, 0, 0, 18, 18, 0, 0, 18, 18, 25, 55, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
- 0, 0, 55, 55, 0, 55, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 55, 55, 5, 5, 27, 27, 27, 27, 27, 27, 5, 5, 0, 0, 0, 0, 0, 25,
- 25, 18, 0, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 55, 55, 0, 0, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0, 55, 55, 0, 55, 55, 0, 0,
- 25, 0, 18, 18, 18, 25, 25, 0, 0, 0, 0, 25, 25, 0, 0, 25, 25, 25, 0, 0, 0,
- 25, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 0, 55, 0, 0, 0, 0, 0, 0, 0, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 25, 25, 55, 55, 55, 25, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 25, 25, 18, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0,
- 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55,
- 0, 55, 55, 55, 55, 55, 0, 0, 25, 55, 18, 18, 18, 25, 25, 25, 25, 25, 0,
- 25, 25, 18, 0, 18, 18, 25, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 5,
- 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 25, 18, 18, 0, 55, 55, 55,
- 55, 55, 55, 55, 55, 0, 0, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55,
- 55, 55, 55, 55, 0, 55, 55, 0, 55, 55, 55, 55, 55, 0, 0, 25, 55, 18, 25,
- 18, 25, 25, 25, 25, 0, 0, 18, 18, 0, 0, 18, 18, 25, 0, 0, 0, 0, 0, 0, 0,
- 0, 25, 18, 0, 0, 0, 0, 55, 55, 0, 55, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 5, 55, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 25, 55, 0, 55, 55, 55, 55, 55, 55, 0, 0, 0, 55, 55, 55, 0,
- 55, 55, 55, 55, 0, 0, 0, 55, 55, 0, 55, 0, 55, 55, 0, 0, 0, 55, 55, 0, 0,
- 0, 55, 55, 55, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 0, 0, 0, 0, 18, 18, 25, 18, 18, 0, 0, 0, 18, 18, 18, 0, 18, 18, 18, 25,
- 0, 0, 55, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 27, 27, 27, 5, 5, 5, 5, 5, 5, 5, 5,
- 0, 0, 0, 0, 0, 25, 18, 18, 18, 0, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55,
- 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 55, 25, 25, 25, 18, 18, 18, 18, 0,
- 25, 25, 25, 0, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 25, 25, 0, 55, 55,
- 55, 0, 0, 0, 0, 0, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 0, 0, 0, 0, 0, 0, 0, 0, 27, 27, 27, 27, 27, 27, 27, 5, 0, 25, 18, 18,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 0, 0,
- 25, 55, 18, 25, 18, 18, 18, 18, 18, 0, 25, 18, 18, 0, 18, 18, 25, 25, 0,
- 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 55, 0, 55, 55, 25, 25, 0,
- 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 55, 55, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 25, 18, 18, 0, 55, 55, 55, 55, 55, 55, 55, 55, 0,
- 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 25, 25, 25, 25, 25, 25, 25, 0, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5,
+ 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 18, 18, 18, 25, 25, 25, 25,
- 0, 18, 18, 18, 0, 18, 18, 18, 25, 55, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
- 0, 0, 0, 0, 0, 55, 55, 55, 25, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 27, 27, 27, 27, 27, 27, 0, 0, 0, 5, 55, 55, 55, 55, 55, 55, 0, 0, 18,
- 18, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 0, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 25, 0, 0, 0, 0,
- 18, 18, 18, 25, 25, 25, 0, 25, 0, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0,
- 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 18, 18, 5, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18, 25, 25, 25, 25, 18, 25,
+ 25, 25, 25, 25, 25, 18, 25, 25, 18, 18, 25, 25, 55, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 5, 5, 5, 5, 5, 5, 55, 55, 55, 55, 55, 55, 18, 18, 25, 25,
+ 55, 55, 55, 55, 25, 25, 25, 55, 18, 18, 18, 55, 55, 18, 18, 18, 18, 18,
+ 18, 18, 55, 55, 55, 25, 25, 25, 25, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 25, 18, 18, 25, 25, 18, 18, 18, 18, 18, 18, 25, 55, 18,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 18, 18, 25, 5, 5, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
+ 139, 139, 139, 139, 139, 139, 139, 0, 139, 0, 0, 0, 0, 0, 139, 0, 0, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 25, 55, 138, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 5, 55, 55, 55,
- 55, 55, 55, 102, 25, 25, 25, 25, 25, 25, 25, 25, 5, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 0,
- 55, 0, 0, 55, 55, 0, 55, 0, 0, 55, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 0,
- 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 0, 55, 0, 0, 55, 55, 0,
- 55, 55, 55, 55, 25, 55, 138, 25, 25, 25, 25, 25, 25, 0, 25, 25, 55, 0, 0,
- 55, 55, 55, 55, 55, 0, 102, 0, 25, 25, 25, 25, 25, 25, 0, 0, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 0, 0, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25,
- 25, 5, 5, 5, 5, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 5, 25, 5, 25, 5, 25, 5, 5, 5, 5, 18, 18, 55,
- 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 5, 102, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 18, 25, 25, 25, 25, 25, 5, 25, 25, 55, 55,
- 55, 55, 55, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 5, 5, 5,
- 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 18, 18, 25, 25, 25, 25, 18, 25, 25, 25, 25, 25, 25, 18, 25, 25, 18, 18,
- 25, 25, 55, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 5, 5, 5, 5, 5, 55,
- 55, 55, 55, 55, 55, 18, 18, 25, 25, 55, 55, 55, 55, 25, 25, 25, 55, 18,
- 18, 18, 55, 55, 18, 18, 18, 18, 18, 18, 18, 55, 55, 55, 25, 25, 25, 25,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 18, 25, 25,
- 18, 18, 18, 18, 18, 18, 25, 55, 18, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 18, 18, 18, 25, 5, 5, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 0,
- 139, 0, 0, 0, 0, 0, 139, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 102, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55,
+ 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 0, 55, 55, 55, 55, 0, 0, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55,
+ 55, 55, 0, 55, 0, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55,
- 0, 55, 0, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 0, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 0,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55,
- 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 0, 55, 55, 55, 55,
- 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 25, 25, 25, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 140, 141, 142, 143, 144, 145, 146, 147, 148, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0,
+ 0, 0, 0, 0, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
+ 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+ 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+ 231, 232, 233, 234, 0, 0, 235, 236, 237, 238, 239, 240, 0, 0, 5, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 0, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 0, 0, 25, 25, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 140, 141, 142,
- 143, 144, 145, 146, 147, 148, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 149, 150, 151, 152, 153,
- 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
- 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195,
- 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
- 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 0, 0, 235, 236,
- 237, 238, 239, 240, 0, 0, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2590,112 +2632,109 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 5, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 2, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 0, 0, 0, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 2, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 5,
+ 241, 241, 241, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 25,
+ 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 25, 5, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 0, 25, 25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 5, 5, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 25, 25, 18, 25, 25, 25, 25, 25, 25, 25, 18, 18, 18, 18,
+ 18, 18, 18, 18, 25, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 5, 5, 5, 102, 5, 5, 5, 5, 55, 25, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 0, 0, 0, 0, 0, 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0,
+ 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 25, 25, 21, 0, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 102, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 5, 5, 5, 241, 241, 241, 55, 55, 55, 55, 55,
- 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 0, 55, 55, 55, 55, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 25, 25, 25, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0,
- 55, 55, 55, 0, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 18, 25, 25,
- 25, 25, 25, 25, 25, 18, 18, 18, 18, 18, 18, 18, 18, 25, 18, 18, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 102, 5, 5, 5, 5, 55, 25, 0,
- 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 25, 25, 25, 21, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 102, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55,
+ 55, 242, 242, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0,
- 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 25, 55, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 55, 0, 0, 0, 0, 0, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 25, 25,
- 25, 18, 18, 18, 18, 25, 25, 18, 18, 18, 0, 0, 0, 0, 18, 18, 25, 18, 18,
- 18, 18, 18, 18, 25, 25, 25, 0, 0, 0, 0, 5, 0, 0, 0, 5, 5, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 25, 25, 25, 18, 18, 18, 18, 25, 25, 18,
+ 18, 18, 0, 0, 0, 0, 18, 18, 25, 18, 18, 18, 18, 18, 18, 25, 25, 25, 0, 0,
+ 0, 0, 5, 0, 0, 0, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 0, 0, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0,
- 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 140, 0, 0, 0, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 18, 18, 25, 0, 0, 5, 5, 55,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 140, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 25, 25, 18, 18, 25, 0, 0, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 25,
- 18, 25, 25, 25, 25, 25, 25, 25, 0, 25, 18, 25, 18, 18, 25, 25, 25, 25,
- 25, 25, 25, 25, 18, 18, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 0, 0, 25, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5,
- 5, 102, 5, 5, 5, 5, 5, 5, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 18, 25, 18, 25, 25, 25, 25, 25, 25, 25, 0,
+ 25, 18, 25, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 18, 18, 18,
+ 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 25, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 102, 5, 5, 5, 5, 5, 5, 0, 0,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
- 25, 25, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 18, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 25,
- 25, 25, 25, 25, 18, 25, 18, 18, 18, 18, 18, 25, 18, 18, 55, 55, 55, 55,
- 55, 55, 55, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 25, 25, 18, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 18, 25, 25, 25, 25, 18, 18, 25, 25, 18, 25,
- 25, 25, 55, 55, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 25, 18, 25, 25, 25, 25, 25, 18, 25, 18, 18,
+ 18, 18, 18, 25, 18, 18, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 25, 25, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
+ 0, 0, 25, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 25,
+ 25, 25, 25, 18, 18, 25, 25, 18, 25, 25, 25, 55, 55, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 25, 25, 18, 18,
+ 18, 25, 18, 25, 25, 25, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 25, 18, 25, 25, 18, 18, 18, 25, 18, 25, 25, 25, 18, 18, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18,
+ 18, 18, 18, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 25,
+ 25, 0, 0, 0, 5, 5, 5, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0,
+ 55, 55, 55, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 18, 18, 18, 18, 18, 25, 25, 25,
- 25, 25, 25, 25, 25, 18, 18, 25, 25, 0, 0, 0, 5, 5, 5, 5, 5, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 0, 0, 0, 55, 55, 55, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 102, 102, 102,
- 102, 102, 102, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 102, 102, 102, 102, 102, 102, 5, 5, 243, 244,
+ 245, 246, 247, 248, 249, 250, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
- 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 5, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 25, 25, 25, 25, 25, 25, 25,
- 55, 55, 55, 55, 25, 55, 55, 55, 55, 18, 18, 25, 55, 55, 0, 25, 25, 0, 0,
- 0, 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5,
+ 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 5, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 18, 25, 25, 25, 25, 25, 25, 25, 55, 55, 55, 55,
+ 25, 55, 55, 55, 55, 18, 18, 25, 55, 55, 0, 25, 25, 0, 0, 0, 0, 0, 0, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 101, 101, 101, 101, 101, 101,
- 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 101, 101, 101, 101, 101, 101, 101, 101, 101,
101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
- 101, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 101, 242, 20,
- 20, 20, 243, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 101, 101, 101,
+ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 101, 252, 20, 20, 20, 253, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 101, 101, 101, 101, 101, 101,
101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
- 101, 101, 101, 101, 101, 101, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 101, 101, 101, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 30, 31, 30,
+ 25, 25, 25, 25, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
@@ -2704,49 +2743,49 @@ static unsigned short index2[] = {
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
- 31, 30, 31, 244, 245, 246, 247, 248, 249, 20, 20, 250, 20, 30, 31, 30,
+ 31, 254, 255, 256, 257, 258, 259, 20, 20, 260, 20, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
- 31, 30, 31, 251, 251, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252,
- 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 0, 0, 252, 252, 252,
- 252, 252, 252, 0, 0, 251, 251, 251, 251, 251, 251, 251, 251, 252, 252,
- 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 251, 251,
- 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 0,
- 0, 252, 252, 252, 252, 252, 252, 0, 0, 253, 251, 254, 251, 255, 251, 256,
- 251, 0, 252, 0, 252, 0, 252, 0, 252, 251, 251, 251, 251, 251, 251, 251,
- 251, 252, 252, 252, 252, 252, 252, 252, 252, 257, 257, 258, 258, 258,
- 258, 259, 259, 260, 260, 261, 261, 262, 262, 0, 0, 263, 264, 265, 266,
- 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
- 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
- 309, 310, 251, 251, 311, 312, 313, 0, 314, 315, 252, 252, 316, 316, 317,
- 6, 318, 6, 6, 6, 319, 320, 321, 0, 322, 323, 324, 324, 324, 324, 325, 6,
- 6, 6, 251, 251, 326, 327, 0, 0, 328, 329, 252, 252, 330, 330, 0, 6, 6, 6,
- 251, 251, 331, 332, 333, 126, 334, 335, 252, 252, 336, 336, 130, 6, 6, 6,
- 0, 0, 337, 338, 339, 0, 340, 341, 342, 342, 343, 343, 344, 6, 6, 0, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 21, 5, 5, 5, 5, 5, 5, 5, 5, 6,
- 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 3, 3, 21, 21, 21, 21, 21, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 18, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 21, 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 345, 101,
- 0, 0, 346, 347, 348, 349, 350, 351, 5, 5, 5, 5, 5, 101, 345, 26, 22, 23,
- 346, 347, 348, 349, 350, 351, 5, 5, 5, 5, 5, 0, 101, 101, 101, 101, 101,
+ 31, 261, 261, 261, 261, 261, 261, 261, 261, 262, 262, 262, 262, 262, 262,
+ 262, 262, 261, 261, 261, 261, 261, 261, 0, 0, 262, 262, 262, 262, 262,
+ 262, 0, 0, 261, 261, 261, 261, 261, 261, 261, 261, 262, 262, 262, 262,
+ 262, 262, 262, 262, 261, 261, 261, 261, 261, 261, 261, 261, 262, 262,
+ 262, 262, 262, 262, 262, 262, 261, 261, 261, 261, 261, 261, 0, 0, 262,
+ 262, 262, 262, 262, 262, 0, 0, 263, 261, 264, 261, 265, 261, 266, 261, 0,
+ 262, 0, 262, 0, 262, 0, 262, 261, 261, 261, 261, 261, 261, 261, 261, 262,
+ 262, 262, 262, 262, 262, 262, 262, 267, 267, 268, 268, 268, 268, 269,
+ 269, 270, 270, 271, 271, 272, 272, 0, 0, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
+ 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 261, 261, 321, 322, 323, 0, 324, 325, 262, 262, 326, 326, 327, 6, 328, 6,
+ 6, 6, 329, 330, 331, 0, 332, 333, 334, 334, 334, 334, 335, 6, 6, 6, 261,
+ 261, 336, 337, 0, 0, 338, 339, 262, 262, 340, 340, 0, 6, 6, 6, 261, 261,
+ 341, 342, 343, 126, 344, 345, 262, 262, 346, 346, 130, 6, 6, 6, 0, 0,
+ 347, 348, 349, 0, 350, 351, 352, 352, 353, 353, 354, 6, 6, 0, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 21, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 6, 3, 3, 21, 21, 21, 21, 21, 2, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 21,
+ 21, 21, 21, 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 355, 101, 0,
+ 0, 356, 357, 358, 359, 360, 361, 5, 5, 5, 5, 5, 101, 355, 26, 22, 23,
+ 356, 357, 358, 359, 360, 361, 5, 5, 5, 5, 5, 0, 101, 101, 101, 101, 101,
101, 101, 101, 101, 101, 101, 101, 101, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 6, 6, 6, 6, 25, 6, 6, 6, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5, 5, 120, 5, 5, 5, 5, 120, 5, 5, 20, 120, 120, 120, 20, 20, 120, 120,
- 120, 20, 5, 120, 5, 5, 352, 120, 120, 120, 120, 120, 5, 5, 5, 5, 5, 5,
- 120, 5, 353, 5, 120, 5, 354, 355, 120, 120, 352, 20, 120, 120, 356, 120,
+ 120, 20, 5, 120, 5, 5, 362, 120, 120, 120, 120, 120, 5, 5, 5, 5, 5, 5,
+ 120, 5, 363, 5, 120, 5, 364, 365, 120, 120, 362, 20, 120, 120, 366, 120,
20, 55, 55, 55, 55, 20, 5, 5, 20, 20, 120, 120, 5, 5, 5, 5, 5, 120, 20,
- 20, 20, 20, 5, 5, 5, 5, 357, 5, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
- 358, 358, 358, 358, 358, 358, 359, 359, 359, 359, 359, 359, 359, 359,
- 359, 359, 359, 359, 359, 359, 359, 359, 241, 241, 241, 30, 31, 241, 241,
+ 20, 20, 20, 5, 5, 5, 5, 367, 5, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368,
+ 368, 368, 368, 368, 368, 368, 369, 369, 369, 369, 369, 369, 369, 369,
+ 369, 369, 369, 369, 369, 369, 369, 369, 241, 241, 241, 30, 31, 241, 241,
241, 241, 27, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
@@ -2762,28 +2801,28 @@ static unsigned short index2[] = {
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 22, 23, 346,
- 347, 348, 349, 350, 351, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26,
- 22, 23, 346, 347, 348, 349, 350, 351, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 26, 22, 23, 346, 347, 348, 349, 350, 351, 27, 27, 27, 27, 27, 27,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 22, 23, 356,
+ 357, 358, 359, 360, 361, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26,
+ 22, 23, 356, 357, 358, 359, 360, 361, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 26, 22, 23, 356, 357, 358, 359, 360, 361, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
- 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360,
- 360, 360, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361,
- 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361, 361,
- 345, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 22, 23, 346, 347, 348,
- 349, 350, 351, 27, 345, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370,
+ 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370,
+ 370, 370, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371,
+ 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371,
+ 355, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 22, 23, 356, 357, 358,
+ 359, 360, 361, 27, 355, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 26, 22, 23, 346, 347, 348, 349, 350, 351, 27, 26, 22,
- 23, 346, 347, 348, 349, 350, 351, 27, 26, 22, 23, 346, 347, 348, 349,
- 350, 351, 27, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 26, 22, 23, 356, 357, 358, 359, 360, 361, 27, 26, 22,
+ 23, 356, 357, 358, 359, 360, 361, 27, 26, 22, 23, 356, 357, 358, 359,
+ 360, 361, 27, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
@@ -2805,18 +2844,18 @@ static unsigned short index2[] = {
136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 0,
- 30, 31, 362, 363, 364, 365, 366, 30, 31, 30, 31, 30, 31, 367, 368, 369,
- 370, 20, 30, 31, 20, 30, 31, 20, 20, 20, 20, 20, 101, 101, 371, 371, 30,
+ 30, 31, 372, 373, 374, 375, 376, 30, 31, 30, 31, 30, 31, 377, 378, 379,
+ 380, 20, 30, 31, 20, 30, 31, 20, 20, 20, 20, 20, 101, 101, 381, 381, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 20, 5, 5, 5, 5, 5, 5, 30, 31, 30, 31,
- 25, 25, 25, 30, 31, 0, 0, 0, 0, 0, 5, 5, 5, 5, 27, 5, 5, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 0, 372, 0, 0, 0, 0, 0, 372, 0, 0, 55,
+ 25, 25, 25, 30, 31, 0, 0, 0, 0, 0, 5, 5, 5, 5, 27, 5, 5, 382, 382, 382,
+ 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
+ 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
+ 382, 382, 382, 382, 382, 382, 382, 0, 382, 0, 0, 0, 0, 0, 382, 0, 0, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2829,8 +2868,8 @@ static unsigned short index2[] = {
55, 55, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 373, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 383, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
@@ -2882,14 +2921,14 @@ static unsigned short index2[] = {
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 0, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55,
+ 5, 5, 5, 5, 5, 5, 5, 5, 0, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2898,7 +2937,7 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2908,7 +2947,7 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2916,47 +2955,47 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 374,
- 55, 55, 374, 55, 55, 55, 374, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 384,
+ 55, 55, 384, 55, 55, 55, 384, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55,
- 55, 55, 55, 55, 374, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55,
+ 55, 55, 55, 55, 384, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 374, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 384, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55,
+ 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 374, 55, 374, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 384, 55, 384, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 374, 55, 374, 374, 374, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55,
+ 55, 55, 384, 55, 384, 384, 384, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 374, 374, 374, 374, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 384, 384, 384, 384, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2964,7 +3003,7 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2973,14 +3012,14 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -2988,8 +3027,8 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 374, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 374, 374, 374, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 384, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 384, 384, 384, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3002,11 +3041,11 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3014,10 +3053,10 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3025,7 +3064,7 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3033,40 +3072,40 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55,
- 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55,
+ 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3106,26 +3145,26 @@ static unsigned short index2[] = {
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
- 31, 30, 31, 101, 20, 20, 20, 20, 20, 20, 20, 20, 30, 31, 30, 31, 375, 30,
- 31, 30, 31, 30, 31, 30, 31, 30, 31, 102, 6, 6, 30, 31, 376, 20, 55, 30,
+ 31, 30, 31, 101, 20, 20, 20, 20, 20, 20, 20, 20, 30, 31, 30, 31, 385, 30,
+ 31, 30, 31, 30, 31, 30, 31, 30, 31, 102, 6, 6, 30, 31, 386, 20, 55, 30,
31, 30, 31, 20, 20, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30,
- 31, 30, 31, 30, 31, 30, 31, 377, 378, 379, 380, 0, 0, 381, 382, 383, 384,
- 30, 31, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 31, 30, 31, 30, 31, 30, 31, 387, 388, 389, 390, 387, 0, 391, 392, 393,
+ 394, 30, 31, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 101, 101,
- 20, 55, 55, 55, 55, 55, 55, 55, 25, 55, 55, 55, 25, 55, 55, 55, 55, 25,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55,
+ 101, 101, 20, 55, 55, 55, 55, 55, 55, 55, 25, 55, 55, 55, 25, 55, 55, 55,
+ 55, 25, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 18, 18, 25, 25, 18, 5, 5, 5, 5, 0, 0, 0, 0,
+ 27, 27, 27, 27, 27, 27, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 18, 18, 25, 25, 18, 5, 5, 5, 5, 0, 0, 0, 0, 27, 27,
- 27, 27, 27, 27, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 18, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0,
- 18, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 25, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0,
- 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 25, 25, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0,
+ 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 55, 55, 55, 55, 55, 55, 5, 5, 5, 55, 5, 55, 0, 0, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 25,
@@ -3158,14 +3197,14 @@ static unsigned short index2[] = {
0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55,
55, 55, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 385, 20, 20, 20, 20, 20, 20, 20, 6, 101, 101, 101, 101, 20, 20,
- 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 386, 387, 388, 389, 390,
- 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
- 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418,
- 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,
- 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446,
- 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460,
- 461, 462, 463, 464, 465, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 20, 20, 395, 20, 20, 20, 20, 20, 20, 20, 6, 101, 101, 101, 101, 20, 20,
+ 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 396, 397, 398, 399, 400,
+ 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414,
+ 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428,
+ 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442,
+ 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456,
+ 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470,
+ 471, 472, 473, 474, 475, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 18, 18, 25, 18, 18, 25, 18, 18, 5, 18, 25, 0, 0, 7,
8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
@@ -3186,15 +3225,15 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55,
- 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55,
+ 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 374, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 384, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3208,9 +3247,9 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 466, 467, 468, 469,
- 470, 471, 472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 473, 474, 475, 476,
- 477, 0, 0, 0, 0, 0, 55, 25, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 476, 477, 478, 479,
+ 480, 481, 482, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 483, 484, 485, 486,
+ 487, 0, 0, 0, 0, 0, 55, 25, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 5,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55,
55, 0, 55, 0, 55, 55, 0, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3227,7 +3266,7 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 478, 478, 478, 478, 478, 478,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 488, 488, 488, 488, 488, 488,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3242,13 +3281,13 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 478, 478, 5, 5, 0, 0, 25, 25, 25,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 488, 488, 5, 5, 0, 0, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 6, 5, 5, 5,
5, 5, 5, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 5, 5, 5, 18, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 18, 18, 5, 5, 6, 0, 5, 6, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 0, 0, 0, 0,
- 478, 55, 478, 55, 478, 0, 478, 55, 478, 55, 478, 55, 478, 55, 478, 55,
+ 488, 55, 488, 55, 488, 0, 488, 55, 488, 55, 488, 55, 488, 55, 488, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3264,7 +3303,7 @@ static unsigned short index2[] = {
5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 102, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 479, 479, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 489, 489, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
0, 0, 0, 55, 55, 55, 55, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 0, 0, 55,
55, 55, 55, 55, 55, 0, 0, 55, 55, 55, 0, 0, 0, 5, 5, 5, 6, 5, 5, 5, 0, 5,
@@ -3290,7 +3329,7 @@ static unsigned short index2[] = {
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 27, 27, 27, 27, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 27, 27, 5, 0, 0, 0, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 27, 27, 5, 5, 5, 0, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
@@ -3320,202 +3359,223 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 5, 241, 241, 241,
241, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 480, 480,
- 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480,
- 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 480,
- 480, 480, 480, 480, 480, 480, 480, 480, 480, 480, 481, 481, 481, 481,
- 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481,
- 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, 481,
- 481, 481, 481, 481, 481, 481, 481, 481, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 490, 490,
+ 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490,
+ 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490,
+ 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 491, 491, 491, 491,
+ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
+ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
+ 491, 491, 491, 491, 491, 491, 491, 491, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 490, 490, 490, 490,
+ 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490,
+ 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490,
+ 490, 490, 490, 490, 0, 0, 0, 0, 491, 491, 491, 491, 491, 491, 491, 491,
+ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491,
+ 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 0,
+ 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55,
- 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 55, 55, 55, 55, 55, 55, 0, 0, 55, 0, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
+ 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 0, 0, 55, 0, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 0, 55, 55, 0, 0, 0, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 5, 27, 27, 27, 27,
- 27, 27, 27, 27, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 27, 27, 27, 27, 27, 27, 27, 55,
+ 55, 55, 0, 55, 55, 0, 0, 0, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 5, 27, 27, 27,
+ 27, 27, 27, 27, 27, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 5, 5, 27, 27, 27, 27, 27, 27, 27,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0, 0, 0, 0, 0, 27, 27,
- 27, 27, 27, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 27, 27, 27, 27, 27, 27, 0, 0, 0, 5, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0, 0, 0, 0, 0, 27,
+ 27, 27, 27, 27, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 27, 27, 27, 27, 27, 27, 0, 0, 0, 5, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 27, 27, 55, 55, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 27, 27, 27, 27, 27, 27,
+ 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 27, 27, 55, 55, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 55, 25, 25, 25, 0, 25, 25, 0, 0, 0, 0, 0, 25, 25, 25, 25,
- 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0,
- 0, 0, 25, 25, 25, 0, 0, 0, 0, 25, 26, 22, 23, 346, 27, 27, 27, 27, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 55, 55,
+ 27, 27, 27, 27, 27, 55, 25, 25, 25, 0, 25, 25, 0, 0, 0, 0, 0, 25, 25, 25,
+ 25, 55, 55, 55, 55, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 27, 27, 5, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 25, 25, 25, 0, 0, 0, 0, 25, 26, 22, 23, 356, 27, 27, 27, 27,
+ 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
- 55, 55, 55, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 0, 0, 0,
- 0, 27, 27, 27, 27, 27, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 27, 27, 5, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55,
+ 55, 55, 55, 55, 55, 55, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25,
+ 25, 0, 0, 0, 0, 27, 27, 27, 27, 27, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 27, 27, 27, 27, 27, 27,
- 27, 27, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 0, 0, 0, 0, 0, 27, 27, 27, 27, 27, 27, 27, 27, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
- 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 27, 27, 27,
- 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 27, 27, 27,
+ 27, 27, 27, 27, 27, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 27, 27, 27, 27, 27, 27, 27, 27,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27,
+ 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 108,
108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
- 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
+ 108, 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
- 115, 115, 115, 115, 115, 115, 115, 115, 115, 0, 0, 0, 0, 0, 0, 0, 27, 27,
- 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 0, 0, 0, 0, 0, 0,
+ 0, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 26, 22, 23, 346, 347, 348, 349, 350, 351, 27, 27, 27, 27,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 22, 23, 356, 357, 358, 359, 360, 361, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 0, 18, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 27, 27, 27, 0, 18, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 26, 22, 23, 346, 347, 348, 349, 350,
- 351, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 18,
+ 55, 55, 55, 55, 55, 55, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 26, 22, 23, 356, 357, 358,
+ 359, 360, 361, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
+ 25, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25, 25, 25,
+ 25, 18, 18, 25, 25, 5, 5, 21, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 25, 25, 25, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25, 25, 25, 25, 18, 18,
- 25, 25, 5, 5, 21, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 25, 25, 25,
+ 18, 25, 25, 25, 25, 25, 25, 25, 25, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 0, 0, 0, 0, 0, 0, 25, 25, 25, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 5, 5, 55, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 25, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 25, 25, 25, 18, 25, 25,
- 25, 25, 25, 25, 25, 25, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 5, 5, 5,
- 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 5, 5, 55, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 25, 25, 18, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 55, 55, 55,
+ 55, 5, 5, 5, 5, 5, 25, 25, 25, 5, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 55, 5, 55, 5, 5, 5, 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25, 25, 25, 18, 18, 25, 18, 25,
+ 25, 5, 5, 5, 5, 5, 5, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 0, 55, 55, 55, 55, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 5, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18,
- 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 55, 55, 55, 55, 5, 5, 5,
- 5, 5, 25, 25, 25, 5, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 55, 5,
- 55, 5, 5, 5, 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 18, 18, 18, 25, 25, 25, 18, 18, 25, 18, 25, 25, 5, 5, 5,
- 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 25, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0,
+ 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 25, 25, 18, 18,
+ 0, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 55, 0, 0, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0, 55, 55, 55, 55, 55, 0, 0,
+ 25, 55, 18, 18, 25, 18, 18, 18, 18, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0,
+ 55, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 18, 18, 0,
+ 0, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 25, 25, 25, 25, 25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 25,
+ 25, 25, 18, 25, 55, 55, 55, 55, 5, 5, 5, 5, 5, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25, 25, 25, 25, 25, 25, 18, 25,
+ 18, 18, 18, 18, 25, 25, 18, 25, 25, 55, 55, 5, 55, 0, 0, 0, 0, 0, 0, 0,
+ 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55,
- 55, 55, 55, 55, 55, 0, 55, 0, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 5, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 25, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 25, 25, 18, 18, 0, 55, 55,
- 55, 55, 55, 55, 55, 55, 0, 0, 55, 55, 0, 0, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55,
- 55, 55, 55, 55, 55, 0, 55, 55, 0, 55, 55, 55, 55, 55, 0, 0, 25, 55, 18,
- 18, 25, 18, 18, 18, 18, 0, 0, 18, 18, 0, 0, 18, 18, 18, 0, 0, 55, 0, 0,
- 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 18, 18, 0, 0, 25, 25,
- 25, 25, 25, 25, 25, 0, 0, 0, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25,
- 25, 25, 25, 25, 25, 18, 25, 18, 18, 18, 18, 25, 25, 18, 25, 25, 55, 55,
- 5, 55, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25, 25,
+ 25, 25, 0, 0, 18, 18, 18, 18, 25, 25, 18, 25, 25, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 55, 55, 55, 55, 25, 25, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 18, 18, 18, 25, 25, 25, 25, 0, 0, 18, 18, 18, 18, 25, 25, 18, 25,
- 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 55, 55, 55, 55, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 18, 18, 25, 18, 25, 25,
+ 5, 5, 5, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25,
- 18, 18, 25, 18, 25, 25, 5, 5, 5, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 25, 18, 25, 18, 18, 25, 25, 25, 25, 25, 25, 18, 25, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 25, 18, 25, 18, 18, 25, 25, 25, 25, 25,
- 25, 18, 25, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 25, 25, 25, 18, 18, 25, 25, 25, 25, 18,
+ 25, 25, 25, 25, 25, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 27,
+ 27, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 25, 25, 25, 18,
- 18, 25, 25, 25, 25, 18, 25, 25, 25, 25, 25, 0, 0, 0, 0, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 27, 27, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17,
+ 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 18, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 18, 25, 55, 5,
+ 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 0, 0, 0, 5, 5, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 0, 18, 25, 25, 25, 25, 25, 25, 25, 18, 25, 25,
+ 18, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 241, 241, 241, 241, 241, 241, 241,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
@@ -3523,94 +3583,108 @@ static unsigned short index2[] = {
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
- 241, 241, 241, 241, 241, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 0, 5, 5, 5,
+ 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 0, 0, 25, 25, 25, 25, 25, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 25, 25, 25, 25, 25,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 25, 25, 25, 25, 25, 25,
- 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 102, 102, 102, 102, 5, 5, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 27, 27, 27, 27,
- 27, 27, 27, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 102, 102,
+ 102, 102, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 0, 27, 27, 27, 27, 27, 27, 27, 0, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25,
- 25, 25, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
- 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 5, 25, 25, 5, 21,
- 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0,
+ 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 5, 25, 25, 5,
+ 21, 21, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
- 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 18, 25, 25, 25, 5, 5, 5, 18,
- 18, 18, 18, 18, 18, 21, 21, 21, 21, 21, 21, 21, 21, 25, 25, 25, 25, 25,
- 25, 25, 25, 5, 5, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 25,
+ 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 18, 18, 25, 25, 25, 5, 5, 5,
+ 18, 18, 18, 18, 18, 18, 21, 21, 21, 21, 21, 21, 21, 21, 25, 25, 25, 25,
+ 25, 25, 25, 25, 5, 5, 25, 25, 25, 25, 25, 25, 25, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 25,
25, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -3700,131 +3774,134 @@ static unsigned short index2[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25,
+ 25, 25, 0, 25, 25, 0, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 0, 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 25, 25, 25, 25, 25,
- 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 0,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0, 55, 0, 0, 55, 0, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 55, 0, 55, 0,
- 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 55, 0, 55, 0, 55, 0, 55, 55, 55, 0, 55,
- 55, 0, 55, 0, 0, 55, 0, 55, 0, 55, 0, 55, 0, 55, 0, 55, 55, 0, 55, 0, 0,
- 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 55,
- 55, 55, 55, 0, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 492, 492, 492, 492, 492, 492,
+ 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492,
+ 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492,
+ 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493,
+ 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493,
+ 493, 493, 493, 493, 493, 493, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 0,
+ 55, 0, 0, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 55, 55, 55,
+ 55, 0, 55, 0, 55, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 55, 0, 55, 0, 55, 0,
+ 55, 55, 55, 0, 55, 55, 0, 55, 0, 0, 55, 0, 55, 0, 55, 0, 55, 0, 55, 0,
+ 55, 55, 0, 55, 0, 0, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 0,
+ 55, 55, 55, 55, 0, 55, 55, 55, 55, 0, 55, 0, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 0, 0, 0, 0, 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 0, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0,
- 0, 55, 55, 55, 0, 55, 55, 55, 55, 55, 0, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
+ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 345, 345, 26, 22, 23, 346, 347, 348, 349, 350, 351, 27, 27, 0, 0, 0, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 355, 355, 26, 22, 23, 356, 357, 358, 359, 360,
+ 361, 27, 27, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 494, 494, 494, 494, 494,
+ 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494,
+ 494, 494, 494, 494, 494, 494, 494, 5, 5, 5, 5, 5, 5, 494, 494, 494, 494,
+ 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494,
+ 494, 494, 494, 494, 494, 494, 494, 494, 5, 5, 0, 0, 0, 0, 494, 494, 494,
+ 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494,
+ 494, 494, 494, 494, 494, 494, 494, 494, 494, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 0, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482,
- 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482,
- 482, 482, 5, 5, 5, 5, 5, 5, 482, 482, 482, 482, 482, 482, 482, 482, 482,
- 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482,
- 482, 482, 482, 5, 5, 0, 0, 0, 0, 482, 482, 482, 482, 482, 482, 482, 482,
- 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482, 482,
- 482, 482, 482, 482, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 5, 5,
+ 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
+ 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 374, 55,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 384, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55,
+ 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3835,32 +3912,32 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 384, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 374, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
@@ -3871,47 +3948,47 @@ static unsigned short index2[] = {
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 374, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 384, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55,
+ 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 25, 25, 25, 25, 25, 25, 25,
+ 21, 21, 21, 21, 21, 21, 21, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
@@ -3924,13 +4001,13 @@ static unsigned short index2[] = {
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
};
/* Returns the numeric value as double for Unicode characters
@@ -3996,11 +4073,13 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x11136:
case 0x111D0:
case 0x112F0:
+ case 0x11450:
case 0x114D0:
case 0x11650:
case 0x116C0:
case 0x11730:
case 0x118E0:
+ case 0x11C50:
case 0x16A60:
case 0x16B50:
case 0x1D7CE:
@@ -4008,6 +4087,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7E2:
case 0x1D7EC:
case 0x1D7F6:
+ case 0x1E950:
case 0x1F100:
case 0x1F101:
case 0x1F10B:
@@ -4108,11 +4188,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D1:
case 0x111E1:
case 0x112F1:
+ case 0x11451:
case 0x114D1:
case 0x11651:
case 0x116C1:
case 0x11731:
case 0x118E1:
+ case 0x11C51:
+ case 0x11C5A:
case 0x12415:
case 0x1241E:
case 0x1242C:
@@ -4128,17 +4211,22 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7ED:
case 0x1D7F7:
case 0x1E8C7:
+ case 0x1E951:
case 0x1F102:
case 0x2092A:
return (double) 1.0;
+ case 0x0D5C:
case 0x2152:
return (double) 1.0/10.0;
case 0x109F6:
return (double) 1.0/12.0;
case 0x09F4:
case 0x0B75:
+ case 0x0D76:
case 0xA833:
return (double) 1.0/16.0;
+ case 0x0D58:
+ return (double) 1.0/160.0;
case 0x00BD:
case 0x0B73:
case 0x0D74:
@@ -4152,6 +4240,8 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x10E7B:
case 0x12464:
return (double) 1.0/2.0;
+ case 0x0D5B:
+ return (double) 1.0/20.0;
case 0x2153:
case 0x10E7D:
case 0x1245A:
@@ -4170,6 +4260,9 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x12462:
case 0x12463:
return (double) 1.0/4.0;
+ case 0x0D59:
+ return (double) 1.0/40.0;
+ case 0x0D5E:
case 0x2155:
return (double) 1.0/5.0;
case 0x2159:
@@ -4179,6 +4272,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
return (double) 1.0/7.0;
case 0x09F5:
case 0x0B76:
+ case 0x0D77:
case 0x215B:
case 0xA834:
case 0x1245F:
@@ -4236,6 +4330,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111EA:
case 0x1173A:
case 0x118EA:
+ case 0x11C63:
case 0x16B5B:
case 0x1D369:
return (double) 10.0;
@@ -4269,6 +4364,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x10E72:
case 0x11064:
case 0x111F3:
+ case 0x11C6C:
case 0x16B5C:
return (double) 100.0;
case 0x0BF2:
@@ -4470,11 +4566,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D2:
case 0x111E2:
case 0x112F2:
+ case 0x11452:
case 0x114D2:
case 0x11652:
case 0x116C2:
case 0x11732:
case 0x118E2:
+ case 0x11C52:
+ case 0x11C5B:
case 0x12400:
case 0x12416:
case 0x1241F:
@@ -4494,6 +4593,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7EE:
case 0x1D7F8:
case 0x1E8C8:
+ case 0x1E952:
case 0x1F103:
case 0x22390:
return (double) 2.0;
@@ -4537,6 +4637,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111EB:
case 0x1173B:
case 0x118EB:
+ case 0x11C64:
case 0x1D36A:
return (double) 20.0;
case 0x1011A:
@@ -4657,11 +4758,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D3:
case 0x111E3:
case 0x112F3:
+ case 0x11453:
case 0x114D3:
case 0x11653:
case 0x116C3:
case 0x11733:
case 0x118E3:
+ case 0x11C53:
+ case 0x11C5C:
case 0x12401:
case 0x12408:
case 0x12417:
@@ -4686,6 +4790,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7EF:
case 0x1D7F9:
case 0x1E8C9:
+ case 0x1E953:
case 0x1F104:
case 0x20AFD:
case 0x20B19:
@@ -4696,10 +4801,13 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
return (double) 3.0/12.0;
case 0x09F6:
case 0x0B77:
+ case 0x0D78:
case 0xA835:
return (double) 3.0/16.0;
case 0x0F2B:
return (double) 3.0/2.0;
+ case 0x0D5D:
+ return (double) 3.0/20.0;
case 0x00BE:
case 0x09F8:
case 0x0B74:
@@ -4711,6 +4819,8 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
return (double) 3.0/5.0;
case 0x215C:
return (double) 3.0/8.0;
+ case 0x0D5A:
+ return (double) 3.0/80.0;
case 0x1374:
case 0x303A:
case 0x324A:
@@ -4724,6 +4834,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1105D:
case 0x111EC:
case 0x118EC:
+ case 0x11C65:
case 0x1D36B:
case 0x20983:
return (double) 30.0;
@@ -4836,11 +4947,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D4:
case 0x111E4:
case 0x112F4:
+ case 0x11454:
case 0x114D4:
case 0x11654:
case 0x116C4:
case 0x11734:
case 0x118E4:
+ case 0x11C54:
+ case 0x11C5D:
case 0x12402:
case 0x12409:
case 0x1240F:
@@ -4866,6 +4980,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7F0:
case 0x1D7FA:
case 0x1E8CA:
+ case 0x1E954:
case 0x1F105:
case 0x20064:
case 0x200E2:
@@ -4886,6 +5001,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1105E:
case 0x111ED:
case 0x118ED:
+ case 0x11C66:
case 0x12467:
case 0x1D36C:
case 0x2098C:
@@ -5005,11 +5121,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D5:
case 0x111E5:
case 0x112F5:
+ case 0x11455:
case 0x114D5:
case 0x11655:
case 0x116C5:
case 0x11735:
case 0x118E5:
+ case 0x11C55:
+ case 0x11C5E:
case 0x12403:
case 0x1240A:
case 0x12410:
@@ -5031,6 +5150,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7F1:
case 0x1D7FB:
case 0x1E8CB:
+ case 0x1E955:
case 0x1F106:
case 0x20121:
return (double) 5.0;
@@ -5067,6 +5187,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1105F:
case 0x111EE:
case 0x118EE:
+ case 0x11C67:
case 0x12468:
case 0x1D36D:
return (double) 50.0;
@@ -5172,11 +5293,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D6:
case 0x111E6:
case 0x112F6:
+ case 0x11456:
case 0x114D6:
case 0x11656:
case 0x116C6:
case 0x11736:
case 0x118E6:
+ case 0x11C56:
+ case 0x11C5F:
case 0x12404:
case 0x1240B:
case 0x12411:
@@ -5194,6 +5318,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7F2:
case 0x1D7FC:
case 0x1E8CC:
+ case 0x1E956:
case 0x1F107:
case 0x20AEA:
return (double) 6.0;
@@ -5208,6 +5333,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x11060:
case 0x111EF:
case 0x118EF:
+ case 0x11C68:
case 0x1D36E:
return (double) 60.0;
case 0x1011E:
@@ -5293,11 +5419,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D7:
case 0x111E7:
case 0x112F7:
+ case 0x11457:
case 0x114D7:
case 0x11657:
case 0x116C7:
case 0x11737:
case 0x118E7:
+ case 0x11C57:
+ case 0x11C60:
case 0x12405:
case 0x1240C:
case 0x12412:
@@ -5316,6 +5445,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7F3:
case 0x1D7FD:
case 0x1E8CD:
+ case 0x1E957:
case 0x1F108:
case 0x20001:
return (double) 7.0;
@@ -5334,6 +5464,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x11061:
case 0x111F0:
case 0x118F0:
+ case 0x11C69:
case 0x1D36F:
return (double) 70.0;
case 0x1011F:
@@ -5417,11 +5548,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D8:
case 0x111E8:
case 0x112F8:
+ case 0x11458:
case 0x114D8:
case 0x11658:
case 0x116C8:
case 0x11738:
case 0x118E8:
+ case 0x11C58:
+ case 0x11C61:
case 0x12406:
case 0x1240D:
case 0x12413:
@@ -5439,6 +5573,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7F4:
case 0x1D7FE:
case 0x1E8CE:
+ case 0x1E958:
case 0x1F109:
return (double) 8.0;
case 0x109FD:
@@ -5451,6 +5586,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x11062:
case 0x111F1:
case 0x118F1:
+ case 0x11C6A:
case 0x1D370:
return (double) 80.0;
case 0x10120:
@@ -5535,11 +5671,14 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x111D9:
case 0x111E9:
case 0x112F9:
+ case 0x11459:
case 0x114D9:
case 0x11659:
case 0x116C9:
case 0x11739:
case 0x118E9:
+ case 0x11C59:
+ case 0x11C62:
case 0x12407:
case 0x1240E:
case 0x12414:
@@ -5559,6 +5698,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x1D7F5:
case 0x1D7FF:
case 0x1E8CF:
+ case 0x1E959:
case 0x1F10A:
case 0x2F890:
return (double) 9.0;
@@ -5574,6 +5714,7 @@ double _PyUnicode_ToNumeric(Py_UCS4 ch)
case 0x11063:
case 0x111F2:
case 0x118F2:
+ case 0x11C6B:
case 0x1D371:
return (double) 90.0;
case 0x10121:
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index 7e6f36458b..ab6b235255 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -265,7 +265,7 @@ insert_head(PyWeakReference *newref, PyWeakReference **list)
}
static int
-parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
+parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
PyObject **obp, PyObject **callbackp)
{
return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
@@ -453,7 +453,7 @@ proxy_checkref(PyWeakReference *proxy)
method(PyObject *proxy) { \
_Py_IDENTIFIER(special); \
UNWRAP(proxy); \
- return _PyObject_CallMethodId(proxy, &PyId_##special, ""); \
+ return _PyObject_CallMethodId(proxy, &PyId_##special, NULL); \
}