summaryrefslogtreecommitdiffstats
path: root/Objects/unicodeobject.c
diff options
context:
space:
mode:
authorEric Smith <eric@trueblade.com>2007-08-26 22:27:13 (GMT)
committerEric Smith <eric@trueblade.com>2007-08-26 22:27:13 (GMT)
commit7ade6485abde95c5cc9676ad3e476ba3aca98037 (patch)
treefa5710899c3e376f89eb6a6460e06f3feee62d58 /Objects/unicodeobject.c
parent2bf4d5ba2881725bb7695bc0573bab0e2ca4fec5 (diff)
downloadcpython-7ade6485abde95c5cc9676ad3e476ba3aca98037.zip
cpython-7ade6485abde95c5cc9676ad3e476ba3aca98037.tar.gz
cpython-7ade6485abde95c5cc9676ad3e476ba3aca98037.tar.bz2
PEP 3101: Completed string.Formatter class. Reimplemented field_name to object transformation.
Diffstat (limited to 'Objects/unicodeobject.c')
-rw-r--r--Objects/unicodeobject.c165
1 files changed, 157 insertions, 8 deletions
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index d10d26f..1421bb2 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -9161,9 +9161,8 @@ typedef struct {
static void
formatteriter_dealloc(formatteriterobject *it)
{
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->str);
- PyObject_GC_Del(it);
+ Py_XDECREF(it->str);
+ PyObject_FREE(it);
}
/* returns a tuple:
@@ -9313,7 +9312,7 @@ _unicodeformatter_iterator(PyObject *str)
{
formatteriterobject *it;
- it = PyObject_GC_New(formatteriterobject, &PyFormatterIter_Type);
+ it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
if (it == NULL)
return NULL;
@@ -9326,17 +9325,167 @@ _unicodeformatter_iterator(PyObject *str)
PyUnicode_AS_UNICODE(str),
PyUnicode_GET_SIZE(str));
- _PyObject_GC_TRACK(it);
return (PyObject *)it;
}
-PyObject *
-_unicodeformatter_lookup(PyObject *field_name, PyObject *args,
- PyObject *kwargs)
+/********************* FieldName Iterator ************************/
+
+/* this is used to implement string.Formatter.vparse(). it parses
+ the field name into attribute and item values. */
+
+typedef struct {
+ PyObject_HEAD
+
+ /* we know this to be a unicode object, but since we just keep
+ it around to keep the object alive, having it as PyObject
+ is okay */
+ PyObject *str;
+
+ FieldNameIterator it_field;
+} fieldnameiterobject;
+
+static void
+fieldnameiter_dealloc(fieldnameiterobject *it)
{
+ Py_XDECREF(it->str);
+ PyObject_FREE(it);
+}
+
+/* returns a tuple:
+ (is_attr, value)
+ is_attr is true if we used attribute syntax (e.g., '.foo')
+ false if we used index syntax (e.g., '[foo]')
+ value is an integer or string
+*/
+static PyObject *
+fieldnameiter_next(fieldnameiterobject *it)
+{
+ int result;
+ int is_attr;
+ Py_ssize_t idx;
+ SubString name;
+
+ result = FieldNameIterator_next(&it->it_field, &is_attr,
+ &idx, &name);
+ if (result == 0 || result == 1) {
+ /* if 0, error has already been set, if 1, iterator is empty */
+ return NULL;
+ } else {
+ PyObject* result = NULL;
+ PyObject* is_attr_obj = NULL;
+ PyObject* obj = NULL;
+
+ is_attr_obj = PyBool_FromLong(is_attr);
+ if (is_attr_obj == NULL)
+ goto error;
+
+ /* either an integer or a string */
+ if (idx != -1)
+ obj = PyInt_FromSsize_t(idx);
+ else
+ obj = STRINGLIB_NEW(name.ptr, name.end - name.ptr);
+ if (obj == NULL)
+ goto error;
+
+ /* return a tuple of values */
+ result = PyTuple_Pack(2, is_attr_obj, obj);
+ if (result == NULL)
+ goto error;
+
+ return result;
+
+ error:
+ Py_XDECREF(result);
+ Py_XDECREF(is_attr_obj);
+ Py_XDECREF(obj);
+ return NULL;
+ }
return NULL;
}
+static PyMethodDef fieldnameiter_methods[] = {
+ {NULL, NULL} /* sentinel */
+};
+
+static PyTypeObject PyFieldNameIter_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "fieldnameiterator", /* tp_name */
+ sizeof(fieldnameiterobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)fieldnameiter_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 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, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)fieldnameiter_next, /* tp_iternext */
+ fieldnameiter_methods, /* tp_methods */
+ 0};
+
+PyObject *
+_unicodeformatter_field_name_split(PyObject *field_name)
+{
+ SubString first;
+ Py_ssize_t first_idx;
+ fieldnameiterobject *it;
+
+ PyObject *first_obj = NULL;
+ PyObject *it_obj = NULL;
+ PyObject *result;
+
+ it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
+ if (it == NULL)
+ goto error;
+ it->str = NULL;
+ it_obj = (PyObject *)it;
+
+ if (!field_name_split(STRINGLIB_STR(field_name),
+ STRINGLIB_LEN(field_name),
+ &first, &first_idx, &it->it_field))
+ goto error;
+
+ /* first becomes an integer, if possible, else a string */
+ if (first_idx != -1)
+ first_obj = PyInt_FromSsize_t(first_idx);
+ else
+ /* convert "first" into a string object */
+ first_obj = STRINGLIB_NEW(first.ptr, first.end - first.ptr);
+ if (first_obj == NULL)
+ goto error;
+
+ /* take ownership, give the object to the iterator. this is
+ just to keep the field_name alive */
+ Py_INCREF(field_name);
+ it->str = field_name;
+
+ /* return a tuple of values */
+ result = PyTuple_Pack(2, first_obj, it_obj);
+ if (result == NULL)
+ goto error;
+
+ return result;
+error:
+ Py_XDECREF(it_obj);
+ Py_XDECREF(first_obj);
+ return NULL;
+}
/********************* Unicode Iterator **************************/