📄 object.c
字号:
/* Portions Copyright (c) 2005 Nokia Corporation */
/* Generic object operations; and implementation of None (NoObject) */
#include "Python.h"
#ifdef macintosh
#include "macglue.h"
#endif
/* just for trashcan: */
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"
#if defined( Py_TRACE_REFS ) || defined( Py_REF_DEBUG )
DL_IMPORT(long) _Py_RefTotal;
#endif
#ifndef SYMBIAN
DL_IMPORT(int) Py_DivisionWarningFlag;
#endif
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
These are used by the individual routines for object creation.
Do not call them otherwise, they do not initialize the object! */
#ifdef COUNT_ALLOCS
const static PyTypeObject *type_list;
extern int tuple_zero_allocs, fast_tuple_allocs;
extern int quick_int_allocs, quick_neg_int_allocs;
extern int null_strings, one_strings;
DL_EXPORT(void)
dump_counts(void)
{
PyTypeObject *tp;
for (tp = type_list; tp; tp = tp->tp_next)
fprintf(stderr, "%s alloc'd: %d, freed: %d, max in use: %d\n",
tp->tp_name, tp->tp_allocs, tp->tp_frees,
tp->tp_maxalloc);
fprintf(stderr, "fast tuple allocs: %d, empty: %d\n",
fast_tuple_allocs, tuple_zero_allocs);
fprintf(stderr, "fast int allocs: pos: %d, neg: %d\n",
quick_int_allocs, quick_neg_int_allocs);
fprintf(stderr, "null strings: %d, 1-strings: %d\n",
null_strings, one_strings);
}
DL_EXPORT(PyObject *)
get_counts(void)
{
PyTypeObject *tp;
PyObject *result;
PyObject *v;
result = PyList_New(0);
if (result == NULL)
return NULL;
for (tp = type_list; tp; tp = tp->tp_next) {
v = Py_BuildValue("(siii)", tp->tp_name, tp->tp_allocs,
tp->tp_frees, tp->tp_maxalloc);
if (v == NULL) {
Py_DECREF(result);
return NULL;
}
if (PyList_Append(result, v) < 0) {
Py_DECREF(v);
Py_DECREF(result);
return NULL;
}
Py_DECREF(v);
}
return result;
}
DL_EXPORT(void)
inc_count(PyTypeObject *tp)
{
if (tp->tp_allocs == 0) {
/* first time; insert in linked list */
if (tp->tp_next != NULL) /* sanity check */
Py_FatalError("XXX inc_count sanity check");
tp->tp_next = type_list;
/* Note that as of Python 2.2, heap-allocated type objects
* can go away, but this code requires that they stay alive
* until program exit. That's why we're careful with
* refcounts here. type_list gets a new reference to tp,
* while ownership of the reference type_list used to hold
* (if any) was transferred to tp->tp_next in the line above.
* tp is thus effectively immortal after this.
*/
Py_INCREF(tp);
type_list = tp;
}
tp->tp_allocs++;
if (tp->tp_allocs - tp->tp_frees > tp->tp_maxalloc)
tp->tp_maxalloc = tp->tp_allocs - tp->tp_frees;
}
#endif
DL_EXPORT(PyObject *)
PyObject_Init(PyObject *op, PyTypeObject *tp)
{
if (op == NULL)
return PyErr_NoMemory();
/* Any changes should be reflected in PyObject_INIT (objimpl.h) */
op->ob_type = tp;
_Py_NewReference(op);
return op;
}
DL_EXPORT(PyVarObject *)
PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, int size)
{
if (op == NULL)
return (PyVarObject *) PyErr_NoMemory();
/* Any changes should be reflected in PyObject_INIT_VAR */
op->ob_size = size;
op->ob_type = tp;
_Py_NewReference((PyObject *)op);
return op;
}
DL_EXPORT(PyObject *)
_PyObject_New(PyTypeObject *tp)
{
PyObject *op;
op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
if (op == NULL)
return PyErr_NoMemory();
return PyObject_INIT(op, tp);
}
DL_EXPORT(PyVarObject *)
_PyObject_NewVar(PyTypeObject *tp, int nitems)
{
PyVarObject *op;
const size_t size = _PyObject_VAR_SIZE(tp, nitems);
op = (PyVarObject *) PyObject_MALLOC(size);
if (op == NULL)
return (PyVarObject *)PyErr_NoMemory();
return PyObject_INIT_VAR(op, tp, nitems);
}
DL_EXPORT(void)
_PyObject_Del(PyObject *op)
{
PyObject_FREE(op);
}
DL_EXPORT(int)
PyObject_Print(PyObject *op, FILE *fp, int flags)
{
int ret = 0;
if (PyErr_CheckSignals())
return -1;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return -1;
}
#endif
clearerr(fp); /* Clear any previous error condition */
if (op == NULL) {
fprintf(fp, "<nil>");
}
else {
if (op->ob_refcnt <= 0)
fprintf(fp, "<refcnt %u at %p>",
op->ob_refcnt, op);
else if (op->ob_type->tp_print == NULL) {
PyObject *s;
if (flags & Py_PRINT_RAW)
s = PyObject_Str(op);
else
s = PyObject_Repr(op);
if (s == NULL)
ret = -1;
else {
ret = PyObject_Print(s, fp, Py_PRINT_RAW);
}
Py_XDECREF(s);
}
else
ret = (*op->ob_type->tp_print)(op, fp, flags);
}
if (ret == 0) {
if (ferror(fp)) {
PyErr_SetFromErrno(PyExc_IOError);
clearerr(fp);
ret = -1;
}
}
return ret;
}
/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */
DL_EXPORT(void)
_PyObject_Dump(PyObject* op)
{
if (op == NULL)
fprintf(stderr, "NULL\n");
else {
fprintf(stderr, "object : ");
(void)PyObject_Print(op, stderr, 0);
fprintf(stderr, "\n"
"type : %s\n"
"refcount: %d\n"
"address : %p\n",
op->ob_type==NULL ? "NULL" : op->ob_type->tp_name,
op->ob_refcnt,
op);
}
}
DL_EXPORT(PyObject *)
PyObject_Repr(PyObject *v)
{
if (PyErr_CheckSignals())
return NULL;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return NULL;
}
#endif
if (v == NULL)
return PyString_FromString("<NULL>");
else if (v->ob_type->tp_repr == NULL)
return PyString_FromFormat("<%s object at %p>",
v->ob_type->tp_name, v);
else {
PyObject *res;
res = (*v->ob_type->tp_repr)(v);
if (res == NULL)
return NULL;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(res)) {
PyObject* str;
str = PyUnicode_AsUnicodeEscapeString(res);
Py_DECREF(res);
if (str)
res = str;
else
return NULL;
}
#endif
if (!PyString_Check(res)) {
PyErr_Format(PyExc_TypeError,
"__repr__ returned non-string (type %.200s)",
res->ob_type->tp_name);
Py_DECREF(res);
return NULL;
}
return res;
}
}
DL_EXPORT(PyObject *)
PyObject_Str(PyObject *v)
{
PyObject *res;
if (v == NULL)
return PyString_FromString("<NULL>");
if (PyString_CheckExact(v)) {
Py_INCREF(v);
return v;
}
if (v->ob_type->tp_str == NULL)
return PyObject_Repr(v);
res = (*v->ob_type->tp_str)(v);
if (res == NULL)
return NULL;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(res)) {
PyObject* str;
str = PyUnicode_AsEncodedString(res, NULL, NULL);
Py_DECREF(res);
if (str)
res = str;
else
return NULL;
}
#endif
if (!PyString_Check(res)) {
PyErr_Format(PyExc_TypeError,
"__str__ returned non-string (type %.200s)",
res->ob_type->tp_name);
Py_DECREF(res);
return NULL;
}
return res;
}
#ifdef Py_USING_UNICODE
DL_EXPORT(PyObject *)
PyObject_Unicode(PyObject *v)
{
PyObject *res;
if (v == NULL)
res = PyString_FromString("<NULL>");
if (PyUnicode_CheckExact(v)) {
Py_INCREF(v);
return v;
}
if (PyUnicode_Check(v)) {
/* For a Unicode subtype that's not a Unicode object,
return a true Unicode object with the same data. */
return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(v),
PyUnicode_GET_SIZE(v));
}
if (PyString_Check(v)) {
Py_INCREF(v);
res = v;
}
else {
PyObject *func;
#ifndef SYMBIAN
static PyObject *unicodestr;
#else
#define unicodestr (PYTHON_GLOBALS->unicodestr)
#endif
/* XXX As soon as we have a tp_unicode slot, we should
check this before trying the __unicode__
method. */
if (unicodestr == NULL) {
unicodestr = PyString_InternFromString(
"__unicode__");
if (unicodestr == NULL)
return NULL;
}
func = PyObject_GetAttr(v, unicodestr);
if (func != NULL) {
res = PyEval_CallObject(func, (PyObject *)NULL);
Py_DECREF(func);
}
else {
PyErr_Clear();
if (v->ob_type->tp_str != NULL)
res = (*v->ob_type->tp_str)(v);
else
res = PyObject_Repr(v);
}
}
if (res == NULL)
return NULL;
if (!PyUnicode_Check(res)) {
PyObject *str;
str = PyUnicode_FromEncodedObject(res, NULL, "strict");
Py_DECREF(res);
if (str)
res = str;
else
return NULL;
}
return res;
}
#endif
/* Macro to get the tp_richcompare field of a type if defined */
#define RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) \
? (t)->tp_richcompare : NULL)
/* Map rich comparison operators to their swapped version, e.g. LT --> GT */
const static int swapped_op[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
/* Try a genuine rich comparison, returning an object. Return:
NULL for exception;
NotImplemented if this particular rich comparison is not implemented or
undefined;
some object not equal to NotImplemented if it is implemented
(this latter object may not be a Boolean).
*/
static PyObject *
try_rich_compare(PyObject *v, PyObject *w, int op)
{
richcmpfunc f;
PyObject *res;
if (v->ob_type != w->ob_type &&
PyType_IsSubtype(w->ob_type, v->ob_type) &&
(f = RICHCOMPARE(w->ob_type)) != NULL) {
res = (*f)(w, v, swapped_op[op]);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if ((f = RICHCOMPARE(v->ob_type)) != NULL) {
res = (*f)(v, w, op);
if (res != Py_NotImplemented)
return res;
Py_DECREF(res);
}
if ((f = RICHCOMPARE(w->ob_type)) != NULL) {
return (*f)(w, v, swapped_op[op]);
}
res = Py_NotImplemented;
Py_INCREF(res);
return res;
}
/* Try a genuine rich comparison, returning an int. Return:
-1 for exception (including the case where try_rich_compare() returns an
object that's not a Boolean);
0 if the outcome is false;
1 if the outcome is true;
2 if this particular rich comparison is not implemented or undefined.
*/
static int
try_rich_compare_bool(PyObject *v, PyObject *w, int op)
{
PyObject *res;
int ok;
if (RICHCOMPARE(v->ob_type) == NULL && RICHCOMPARE(w->ob_type) == NULL)
return 2; /* Shortcut, avoid INCREF+DECREF */
res = try_rich_compare(v, w, op);
if (res == NULL)
return -1;
if (res == Py_NotImplemented) {
Py_DECREF(res);
return 2;
}
ok = PyObject_IsTrue(res);
Py_DECREF(res);
return ok;
}
/* Try rich comparisons to determine a 3-way comparison. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular rich comparison is not implemented or undefined.
*/
static int
try_rich_to_3way_compare(PyObject *v, PyObject *w)
{
const static struct { int op; int outcome; } tries[3] = {
/* Try this operator, and if it is true, use this outcome: */
{Py_EQ, 0},
{Py_LT, -1},
{Py_GT, 1},
};
int i;
if (RICHCOMPARE(v->ob_type) == NULL && RICHCOMPARE(w->ob_type) == NULL)
return 2; /* Shortcut */
for (i = 0; i < 3; i++) {
switch (try_rich_compare_bool(v, w, tries[i].op)) {
case -1:
return -2;
case 1:
return tries[i].outcome;
}
}
return 2;
}
/* Try a 3-way comparison, returning an int. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular 3-way comparison is not implemented or undefined.
*/
static int
try_3way_compare(PyObject *v, PyObject *w)
{
int c;
cmpfunc f;
/* Comparisons involving instances are given to instance_compare,
which has the same return conventions as this function. */
f = v->ob_type->tp_compare;
if (PyInstance_Check(v))
return (*f)(v, w);
if (PyInstance_Check(w))
return (*w->ob_type->tp_compare)(v, w);
/* If both have the same (non-NULL) tp_compare, use it. */
if (f != NULL && f == w->ob_type->tp_compare) {
c = (*f)(v, w);
if (c < 0 && PyErr_Occurred())
return -1;
return c < 0 ? -1 : c > 0 ? 1 : 0;
}
/* If either tp_compare is _PyObject_SlotCompare, that's safe. */
if (f == _PyObject_SlotCompare ||
w->ob_type->tp_compare == _PyObject_SlotCompare)
return _PyObject_SlotCompare(v, w);
/* Try coercion; if it fails, give up */
c = PyNumber_CoerceEx(&v, &w);
if (c < 0)
return -2;
if (c > 0)
return 2;
/* Try v's comparison, if defined */
if ((f = v->ob_type->tp_compare) != NULL) {
c = (*f)(v, w);
Py_DECREF(v);
Py_DECREF(w);
if (c < 0 && PyErr_Occurred())
return -2;
return c < 0 ? -1 : c > 0 ? 1 : 0;
}
/* Try w's comparison, if defined */
if ((f = w->ob_type->tp_compare) != NULL) {
c = (*f)(w, v); /* swapped! */
Py_DECREF(v);
Py_DECREF(w);
if (c < 0 && PyErr_Occurred())
return -2;
return c < 0 ? 1 : c > 0 ? -1 : 0; /* negated! */
}
/* No comparison defined */
Py_DECREF(v);
Py_DECREF(w);
return 2;
}
/* Final fallback 3-way comparison, returning an int. Return:
-2 if an error occurred;
-1 if v < w;
0 if v == w;
1 if v > w.
*/
static int
default_3way_compare(PyObject *v, PyObject *w)
{
int c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -