⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dictobject.c

📁 python s60 1.4.5版本的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * insert new keys or remove them.
 */
DL_EXPORT(int)
PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
{
	register dictobject *mp;
	register long hash;
	register int n_used;

	if (!PyDict_Check(op)) {
		PyErr_BadInternalCall();
		return -1;
	}
	mp = (dictobject *)op;
#ifdef CACHE_HASH
	if (PyString_CheckExact(key)) {
#ifdef INTERN_STRINGS
		if (((PyStringObject *)key)->ob_sinterned != NULL) {
			key = ((PyStringObject *)key)->ob_sinterned;
			hash = ((PyStringObject *)key)->ob_shash;
		}
		else
#endif
		{
			hash = ((PyStringObject *)key)->ob_shash;
			if (hash == -1)
				hash = PyObject_Hash(key);
		}
	}
	else
#endif
	{
		hash = PyObject_Hash(key);
		if (hash == -1)
			return -1;
	}
	assert(mp->ma_fill <= mp->ma_mask);  /* at least one empty slot */
	n_used = mp->ma_used;
	Py_INCREF(value);
	Py_INCREF(key);
	insertdict(mp, key, hash, value);
	/* If we added a key, we can safely resize.  Otherwise skip this!
	 * If fill >= 2/3 size, adjust size.  Normally, this doubles the
	 * size, but it's also possible for the dict to shrink (if ma_fill is
	 * much larger than ma_used, meaning a lot of dict keys have been
	 * deleted).
	 */
	if (mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2) {
		if (dictresize(mp, mp->ma_used*2) != 0)
			return -1;
	}
	return 0;
}

