annotate Objects/stringlib/unicode_format.h @ 87690:66c1c9f32567 default tip

Add use_weakref option to functools.lru_cache The use_weakref option makes lru_cache create weak references to the function arguments when creating the cache key, which prevents them from staying in the memory forever even after all other references to them are gone. This is a proof of concept for http://bugs.python.org/issue19859
author Radomir Dopieralski <devel@sheep.art.pl>
date Tue, 03 Dec 2013 16:02:48 +0100
parents e27684eed3b6
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
2 unicode_format.h -- implementation of str.format().
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
3 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
4
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
5 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
6 /*********** Global data structures and forward declarations *********/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
7 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
8
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
9 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
10 A SubString consists of the characters between two string or
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
11 unicode pointers.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
12 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
13 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
14 PyObject *str; /* borrowed reference */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
15 Py_ssize_t start, end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
16 } SubString;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
17
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
18
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
19 typedef enum {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
20 ANS_INIT,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
21 ANS_AUTO,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
22 ANS_MANUAL
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
23 } AutoNumberState; /* Keep track if we're auto-numbering fields */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
24
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
25 /* Keeps track of our auto-numbering state, and which number field we're on */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
26 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
27 AutoNumberState an_state;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
28 int an_field_number;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
29 } AutoNumber;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
30
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
31
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
32 /* forward declaration for recursion */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
33 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
34 build_string(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
35 int recursion_depth, AutoNumber *auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
36
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
37
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
38
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
39 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
40 /************************** Utility functions ************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
41 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
42
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
43 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
44 AutoNumber_Init(AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
45 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
46 auto_number->an_state = ANS_INIT;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
47 auto_number->an_field_number = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
48 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
49
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
50 /* fill in a SubString from a pointer and length */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
51 Py_LOCAL_INLINE(void)
72750
1a0715386d27 Fix compilation warnings under 64-bit Windows
Antoine Pitrou <solipsis@pitrou.net>
parents: 72475
diff changeset
52 SubString_init(SubString *str, PyObject *s, Py_ssize_t start, Py_ssize_t end)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
53 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
54 str->str = s;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
55 str->start = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
56 str->end = end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
57 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
58
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
59 /* return a new string. if str->str is NULL, return None */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
60 Py_LOCAL_INLINE(PyObject *)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
61 SubString_new_object(SubString *str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
62 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
63 if (str->str == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
64 Py_INCREF(Py_None);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
65 return Py_None;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
66 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
67 return PyUnicode_Substring(str->str, str->start, str->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
68 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
69
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
70 /* return a new string. if str->str is NULL, return None */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
71 Py_LOCAL_INLINE(PyObject *)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
72 SubString_new_object_or_empty(SubString *str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
73 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
74 if (str->str == NULL) {
73803
d855329d0f72 Replace PyUnicode_FromUnicode(NULL, 0) by PyUnicode_New(0, 0)
Victor Stinner <victor.stinner@haypocalc.com>
parents: 73337
diff changeset
75 return PyUnicode_New(0, 0);
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
76 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
77 return SubString_new_object(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
78 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
79
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
80 /* Return 1 if an error has been detected switching between automatic
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
81 field numbering and manual field specification, else return 0. Set
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
82 ValueError on error. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
83 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
84 autonumber_state_error(AutoNumberState state, int field_name_is_empty)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
85 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
86 if (state == ANS_MANUAL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
87 if (field_name_is_empty) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
88 PyErr_SetString(PyExc_ValueError, "cannot switch from "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
89 "manual field specification to "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
90 "automatic field numbering");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
91 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
92 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
93 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
94 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
95 if (!field_name_is_empty) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
96 PyErr_SetString(PyExc_ValueError, "cannot switch from "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
97 "automatic field numbering to "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
98 "manual field specification");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
99 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
100 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
101 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
102 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
103 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
104
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
105
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
106 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
107 /*********** Format string parsing -- integers and identifiers *********/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
108 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
109
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
110 static Py_ssize_t
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
111 get_integer(const SubString *str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
112 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
113 Py_ssize_t accumulator = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
114 Py_ssize_t digitval;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
115 Py_ssize_t i;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
116
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
117 /* empty string is an error */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
118 if (str->start >= str->end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
119 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
120
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
121 for (i = str->start; i < str->end; i++) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
122 digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ_CHAR(str->str, i));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
123 if (digitval < 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
124 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
125 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
126 Detect possible overflow before it happens:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
127
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
128 accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
129 accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
130 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
131 if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
132 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
133 "Too many decimal digits in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
134 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
135 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
136 accumulator = accumulator * 10 + digitval;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
137 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
138 return accumulator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
139 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
140
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
141 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
142 /******** Functions to get field objects and specification strings ******/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
143 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
144
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
145 /* do the equivalent of obj.name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
146 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
147 getattr(PyObject *obj, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
148 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
149 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
150 PyObject *str = SubString_new_object(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
151 if (str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
152 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
153 newobj = PyObject_GetAttr(obj, str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
154 Py_DECREF(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
155 return newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
156 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
157
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
158 /* do the equivalent of obj[idx], where obj is a sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
159 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
160 getitem_sequence(PyObject *obj, Py_ssize_t idx)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
161 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
162 return PySequence_GetItem(obj, idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
163 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
164
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
165 /* do the equivalent of obj[idx], where obj is not a sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
166 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
167 getitem_idx(PyObject *obj, Py_ssize_t idx)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
168 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
169 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
170 PyObject *idx_obj = PyLong_FromSsize_t(idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
171 if (idx_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
172 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
173 newobj = PyObject_GetItem(obj, idx_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
174 Py_DECREF(idx_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
175 return newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
176 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
177
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
178 /* do the equivalent of obj[name] */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
179 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
180 getitem_str(PyObject *obj, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
181 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
182 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
183 PyObject *str = SubString_new_object(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
184 if (str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
185 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
186 newobj = PyObject_GetItem(obj, str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
187 Py_DECREF(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
188 return newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
189 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
190
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
191 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
192 /* the entire string we're parsing. we assume that someone else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
193 is managing its lifetime, and that it will exist for the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
194 lifetime of the iterator. can be empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
195 SubString str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
196
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
197 /* index to where we are inside field_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
198 Py_ssize_t index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
199 } FieldNameIterator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
200
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
201
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
202 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
203 FieldNameIterator_init(FieldNameIterator *self, PyObject *s,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
204 Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
205 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
206 SubString_init(&self->str, s, start, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
207 self->index = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
208 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
209 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
210
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
211 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
212 _FieldNameIterator_attr(FieldNameIterator *self, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
213 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
214 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
215
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
216 name->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
217 name->start = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
218
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
219 /* return everything until '.' or '[' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
220 while (self->index < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
221 c = PyUnicode_READ_CHAR(self->str.str, self->index++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
222 switch (c) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
223 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
224 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
225 /* backup so that we this character will be seen next time */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
226 self->index--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
227 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
228 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
229 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
230 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
231 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
232 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
233 /* end of string is okay */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
234 name->end = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
235 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
236 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
237
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
238 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
239 _FieldNameIterator_item(FieldNameIterator *self, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
240 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
241 int bracket_seen = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
242 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
243
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
244 name->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
245 name->start = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
246
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
247 /* return everything until ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
248 while (self->index < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
249 c = PyUnicode_READ_CHAR(self->str.str, self->index++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
250 switch (c) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
251 case ']':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
252 bracket_seen = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
253 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
254 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
255 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
256 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
257 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
258 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
259 /* make sure we ended with a ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
260 if (!bracket_seen) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
261 PyErr_SetString(PyExc_ValueError, "Missing ']' in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
262 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
263 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
264
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
265 /* end of string is okay */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
266 /* don't include the ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
267 name->end = self->index-1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
268 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
269 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
270
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
271 /* returns 0 on error, 1 on non-error termination, and 2 if it returns a value */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
272 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
273 FieldNameIterator_next(FieldNameIterator *self, int *is_attribute,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
274 Py_ssize_t *name_idx, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
275 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
276 /* check at end of input */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
277 if (self->index >= self->str.end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
278 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
279
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
280 switch (PyUnicode_READ_CHAR(self->str.str, self->index++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
281 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
282 *is_attribute = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
283 if (_FieldNameIterator_attr(self, name) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
284 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
285 *name_idx = -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
286 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
287 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
288 *is_attribute = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
289 if (_FieldNameIterator_item(self, name) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
290 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
291 *name_idx = get_integer(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
292 if (*name_idx == -1 && PyErr_Occurred())
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
293 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
294 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
295 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
296 /* Invalid character follows ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
297 PyErr_SetString(PyExc_ValueError, "Only '.' or '[' may "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
298 "follow ']' in format field specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
299 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
300 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
301
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
302 /* empty string is an error */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
303 if (name->start == name->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
304 PyErr_SetString(PyExc_ValueError, "Empty attribute in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
305 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
306 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
307
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
308 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
309 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
310
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
311
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
312 /* input: field_name
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
313 output: 'first' points to the part before the first '[' or '.'
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
314 'first_idx' is -1 if 'first' is not an integer, otherwise
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
315 it's the value of first converted to an integer
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
316 'rest' is an iterator to return the rest
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
317 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
318 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
319 field_name_split(PyObject *str, Py_ssize_t start, Py_ssize_t end, SubString *first,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
320 Py_ssize_t *first_idx, FieldNameIterator *rest,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
321 AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
322 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
323 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
324 Py_ssize_t i = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
325 int field_name_is_empty;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
326 int using_numeric_index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
327
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
328 /* find the part up until the first '.' or '[' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
329 while (i < end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
330 switch (c = PyUnicode_READ_CHAR(str, i++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
331 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
332 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
333 /* backup so that we this character is available to the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
334 "rest" iterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
335 i--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
336 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
337 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
338 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
339 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
340 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
341 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
342
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
343 /* set up the return values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
344 SubString_init(first, str, start, i);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
345 FieldNameIterator_init(rest, str, i, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
346
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
347 /* see if "first" is an integer, in which case it's used as an index */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
348 *first_idx = get_integer(first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
349 if (*first_idx == -1 && PyErr_Occurred())
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
350 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
351
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
352 field_name_is_empty = first->start >= first->end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
353
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
354 /* If the field name is omitted or if we have a numeric index
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
355 specified, then we're doing numeric indexing into args. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
356 using_numeric_index = field_name_is_empty || *first_idx != -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
357
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
358 /* We always get here exactly one time for each field we're
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
359 processing. And we get here in field order (counting by left
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
360 braces). So this is the perfect place to handle automatic field
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
361 numbering if the field name is omitted. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
362
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
363 /* Check if we need to do the auto-numbering. It's not needed if
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
364 we're called from string.Format routines, because it's handled
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
365 in that class by itself. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
366 if (auto_number) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
367 /* Initialize our auto numbering state if this is the first
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
368 time we're either auto-numbering or manually numbering. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
369 if (auto_number->an_state == ANS_INIT && using_numeric_index)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
370 auto_number->an_state = field_name_is_empty ?
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
371 ANS_AUTO : ANS_MANUAL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
372
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
373 /* Make sure our state is consistent with what we're doing
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
374 this time through. Only check if we're using a numeric
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
375 index. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
376 if (using_numeric_index)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
377 if (autonumber_state_error(auto_number->an_state,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
378 field_name_is_empty))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
379 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
380 /* Zero length field means we want to do auto-numbering of the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
381 fields. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
382 if (field_name_is_empty)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
383 *first_idx = (auto_number->an_field_number)++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
384 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
385
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
386 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
387 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
388
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
389
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
390 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
391 get_field_object returns the object inside {}, before the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
392 format_spec. It handles getindex and getattr lookups and consumes
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
393 the entire input string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
394 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
395 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
396 get_field_object(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
397 AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
398 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
399 PyObject *obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
400 int ok;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
401 int is_attribute;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
402 SubString name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
403 SubString first;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
404 Py_ssize_t index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
405 FieldNameIterator rest;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
406
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
407 if (!field_name_split(input->str, input->start, input->end, &first,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
408 &index, &rest, auto_number)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
409 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
410 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
411
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
412 if (index == -1) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
413 /* look up in kwargs */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
414 PyObject *key = SubString_new_object(&first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
415 if (key == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
416 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
417
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
418 /* Use PyObject_GetItem instead of PyDict_GetItem because this
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
419 code is no longer just used with kwargs. It might be passed
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
420 a non-dict when called through format_map. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
421 if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
422 PyErr_SetObject(PyExc_KeyError, key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
423 Py_DECREF(key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
424 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
425 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
426 Py_DECREF(key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
427 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
428 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
429 /* If args is NULL, we have a format string with a positional field
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
430 with only kwargs to retrieve it from. This can only happen when
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
431 used with format_map(), where positional arguments are not
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
432 allowed. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
433 if (args == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
434 PyErr_SetString(PyExc_ValueError, "Format string contains "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
435 "positional fields");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
436 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
437 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
438
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
439 /* look up in args */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
440 obj = PySequence_GetItem(args, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
441 if (obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
442 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
443 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
444
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
445 /* iterate over the rest of the field_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
446 while ((ok = FieldNameIterator_next(&rest, &is_attribute, &index,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
447 &name)) == 2) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
448 PyObject *tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
449
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
450 if (is_attribute)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
451 /* getattr lookup "." */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
452 tmp = getattr(obj, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
453 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
454 /* getitem lookup "[]" */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
455 if (index == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
456 tmp = getitem_str(obj, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
457 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
458 if (PySequence_Check(obj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
459 tmp = getitem_sequence(obj, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
460 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
461 /* not a sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
462 tmp = getitem_idx(obj, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
463 if (tmp == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
464 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
465
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
466 /* assign to obj */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
467 Py_DECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
468 obj = tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
469 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
470 /* end of iterator, this is the non-error case */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
471 if (ok == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
472 return obj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
473 error:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
474 Py_XDECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
475 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
476 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
477
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
478 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
479 /***************** Field rendering functions **************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
480 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
481
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
482 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
483 render_field() is the main function in this section. It takes the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
484 field object and field specification string generated by
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
485 get_field_and_spec, and renders the field into the output string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
486
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
487 render_field calls fieldobj.__format__(format_spec) method, and
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
488 appends to the output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
489 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
490 static int
76851
0d9067cde462 Rename unicode_write_t structure and its methods to "_PyUnicodeWriter"
Victor Stinner <victor.stinner@gmail.com>
parents: 76850
diff changeset
491 render_field(PyObject *fieldobj, SubString *format_spec, _PyUnicodeWriter *writer)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
492 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
493 int ok = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
494 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
495 PyObject *format_spec_object = NULL;
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
496 int (*formatter) (_PyUnicodeWriter*, PyObject *, PyObject *, Py_ssize_t, Py_ssize_t) = NULL;
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
497 int err;
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
498
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
499 /* If we know the type exactly, skip the lookup of __format__ and just
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
500 call the formatter directly. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
501 if (PyUnicode_CheckExact(fieldobj))
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
502 formatter = _PyUnicode_FormatAdvancedWriter;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
503 else if (PyLong_CheckExact(fieldobj))
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
504 formatter = _PyLong_FormatAdvancedWriter;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
505 else if (PyFloat_CheckExact(fieldobj))
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
506 formatter = _PyFloat_FormatAdvancedWriter;
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
507 else if (PyComplex_CheckExact(fieldobj))
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
508 formatter = _PyComplex_FormatAdvancedWriter;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
509
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
510 if (formatter) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
511 /* we know exactly which formatter will be called when __format__ is
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
512 looked up, so call it directly, instead. */
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
513 err = formatter(writer, fieldobj, format_spec->str,
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
514 format_spec->start, format_spec->end);
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
515 return (err == 0);
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
516 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
517 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
518 /* We need to create an object out of the pointers we have, because
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
519 __format__ takes a string/unicode object for format_spec. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
520 if (format_spec->str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
521 format_spec_object = PyUnicode_Substring(format_spec->str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
522 format_spec->start,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
523 format_spec->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
524 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
525 format_spec_object = PyUnicode_New(0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
526 if (format_spec_object == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
527 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
528
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
529 result = PyObject_Format(fieldobj, format_spec_object);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
530 }
76850
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
531 if (result == NULL)
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
532 goto done;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
533
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
534 if (_PyUnicodeWriter_WriteStr(writer, result) == -1)
76850
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
535 goto done;
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
536 ok = 1;
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
537
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
538 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
539 Py_XDECREF(format_spec_object);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
540 Py_XDECREF(result);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
541 return ok;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
542 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
543
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
544 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
545 parse_field(SubString *str, SubString *field_name, SubString *format_spec,
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
546 int *format_spec_needs_expanding, Py_UCS4 *conversion)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
547 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
548 /* Note this function works if the field name is zero length,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
549 which is good. Zero length field names are handled later, in
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
550 field_name_split. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
551
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
552 Py_UCS4 c = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
553
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
554 /* initialize these, as they may be empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
555 *conversion = '\0';
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
556 SubString_init(format_spec, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
557
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
558 /* Search for the field name. it's terminated by the end of
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
559 the string, or a ':' or '!' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
560 field_name->str = str->str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
561 field_name->start = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
562 while (str->start < str->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
563 switch ((c = PyUnicode_READ_CHAR(str->str, str->start++))) {
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
564 case '{':
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
565 PyErr_SetString(PyExc_ValueError, "unexpected '{' in field name");
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
566 return 0;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
567 case '[':
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
568 for (; str->start < str->end; str->start++)
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
569 if (PyUnicode_READ_CHAR(str->str, str->start) == ']')
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
570 break;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
571 continue;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
572 case '}':
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
573 case ':':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
574 case '!':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
575 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
576 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
577 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
578 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
579 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
580 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
581
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
582 field_name->end = str->start - 1;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
583 if (c == '!' || c == ':') {
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
584 Py_ssize_t count;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
585 /* we have a format specifier and/or a conversion */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
586 /* don't include the last character */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
587
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
588 /* see if there's a conversion specifier */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
589 if (c == '!') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
590 /* there must be another character present */
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
591 if (str->start >= str->end) {
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
592 PyErr_SetString(PyExc_ValueError,
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
593 "end of string while looking for conversion "
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
594 "specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
595 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
596 }
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
597 *conversion = PyUnicode_READ_CHAR(str->str, str->start++);
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
598
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
599 if (str->start < str->end) {
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
600 c = PyUnicode_READ_CHAR(str->str, str->start++);
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
601 if (c == '}')
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
602 return 1;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
603 if (c != ':') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
604 PyErr_SetString(PyExc_ValueError,
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
605 "expected ':' after conversion specifier");
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
606 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
607 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
608 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
609 }
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
610 format_spec->str = str->str;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
611 format_spec->start = str->start;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
612 count = 1;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
613 while (str->start < str->end) {
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
614 switch ((c = PyUnicode_READ_CHAR(str->str, str->start++))) {
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
615 case '{':
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
616 *format_spec_needs_expanding = 1;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
617 count++;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
618 break;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
619 case '}':
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
620 count--;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
621 if (count == 0) {
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
622 format_spec->end = str->start - 1;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
623 return 1;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
624 }
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
625 break;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
626 default:
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
627 break;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
628 }
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
629 }
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
630
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
631 PyErr_SetString(PyExc_ValueError, "unmatched '{' in format spec");
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
632 return 0;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
633 }
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
634 else if (c != '}') {
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
635 PyErr_SetString(PyExc_ValueError, "expected '}' before end of string");
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
636 return 0;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
637 }
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
638
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
639 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
640 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
641
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
642 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
643 /******* Output string allocation and escape-to-markup processing ******/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
644 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
645
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
646 /* MarkupIterator breaks the string into pieces of either literal
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
647 text, or things inside {} that need to be marked up. it is
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
648 designed to make it easy to wrap a Python iterator around it, for
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
649 use with the Formatter class */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
650
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
651 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
652 SubString str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
653 } MarkupIterator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
654
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
655 static int
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
656 MarkupIterator_init(MarkupIterator *self, PyObject *str,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
657 Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
658 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
659 SubString_init(&self->str, str, start, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
660 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
661 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
662
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
663 /* returns 0 on error, 1 on non-error termination, and 2 if it got a
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
664 string (or something to be expanded) */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
665 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
666 MarkupIterator_next(MarkupIterator *self, SubString *literal,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
667 int *field_present, SubString *field_name,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
668 SubString *format_spec, Py_UCS4 *conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
669 int *format_spec_needs_expanding)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
670 {
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
671 int at_end;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
672 Py_UCS4 c = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
673 Py_ssize_t start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
674 Py_ssize_t len;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
675 int markup_follows = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
676
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
677 /* initialize all of the output variables */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
678 SubString_init(literal, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
679 SubString_init(field_name, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
680 SubString_init(format_spec, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
681 *conversion = '\0';
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
682 *format_spec_needs_expanding = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
683 *field_present = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
684
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
685 /* No more input, end of iterator. This is the normal exit
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
686 path. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
687 if (self->str.start >= self->str.end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
688 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
689
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
690 start = self->str.start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
691
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
692 /* First read any literal text. Read until the end of string, an
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
693 escaped '{' or '}', or an unescaped '{'. In order to never
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
694 allocate memory and so I can just pass pointers around, if
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
695 there's an escaped '{' or '}' then we'll return the literal
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
696 including the brace, but no format object. The next time
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
697 through, we'll return the rest of the literal, skipping past
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
698 the second consecutive brace. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
699 while (self->str.start < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
700 switch (c = PyUnicode_READ_CHAR(self->str.str, self->str.start++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
701 case '{':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
702 case '}':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
703 markup_follows = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
704 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
705 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
706 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
707 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
708 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
709 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
710
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
711 at_end = self->str.start >= self->str.end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
712 len = self->str.start - start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
713
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
714 if ((c == '}') && (at_end ||
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
715 (c != PyUnicode_READ_CHAR(self->str.str,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
716 self->str.start)))) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
717 PyErr_SetString(PyExc_ValueError, "Single '}' encountered "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
718 "in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
719 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
720 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
721 if (at_end && c == '{') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
722 PyErr_SetString(PyExc_ValueError, "Single '{' encountered "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
723 "in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
724 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
725 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
726 if (!at_end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
727 if (c == PyUnicode_READ_CHAR(self->str.str, self->str.start)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
728 /* escaped } or {, skip it in the input. there is no
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
729 markup object following us, just this literal text */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
730 self->str.start++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
731 markup_follows = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
732 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
733 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
734 len--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
735 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
736
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
737 /* record the literal text */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
738 literal->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
739 literal->start = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
740 literal->end = start + len;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
741
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
742 if (!markup_follows)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
743 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
744
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
745 /* this is markup; parse the field */
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
746 *field_present = 1;
83819
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
747 if (!parse_field(&self->str, field_name, format_spec,
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
748 format_spec_needs_expanding, conversion))
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
749 return 0;
f914130c15bb rewrite the parsing of field names to be more consistent wrt recursive expansion
Benjamin Peterson <benjamin@python.org>
parents: 83818
diff changeset
750 return 2;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
751 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
752
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
753
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
754 /* do the !r or !s conversion on obj */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
755 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
756 do_conversion(PyObject *obj, Py_UCS4 conversion)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
757 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
758 /* XXX in pre-3.0, do we need to convert this to unicode, since it
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
759 might have returned a string? */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
760 switch (conversion) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
761 case 'r':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
762 return PyObject_Repr(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
763 case 's':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
764 return PyObject_Str(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
765 case 'a':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
766 return PyObject_ASCII(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
767 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
768 if (conversion > 32 && conversion < 127) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
769 /* It's the ASCII subrange; casting to char is safe
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
770 (assuming the execution character set is an ASCII
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
771 superset). */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
772 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
773 "Unknown conversion specifier %c",
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
774 (char)conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
775 } else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
776 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
777 "Unknown conversion specifier \\x%x",
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
778 (unsigned int)conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
779 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
780 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
781 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
782
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
783 /* given:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
784
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
785 {field_name!conversion:format_spec}
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
786
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
787 compute the result and write it to output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
788 format_spec_needs_expanding is an optimization. if it's false,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
789 just output the string directly, otherwise recursively expand the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
790 format_spec string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
791
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
792 field_name is allowed to be zero length, in which case we
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
793 are doing auto field numbering.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
794 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
795
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
796 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
797 output_markup(SubString *field_name, SubString *format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
798 int format_spec_needs_expanding, Py_UCS4 conversion,
76851
0d9067cde462 Rename unicode_write_t structure and its methods to "_PyUnicodeWriter"
Victor Stinner <victor.stinner@gmail.com>
parents: 76850
diff changeset
799 _PyUnicodeWriter *writer, PyObject *args, PyObject *kwargs,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
800 int recursion_depth, AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
801 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
802 PyObject *tmp = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
803 PyObject *fieldobj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
804 SubString expanded_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
805 SubString *actual_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
806 int result = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
807
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
808 /* convert field_name to an object */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
809 fieldobj = get_field_object(field_name, args, kwargs, auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
810 if (fieldobj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
811 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
812
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
813 if (conversion != '\0') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
814 tmp = do_conversion(fieldobj, conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
815 if (tmp == NULL || PyUnicode_READY(tmp) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
816 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
817
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
818 /* do the assignment, transferring ownership: fieldobj = tmp */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
819 Py_DECREF(fieldobj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
820 fieldobj = tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
821 tmp = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
822 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
823
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
824 /* if needed, recurively compute the format_spec */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
825 if (format_spec_needs_expanding) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
826 tmp = build_string(format_spec, args, kwargs, recursion_depth-1,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
827 auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
828 if (tmp == NULL || PyUnicode_READY(tmp) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
829 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
830
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
831 /* note that in the case we're expanding the format string,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
832 tmp must be kept around until after the call to
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
833 render_field. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
834 SubString_init(&expanded_format_spec, tmp, 0, PyUnicode_GET_LENGTH(tmp));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
835 actual_format_spec = &expanded_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
836 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
837 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
838 actual_format_spec = format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
839
76820
7be716a47e9d Close #14716: str.format() now uses the new "unicode writer" API instead of the
Victor Stinner <victor.stinner@gmail.com>
parents: 75876
diff changeset
840 if (render_field(fieldobj, actual_format_spec, writer) == 0)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
841 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
842
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
843 result = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
844
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
845 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
846 Py_XDECREF(fieldobj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
847 Py_XDECREF(tmp);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
848
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
849 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
850 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
851
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
852 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
853 do_markup is the top-level loop for the format() method. It
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
854 searches through the format string for escapes to markup codes, and
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
855 calls other functions to move non-markup text to the output,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
856 and to perform the markup to the output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
857 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
858 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
859 do_markup(SubString *input, PyObject *args, PyObject *kwargs,
76851
0d9067cde462 Rename unicode_write_t structure and its methods to "_PyUnicodeWriter"
Victor Stinner <victor.stinner@gmail.com>
parents: 76850
diff changeset
860 _PyUnicodeWriter *writer, int recursion_depth, AutoNumber *auto_number)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
861 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
862 MarkupIterator iter;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
863 int format_spec_needs_expanding;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
864 int result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
865 int field_present;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
866 SubString literal;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
867 SubString field_name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
868 SubString format_spec;
83066
b5d5f422299f Add _PyUnicodeWriter_WriteSubstring() function
Victor Stinner <victor.stinner@gmail.com>
parents: 82340
diff changeset
869 Py_UCS4 conversion;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
870
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
871 MarkupIterator_init(&iter, input->str, input->start, input->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
872 while ((result = MarkupIterator_next(&iter, &literal, &field_present,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
873 &field_name, &format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
874 &conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
875 &format_spec_needs_expanding)) == 2) {
83066
b5d5f422299f Add _PyUnicodeWriter_WriteSubstring() function
Victor Stinner <victor.stinner@gmail.com>
parents: 82340
diff changeset
876 if (literal.end != literal.start) {
b5d5f422299f Add _PyUnicodeWriter_WriteSubstring() function
Victor Stinner <victor.stinner@gmail.com>
parents: 82340
diff changeset
877 if (!field_present && iter.str.start == iter.str.end)
b5d5f422299f Add _PyUnicodeWriter_WriteSubstring() function
Victor Stinner <victor.stinner@gmail.com>
parents: 82340
diff changeset
878 writer->overallocate = 0;
b5d5f422299f Add _PyUnicodeWriter_WriteSubstring() function
Victor Stinner <victor.stinner@gmail.com>
parents: 82340
diff changeset
879 if (_PyUnicodeWriter_WriteSubstring(writer, literal.str,
b5d5f422299f Add _PyUnicodeWriter_WriteSubstring() function
Victor Stinner <victor.stinner@gmail.com>
parents: 82340
diff changeset
880 literal.start, literal.end) < 0)
76850
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
881 return 0;
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
882 }
6c8a117f8966 Issue #14744: Inline unicode_writer_write_char() and unicode_write_str()
Victor Stinner <victor.stinner@gmail.com>
parents: 76820
diff changeset
883
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
884 if (field_present) {
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
885 if (iter.str.start == iter.str.end)
77351
09736ae1c314 Issue #14993: Use standard "unsigned char" instead of a unsigned char bitfield
Victor Stinner <victor.stinner@gmail.com>
parents: 77223
diff changeset
886 writer->overallocate = 0;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
887 if (!output_markup(&field_name, &format_spec,
76820
7be716a47e9d Close #14716: str.format() now uses the new "unicode writer" API instead of the
Victor Stinner <victor.stinner@gmail.com>
parents: 75876
diff changeset
888 format_spec_needs_expanding, conversion, writer,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
889 args, kwargs, recursion_depth, auto_number))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
890 return 0;
77223
22b56b0b8619 Issue #14744: Use the new _PyUnicodeWriter internal API to speed up str%args and str.format(args)
Victor Stinner <victor.stinner@gmail.com>
parents: 76851
diff changeset
891 }
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
892 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
893 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
894 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
895
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
896
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
897 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
898 build_string allocates the output string and then
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
899 calls do_markup to do the heavy lifting.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
900 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
901 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
902 build_string(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
903 int recursion_depth, AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
904 {
76851
0d9067cde462 Rename unicode_write_t structure and its methods to "_PyUnicodeWriter"
Victor Stinner <victor.stinner@gmail.com>
parents: 76850
diff changeset
905 _PyUnicodeWriter writer;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
906
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
907 /* check the recursion level */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
908 if (recursion_depth <= 0) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
909 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
910 "Max string recursion exceeded");
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
911 return NULL;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
912 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
913
83433
edf029fc9591 Close #17694: Add minimum length to _PyUnicodeWriter
Victor Stinner <victor.stinner@gmail.com>
parents: 83066
diff changeset
914 _PyUnicodeWriter_Init(&writer);
edf029fc9591 Close #17694: Add minimum length to _PyUnicodeWriter
Victor Stinner <victor.stinner@gmail.com>
parents: 83066
diff changeset
915 writer.overallocate = 1;
edf029fc9591 Close #17694: Add minimum length to _PyUnicodeWriter
Victor Stinner <victor.stinner@gmail.com>
parents: 83066
diff changeset
916 writer.min_length = PyUnicode_GET_LENGTH(input->str) + 100;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
917
76820
7be716a47e9d Close #14716: str.format() now uses the new "unicode writer" API instead of the
Victor Stinner <victor.stinner@gmail.com>
parents: 75876
diff changeset
918 if (!do_markup(input, args, kwargs, &writer, recursion_depth,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
919 auto_number)) {
76851
0d9067cde462 Rename unicode_write_t structure and its methods to "_PyUnicodeWriter"
Victor Stinner <victor.stinner@gmail.com>
parents: 76850
diff changeset
920 _PyUnicodeWriter_Dealloc(&writer);
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
921 return NULL;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
922 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
923
76851
0d9067cde462 Rename unicode_write_t structure and its methods to "_PyUnicodeWriter"
Victor Stinner <victor.stinner@gmail.com>
parents: 76850
diff changeset
924 return _PyUnicodeWriter_Finish(&writer);
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
925 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
926
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
927 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
928 /*********** main routine ***********************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
929 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
930
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
931 /* this is the main entry point */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
932 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
933 do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
934 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
935 SubString input;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
936
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
937 /* PEP 3101 says only 2 levels, so that
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
938 "{0:{1}}".format('abc', 's') # works
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
939 "{0:{1:{2}}}".format('abc', 's', '') # fails
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
940 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
941 int recursion_depth = 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
942
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
943 AutoNumber auto_number;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
944
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
945 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
946 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
947
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
948 AutoNumber_Init(&auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
949 SubString_init(&input, self, 0, PyUnicode_GET_LENGTH(self));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
950 return build_string(&input, args, kwargs, recursion_depth, &auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
951 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
952
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
953 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
954 do_string_format_map(PyObject *self, PyObject *obj)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
955 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
956 return do_string_format(self, NULL, obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
957 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
958
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
959
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
960 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
961 /*********** formatteriterator ******************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
962 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
963
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
964 /* This is used to implement string.Formatter.vparse(). It exists so
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
965 Formatter can share code with the built in unicode.format() method.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
966 It's really just a wrapper around MarkupIterator that is callable
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
967 from Python. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
968
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
969 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
970 PyObject_HEAD
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
971 PyObject *str;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
972 MarkupIterator it_markup;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
973 } formatteriterobject;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
974
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
975 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
976 formatteriter_dealloc(formatteriterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
977 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
978 Py_XDECREF(it->str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
979 PyObject_FREE(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
980 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
981
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
982 /* returns a tuple:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
983 (literal, field_name, format_spec, conversion)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
984
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
985 literal is any literal text to output. might be zero length
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
986 field_name is the string before the ':'. might be None
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
987 format_spec is the string after the ':'. mibht be None
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
988 conversion is either None, or the string after the '!'
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
989 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
990 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
991 formatteriter_next(formatteriterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
992 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
993 SubString literal;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
994 SubString field_name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
995 SubString format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
996 Py_UCS4 conversion;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
997 int format_spec_needs_expanding;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
998 int field_present;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
999 int result = MarkupIterator_next(&it->it_markup, &literal, &field_present,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1000 &field_name, &format_spec, &conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1001 &format_spec_needs_expanding);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1002
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1003 /* all of the SubString objects point into it->str, so no
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1004 memory management needs to be done on them */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1005 assert(0 <= result && result <= 2);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1006 if (result == 0 || result == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1007 /* if 0, error has already been set, if 1, iterator is empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1008 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1009 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1010 PyObject *literal_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1011 PyObject *field_name_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1012 PyObject *format_spec_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1013 PyObject *conversion_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1014 PyObject *tuple = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1015
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1016 literal_str = SubString_new_object(&literal);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1017 if (literal_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1018 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1019
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1020 field_name_str = SubString_new_object(&field_name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1021 if (field_name_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1022 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1023
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1024 /* if field_name is non-zero length, return a string for
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1025 format_spec (even if zero length), else return None */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1026 format_spec_str = (field_present ?
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1027 SubString_new_object_or_empty :
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1028 SubString_new_object)(&format_spec);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1029 if (format_spec_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1030 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1031
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1032 /* if the conversion is not specified, return a None,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1033 otherwise create a one length string with the conversion
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1034 character */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1035 if (conversion == '\0') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1036 conversion_str = Py_None;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1037 Py_INCREF(conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1038 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1039 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1040 conversion_str = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1041 &conversion, 1);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1042 if (conversion_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1043 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1044
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1045 tuple = PyTuple_Pack(4, literal_str, field_name_str, format_spec_str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1046 conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1047 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1048 Py_XDECREF(literal_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1049 Py_XDECREF(field_name_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1050 Py_XDECREF(format_spec_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1051 Py_XDECREF(conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1052 return tuple;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1053 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1054 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1055
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1056 static PyMethodDef formatteriter_methods[] = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1057 {NULL, NULL} /* sentinel */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1058 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1059
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1060 static PyTypeObject PyFormatterIter_Type = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1061 PyVarObject_HEAD_INIT(&PyType_Type, 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1062 "formatteriterator", /* tp_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1063 sizeof(formatteriterobject), /* tp_basicsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1064 0, /* tp_itemsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1065 /* methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1066 (destructor)formatteriter_dealloc, /* tp_dealloc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1067 0, /* tp_print */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1068 0, /* tp_getattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1069 0, /* tp_setattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1070 0, /* tp_reserved */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1071 0, /* tp_repr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1072 0, /* tp_as_number */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1073 0, /* tp_as_sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1074 0, /* tp_as_mapping */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1075 0, /* tp_hash */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1076 0, /* tp_call */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1077 0, /* tp_str */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1078 PyObject_GenericGetAttr, /* tp_getattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1079 0, /* tp_setattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1080 0, /* tp_as_buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1081 Py_TPFLAGS_DEFAULT, /* tp_flags */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1082 0, /* tp_doc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1083 0, /* tp_traverse */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1084 0, /* tp_clear */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1085 0, /* tp_richcompare */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1086 0, /* tp_weaklistoffset */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1087 PyObject_SelfIter, /* tp_iter */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1088 (iternextfunc)formatteriter_next, /* tp_iternext */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1089 formatteriter_methods, /* tp_methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1090 0,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1091 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1092
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1093 /* unicode_formatter_parser is used to implement
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1094 string.Formatter.vformat. it parses a string and returns tuples
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1095 describing the parsed elements. It's a wrapper around
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1096 stringlib/string_format.h's MarkupIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1097 static PyObject *
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
1098 formatter_parser(PyObject *ignored, PyObject *self)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1099 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1100 formatteriterobject *it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1101
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1102 if (!PyUnicode_Check(self)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1103 PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1104 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1105 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1106
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1107 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1108 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1109
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1110 it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1111 if (it == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1112 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1113
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1114 /* take ownership, give the object to the iterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1115 Py_INCREF(self);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1116 it->str = self;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1117
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1118 /* initialize the contained MarkupIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1119 MarkupIterator_init(&it->it_markup, (PyObject*)self, 0, PyUnicode_GET_LENGTH(self));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1120 return (PyObject *)it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1121 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1122
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1123
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1124 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1125 /*********** fieldnameiterator ******************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1126 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1127
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1128
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1129 /* This is used to implement string.Formatter.vparse(). It parses the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1130 field name into attribute and item values. It's a Python-callable
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1131 wrapper around FieldNameIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1132
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1133 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1134 PyObject_HEAD
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
1135 PyObject *str;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1136 FieldNameIterator it_field;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1137 } fieldnameiterobject;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1138
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1139 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1140 fieldnameiter_dealloc(fieldnameiterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1141 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1142 Py_XDECREF(it->str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1143 PyObject_FREE(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1144 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1145
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1146 /* returns a tuple:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1147 (is_attr, value)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1148 is_attr is true if we used attribute syntax (e.g., '.foo')
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1149 false if we used index syntax (e.g., '[foo]')
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1150 value is an integer or string
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1151 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1152 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1153 fieldnameiter_next(fieldnameiterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1154 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1155 int result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1156 int is_attr;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1157 Py_ssize_t idx;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1158 SubString name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1159
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1160 result = FieldNameIterator_next(&it->it_field, &is_attr,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1161 &idx, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1162 if (result == 0 || result == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1163 /* if 0, error has already been set, if 1, iterator is empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1164 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1165 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1166 PyObject* result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1167 PyObject* is_attr_obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1168 PyObject* obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1169
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1170 is_attr_obj = PyBool_FromLong(is_attr);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1171 if (is_attr_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1172 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1173
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1174 /* either an integer or a string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1175 if (idx != -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1176 obj = PyLong_FromSsize_t(idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1177 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1178 obj = SubString_new_object(&name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1179 if (obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1180 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1181
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1182 /* return a tuple of values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1183 result = PyTuple_Pack(2, is_attr_obj, obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1184
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1185 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1186 Py_XDECREF(is_attr_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1187 Py_XDECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1188 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1189 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1190 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1191
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1192 static PyMethodDef fieldnameiter_methods[] = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1193 {NULL, NULL} /* sentinel */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1194 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1195
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1196 static PyTypeObject PyFieldNameIter_Type = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1197 PyVarObject_HEAD_INIT(&PyType_Type, 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1198 "fieldnameiterator", /* tp_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1199 sizeof(fieldnameiterobject), /* tp_basicsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1200 0, /* tp_itemsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1201 /* methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1202 (destructor)fieldnameiter_dealloc, /* tp_dealloc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1203 0, /* tp_print */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1204 0, /* tp_getattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1205 0, /* tp_setattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1206 0, /* tp_reserved */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1207 0, /* tp_repr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1208 0, /* tp_as_number */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1209 0, /* tp_as_sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1210 0, /* tp_as_mapping */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1211 0, /* tp_hash */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1212 0, /* tp_call */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1213 0, /* tp_str */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1214 PyObject_GenericGetAttr, /* tp_getattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1215 0, /* tp_setattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1216 0, /* tp_as_buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1217 Py_TPFLAGS_DEFAULT, /* tp_flags */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1218 0, /* tp_doc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1219 0, /* tp_traverse */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1220 0, /* tp_clear */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1221 0, /* tp_richcompare */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1222 0, /* tp_weaklistoffset */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1223 PyObject_SelfIter, /* tp_iter */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1224 (iternextfunc)fieldnameiter_next, /* tp_iternext */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1225 fieldnameiter_methods, /* tp_methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1226 0};
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1227
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1228 /* unicode_formatter_field_name_split is used to implement
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1229 string.Formatter.vformat. it takes an PEP 3101 "field name", and
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1230 returns a tuple of (first, rest): "first", the part before the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1231 first '.' or '['; and "rest", an iterator for the rest of the field
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1232 name. it's a wrapper around stringlib/string_format.h's
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1233 field_name_split. The iterator it returns is a
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1234 FieldNameIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1235 static PyObject *
73337
783b4b9dfa5e Replace PyUnicodeObject type by PyObject
Victor Stinner <victor.stinner@haypocalc.com>
parents: 72780
diff changeset
1236 formatter_field_name_split(PyObject *ignored, PyObject *self)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1237 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1238 SubString first;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1239 Py_ssize_t first_idx;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1240 fieldnameiterobject *it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1241
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1242 PyObject *first_obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1243 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1244
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1245 if (!PyUnicode_Check(self)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1246 PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1247 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1248 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1249
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1250 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1251 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1252
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1253 it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1254 if (it == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1255 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1256
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1257 /* take ownership, give the object to the iterator. this is
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1258 just to keep the field_name alive */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1259 Py_INCREF(self);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1260 it->str = self;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1261
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1262 /* Pass in auto_number = NULL. We'll return an empty string for
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1263 first_obj in that case. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1264 if (!field_name_split((PyObject*)self, 0, PyUnicode_GET_LENGTH(self),
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1265 &first, &first_idx, &it->it_field, NULL))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1266 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1267
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1268 /* first becomes an integer, if possible; else a string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1269 if (first_idx != -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1270 first_obj = PyLong_FromSsize_t(first_idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1271 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1272 /* convert "first" into a string object */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1273 first_obj = SubString_new_object(&first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1274 if (first_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1275 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1276
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1277 /* return a tuple of values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1278 result = PyTuple_Pack(2, first_obj, it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1279
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1280 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1281 Py_XDECREF(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1282 Py_XDECREF(first_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1283 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1284 }