DL_EXPORT(int)
PyDict_DelItem(PyObject *op, PyObject *key)
{
	register dictobject *mp;
	register long hash;
	register dictentry *ep;
	PyObject *old_value, *old_key;
#ifdef SYMBIAN
	SPy_Python_globals* pyglobals = PYTHON_GLOBALS; // avoid TLS reads
#endif
	if (!PyDict_Check(op)) {
		PyErr_BadInternalCall();
		return -1;
	}
#ifdef CACHE_HASH
	if (!PyString_CheckExact(key) ||
	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
	{
		hash = PyObject_Hash(key);
		if (hash == -1)
			return -1;
	}
	mp = (dictobject *)op;
	ep = (mp->ma_lookup)(mp, key, hash);
	if (ep->me_value == NULL) {
		PyErr_SetObject(PyExc_KeyError, key);
		return -1;
	}
	old_key = ep->me_key;
	Py_INCREF(dummy);
	ep->me_key = dummy;
	old_value = ep->me_value;
	ep->me_value = NULL;
	mp->ma_used--;
	Py_DECREF(old_value);
	Py_DECREF(old_key);
	return 0;
}

DL_EXPORT(void)
PyDict_Clear(PyObject *op)
{
	dictobject *mp;
	dictentry *ep, *table;
	int table_is_malloced;
	int fill;
	dictentry small_copy[PyDict_MINSIZE];
#ifdef Py_DEBUG
	int i, n;
#endif

	if (!PyDict_Check(op))
		return;
	mp = (dictobject *)op;
#ifdef Py_DEBUG
	n = mp->ma_mask + 1;
	i = 0;
#endif

	table = mp->ma_table;
	assert(table != NULL);
	table_is_malloced = table != mp->ma_smalltable;

	/* This is delicate.  During the process of clearing the dict,
	 * decrefs can cause the dict to mutate.  To avoid fatal confusion
	 * (voice of experience), we have to make the dict empty before
	 * clearing the slots, and never refer to anything via mp->xxx while
	 * clearing.
	 */
	fill = mp->ma_fill;
	if (table_is_malloced)
		EMPTY_TO_MINSIZE(mp);

	else if (fill > 0) {
		/* It's a small table with something that needs to be cleared.
		 * Afraid the only safe way is to copy the dict entries into
		 * another small table first.
		 */
		memcpy(small_copy, table, sizeof(small_copy));
		table = small_copy;
		EMPTY_TO_MINSIZE(mp);
	}
	/* else it's a small table that's already empty */

	/* Now we can finally clear things.  If C had refcounts, we could
	 * assert that the refcount on table is 1 now, i.e. that this function
	 * has unique access to it, so decref side-effects can't alter it.
	 */
	for (ep = table; fill > 0; ++ep) {
#ifdef Py_DEBUG
		assert(i < n);
		++i;
#endif
		if (ep->me_key) {
			--fill;
			Py_DECREF(ep->me_key);
			Py_XDECREF(ep->me_value);
		}
#ifdef Py_DEBUG
		else
			assert(ep->me_value == NULL);
#endif
	}

	if (table_is_malloced)
		PyMem_DEL(table);
}

/* 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
 * delete keys), via PyDict_SetItem().
 */
DL_EXPORT(int)
PyDict_Next(PyObject *op, int *ppos, PyObject **pkey, PyObject **pvalue)
{
	int i;
	register dictobject *mp;
	if (!PyDict_Check(op))
		return 0;
	mp = (dictobject *)op;
	i = *ppos;
	if (i < 0)
		return 0;
	while (i <= mp->ma_mask && mp->ma_table[i].me_value == NULL)
		i++;
	*ppos = i+1;
	if (i > mp->ma_mask)
		return 0;
	if (pkey)
		*pkey = mp->ma_table[i].me_key;
	if (pvalue)
		*pvalue = mp->ma_table[i].me_value;
	return 1;
}

/* Methods */

static void
dict_dealloc(register dictobject *mp)
{
	register dictentry *ep;
	int fill = mp->ma_fill;
 	PyObject_GC_UnTrack(mp);
	Py_TRASHCAN_SAFE_BEGIN(mp)
	for (ep = mp->ma_table; fill > 0; ep++) {
		if (ep->me_key) {
			--fill;
			Py_DECREF(ep->me_key);
			Py_XDECREF(ep->me_value);
		}
	}
	if (mp->ma_table != mp->ma_smalltable)
		PyMem_DEL(mp->ma_table);
	mp->ob_type->tp_free((PyObject *)mp);
	Py_TRASHCAN_SAFE_END(mp)
}

static int
dict_print(register dictobject *mp, register FILE *fp, register int flags)
{
	register int i;
	register int any;

	i = Py_ReprEnter((PyObject*)mp);
	if (i != 0) {
		if (i < 0)
			return i;
		fprintf(fp, "{...}");
		return 0;
	}

	fprintf(fp, "{");
	any = 0;
	for (i = 0; i <= mp->ma_mask; i++) {
		dictentry *ep = mp->ma_table + i;
		PyObject *pvalue = ep->me_value;
		if (pvalue != NULL) {
			/* Prevent PyObject_Repr from deleting value during
			   key format */
			Py_INCREF(pvalue);
			if (any++ > 0)
				fprintf(fp, ", ");
			if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {
				Py_DECREF(pvalue);
				Py_ReprLeave((PyObject*)mp);
				return -1;
			}
			fprintf(fp, ": ");
			if (PyObject_Print(pvalue, fp, 0) != 0) {
				Py_DECREF(pvalue);
				Py_ReprLeave((PyObject*)mp);
				return -1;
			}
			Py_DECREF(pvalue);
		}
	}
	fprintf(fp, "}");
	Py_ReprLeave((PyObject*)mp);
	return 0;
}

static PyObject *
dict_repr(dictobject *mp)
{
	int i;
	PyObject *s, *temp, *colon = NULL;
	PyObject *pieces = NULL, *result = NULL;
	PyObject *key, *value;

	i = Py_ReprEnter((PyObject *)mp);
	if (i != 0) {
		return i > 0 ? PyString_FromString("{...}") : NULL;
	}

	if (mp->ma_used == 0) {
		result = PyString_FromString("{}");
		goto Done;
	}

	pieces = PyList_New(0);
	if (pieces == NULL)
		goto Done;

	colon = PyString_FromString(": ");
	if (colon == NULL)
		goto Done;

	/* Do repr() on each key+value pair, and insert ": " between them.
	   Note that repr may mutate the dict. */
	i = 0;
	while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
		int status;
		/* Prevent repr from deleting value during key format. */
		Py_INCREF(value);
		s = PyObject_Repr(key);
		PyString_Concat(&s, colon);
		PyString_ConcatAndDel(&s, PyObject_Repr(value));
		Py_DECREF(value);
		if (s == NULL)
			goto Done;
		status = PyList_Append(pieces, s);
		Py_DECREF(s);  /* append created a new ref */
		if (status < 0)
			goto Done;
	}

	/* Add "{}" decorations to the first and last items. */
	assert(PyList_GET_SIZE(pieces) > 0);
	s = PyString_FromString("{");
	if (s == NULL)
		goto Done;
	temp = PyList_GET_ITEM(pieces, 0);
	PyString_ConcatAndDel(&s, temp);
	PyList_SET_ITEM(pieces, 0, s);
	if (s == NULL)
		goto Done;

	s = PyString_FromString("}");
	if (s == NULL)
		goto Done;
	temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
	PyString_ConcatAndDel(&temp, s);
	PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
	if (temp == NULL)
		goto Done;

	/* Paste them all together with ", " between. */
	s = PyString_FromString(", ");
	if (s == NULL)
		goto Done;
	result = _PyString_Join(s, pieces);
	Py_DECREF(s);

Done:
	Py_XDECREF(pieces);
	Py_XDECREF(colon);
	Py_ReprLeave((PyObject *)mp);
	return result;
}

static int
dict_length(dictobject *mp)
{
	return mp->ma_used;
}

static PyObject *
dict_subscript(dictobject *mp, register PyObject *key)
{
	PyObject *v;
	long hash;
	assert(mp->ma_table != NULL);
#ifdef CACHE_HASH
	if (!PyString_CheckExact(key) ||
	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
#endif
	{
		hash = PyObject_Hash(key);
		if (hash == -1)
			return NULL;
	}
	v = (mp->ma_lookup)(mp, key, hash) -> me_value;
	if (v == NULL)
		PyErr_SetObject(PyExc_KeyError, key);
	else
		Py_INCREF(v);
	return v;
}

static int
dict_ass_sub(dictobject *mp, PyObject *v, PyObject *w)
{
	if (w == NULL)
		return PyDict_DelItem((PyObject *)mp, v);
	else
		return PyDict_SetItem((PyObject *)mp, v, w);
}

static const PyMappingMethods dict_as_mapping = {
	(inquiry)dict_length, /*mp_length*/
	(binaryfunc)dict_subscript, /*mp_subscript*/
	(objobjargproc)dict_ass_sub, /*mp_ass_subscript*/
};

static PyObject *
dict_keys(register dictobject *mp)
{
	register PyObject *v;
	register int i, j, n;

  again:
	n = mp->ma_used;
	v = PyList_New(n);
	if (v == NULL)
		return NULL;
	if (n != mp->ma_used) {
		/* Durnit.  The allocations caused the dict to resize.
		 * Just start over, this shouldn't normally happen.
		 */
		Py_DECREF(v);
		goto again;
	}
	for (i = 0, j = 0; i <= mp->ma_mask; i++) {
		if (mp->ma_table[i].me_value != NULL) {
			PyObject *key = mp->ma_table[i].me_key;
			Py_INCREF(key);
			PyList_SET_ITEM(v, j, key);
			j++;
		}
	}
	return v;
}

static PyObject *
dict_values(register dictobject *mp)
{
	register PyObject *v;
	register int i, j, n;

  again:
	n = mp->ma_used;
	v = PyList_New(n);
	if (v == NULL)
		return NULL;
	if (n != mp->ma_used) {
		/* Durnit.  The allocations caused the dict to resize.
		 * Just start over, this shouldn't normally happen.
		 */
		Py_DECREF(v);
		goto again;
	}
	for (i = 0, j = 0; i <= mp->ma_mask; i++) {
		if (mp->ma_table[i].me_value != NULL) {
			PyObject *value = mp->ma_table[i].me_value;
			Py_INCREF(value);
			PyList_SET_ITEM(v, j, value);
			j++;
		}
	}
	return v;
}

static PyObject *
dict_items(register dictobject *mp)
{
	register PyObject *v;
	register int i, j, n;
	PyObject *item, *key, *value;

	/* Preallocate the list of tuples, to avoid allocations during
	 * the loop over the items, which could trigger GC, which
	 * could resize the dict. :-(
	 */
  again:
	n = mp->ma_used;
	v = PyList_New(n);
	if (v == NULL)
		return NULL;
	for (i = 0; i < n; i++) {
		item = PyTuple_New(2);
		if (item == NULL) {
			Py_DECREF(v);
			return NULL;
		}
		PyList_SET_ITEM(v, i, item);
	}
	if (n != mp->ma_used) {
		/* Durnit.  The allocations caused the dict to resize.
		 * Just start over, this shouldn't normally happen.
		 */
		Py_DECREF(v);
		goto again;
	}
	/* Nothing we do below makes any function calls. */
	for (i = 0, j = 0; i <= mp->ma_mask; i++) {
		if (mp->ma_table[i].me_value != NULL) {
			key = mp->ma_table[i].me_key;
			value = mp->ma_table[i].me_value;
			item = PyList_GET_ITEM(v, j);
			Py_INCREF(key);
			PyTuple_SET_ITEM(item, 0, key);
			Py_INCREF(value);
			PyTuple_SET_ITEM(item, 1, value);
			j++;
		}
	}
	assert(j == n);
	return v;
}

static PyObject *
dict_update(PyObject *mp, PyObject *other)
{
	if (PyDict_Update(mp, other) < 0)
		return NULL;
	Py_INCREF(Py_None);
	return Py_None;
}

/* Update unconditionally replaces existing items.
   Merge has a 3rd argument 'override'; if set, it acts like Update,
   otherwise it leaves existing items unchanged.

   PyDict_{Update,Merge} update/merge from a mapping object.

   PyDict_MergeFromSeq2 updates/merges from any iterable object
   producing iterable objects of length 2.
*/

DL_EXPORT(int)
PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
{
	PyObject *it;	/* iter(seq2) */
	int i;		/* index into seq2 of current element */
	PyObject *item;	/* seq2[i] */
	PyObject *fast;	/* item as a 2-tuple or 2-list */

	assert(d != NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -