annotate Objects/stringlib/unicode_format.h @ 73323:dad02a080bbc

Improve byte-compilation in packaging to be independent of -O or -B. The code I fixed to comply with PEP 3147 still had one bug: When run under python -O, some paths for pyc files would be pyo, because I called imp.cache_from_source without explicit debug_override argument in some places, and under -O that would return .pyo (this is well explained in the imp docs). Now all code (util.byte_compile, build_py, install_lib) can create .pyo files according to options given by users, without interference from the calling Python’s own optimize mode. On a related topic, I also removed the code that prevented byte compilation under python -B. The rationale is that packaging gives control over the creation of pyc files to the user with its own explicit option, and the behavior should not be changed if the calling Python happens to run with -B for whatever reason. I will argue that this is a bug fix and ask to be allowed to backport this change to distutils. Finally, I moved one nugget of information about the --compile and --optimize options from the source into the doc. It clears up a misunderstanding that I (and maybe other people) had.
author Éric Araujo <merwok@netwok.org>
date Thu, 03 Nov 2011 05:08:28 +0100
parents d49be9b017a2
children 783b4b9dfa5e
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 /* Defines for more efficiently reallocating the string buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
7 #define INITIAL_SIZE_INCREMENT 100
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
8 #define SIZE_MULTIPLIER 2
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
9 #define MAX_SIZE_INCREMENT 3200
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
10
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
11
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 /*********** Global data structures and forward declarations *********/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
14 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
15
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
16 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
17 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
18 unicode pointers.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
19 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
20 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
21 PyObject *str; /* borrowed reference */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
22 Py_ssize_t start, end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
23 } SubString;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
26 typedef enum {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
27 ANS_INIT,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
28 ANS_AUTO,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
29 ANS_MANUAL
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
30 } AutoNumberState; /* Keep track if we're auto-numbering fields */
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 /* 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
33 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
34 AutoNumberState an_state;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
35 int an_field_number;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
36 } AutoNumber;
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 /* forward declaration for recursion */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
40 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
41 build_string(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
42 int recursion_depth, AutoNumber *auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
43
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
44
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 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
47 /************************** Utility functions ************************/
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 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
51 AutoNumber_Init(AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
52 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
53 auto_number->an_state = ANS_INIT;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
54 auto_number->an_field_number = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
55 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
56
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
57 /* fill in a SubString from a pointer and length */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
58 Py_LOCAL_INLINE(void)
72750
1a0715386d27 Fix compilation warnings under 64-bit Windows
Antoine Pitrou <solipsis@pitrou.net>
parents: 72475
diff changeset
59 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
60 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
61 str->str = s;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
62 str->start = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
63 str->end = end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
64 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
65
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
66 /* 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
67 Py_LOCAL_INLINE(PyObject *)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
68 SubString_new_object(SubString *str)
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 if (str->str == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
71 Py_INCREF(Py_None);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
72 return Py_None;
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 return PyUnicode_Substring(str->str, str->start, str->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
75 }
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 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
78 Py_LOCAL_INLINE(PyObject *)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
79 SubString_new_object_or_empty(SubString *str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
80 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
81 if (str->str == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
82 return PyUnicode_FromUnicode(NULL, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
83 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
84 return SubString_new_object(str);
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
87 /* 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
88 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
89 ValueError on error. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
90 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
91 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
92 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
93 if (state == ANS_MANUAL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
94 if (field_name_is_empty) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
95 PyErr_SetString(PyExc_ValueError, "cannot switch from "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
96 "manual field specification to "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
97 "automatic field numbering");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
98 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
99 }
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 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
102 if (!field_name_is_empty) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
103 PyErr_SetString(PyExc_ValueError, "cannot switch from "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
104 "automatic field numbering to "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
105 "manual field specification");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
106 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
107 }
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 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
110 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
111
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 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
114 /*********** Output string management functions ****************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
115 /************************************************************************/
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 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
118 output_data dumps characters into our output string
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
119 buffer.
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 In some cases, it has to reallocate the string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
122
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
123 It returns a status: 0 for a failed reallocation,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
124 1 for success.
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 static int
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
127 output_data(_PyAccu *acc, 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
128 {
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
129 PyObject *substring;
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
130 int r;
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
131
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
132 substring = PyUnicode_Substring(s, start, end);
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
133 if (substring == NULL)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
134 return 0;
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
135 r = _PyAccu_Accumulate(acc, substring);
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
136 Py_DECREF(substring);
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
137 return r == 0;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
138 }
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 /*********** Format string parsing -- integers and identifiers *********/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
142 /************************************************************************/
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 static Py_ssize_t
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
145 get_integer(const SubString *str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
146 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
147 Py_ssize_t accumulator = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
148 Py_ssize_t digitval;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
149 Py_ssize_t i;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
150
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
151 /* empty string is an error */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
152 if (str->start >= str->end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
153 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
154
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
155 for (i = str->start; i < str->end; i++) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
156 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
157 if (digitval < 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
158 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
159 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
160 Detect possible overflow before it happens:
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 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
163 accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
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 if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
166 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
167 "Too many decimal digits in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
168 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
169 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
170 accumulator = accumulator * 10 + digitval;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
171 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
172 return accumulator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
173 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
174
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
175 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
176 /******** Functions to get field objects and specification strings ******/
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
179 /* do the equivalent of obj.name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
180 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
181 getattr(PyObject *obj, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
182 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
183 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
184 PyObject *str = SubString_new_object(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
185 if (str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
186 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
187 newobj = PyObject_GetAttr(obj, str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
188 Py_DECREF(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
189 return newobj;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
192 /* 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
193 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
194 getitem_sequence(PyObject *obj, Py_ssize_t idx)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
195 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
196 return PySequence_GetItem(obj, idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
197 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
198
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
199 /* 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
200 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
201 getitem_idx(PyObject *obj, Py_ssize_t idx)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
202 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
203 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
204 PyObject *idx_obj = PyLong_FromSsize_t(idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
205 if (idx_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
206 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
207 newobj = PyObject_GetItem(obj, idx_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
208 Py_DECREF(idx_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
209 return newobj;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
212 /* do the equivalent of obj[name] */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
213 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
214 getitem_str(PyObject *obj, SubString *name)
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 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
217 PyObject *str = SubString_new_object(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
218 if (str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
219 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
220 newobj = PyObject_GetItem(obj, str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
221 Py_DECREF(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
222 return newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
223 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
224
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
225 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
226 /* 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
227 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
228 lifetime of the iterator. can be empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
229 SubString str;
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 /* index to where we are inside field_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
232 Py_ssize_t index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
233 } FieldNameIterator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
234
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
235
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
236 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
237 FieldNameIterator_init(FieldNameIterator *self, PyObject *s,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
238 Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
239 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
240 SubString_init(&self->str, s, start, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
241 self->index = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
242 return 1;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
245 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
246 _FieldNameIterator_attr(FieldNameIterator *self, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
247 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
248 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
249
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
250 name->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
251 name->start = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
252
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
253 /* return everything until '.' or '[' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
254 while (self->index < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
255 c = PyUnicode_READ_CHAR(self->str.str, self->index++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
256 switch (c) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
257 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
258 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
259 /* 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
260 self->index--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
261 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
262 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
263 continue;
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 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
266 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
267 /* end of string is okay */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
268 name->end = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
269 return 1;
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
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_item(FieldNameIterator *self, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
274 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
275 int bracket_seen = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
276 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
277
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
278 name->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
279 name->start = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
280
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
281 /* return everything until ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
282 while (self->index < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
283 c = PyUnicode_READ_CHAR(self->str.str, self->index++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
284 switch (c) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
285 case ']':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
286 bracket_seen = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
287 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
288 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
289 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
290 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
291 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
292 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
293 /* make sure we ended with a ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
294 if (!bracket_seen) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
295 PyErr_SetString(PyExc_ValueError, "Missing ']' in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
296 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
297 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
298
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
299 /* end of string is okay */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
300 /* don't include the ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
301 name->end = self->index-1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
302 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
303 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
304
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
305 /* 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
306 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
307 FieldNameIterator_next(FieldNameIterator *self, int *is_attribute,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
308 Py_ssize_t *name_idx, SubString *name)
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 /* check at end of input */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
311 if (self->index >= self->str.end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
312 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
313
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
314 switch (PyUnicode_READ_CHAR(self->str.str, self->index++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
315 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
316 *is_attribute = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
317 if (_FieldNameIterator_attr(self, name) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
318 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
319 *name_idx = -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
320 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
321 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
322 *is_attribute = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
323 if (_FieldNameIterator_item(self, name) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
324 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
325 *name_idx = get_integer(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
326 if (*name_idx == -1 && PyErr_Occurred())
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
327 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
328 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
329 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
330 /* Invalid character follows ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
331 PyErr_SetString(PyExc_ValueError, "Only '.' or '[' may "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
332 "follow ']' in format field specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
333 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
334 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
335
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
336 /* empty string is an error */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
337 if (name->start == name->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
338 PyErr_SetString(PyExc_ValueError, "Empty attribute in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
339 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
340 }
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 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
343 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
344
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
345
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
346 /* input: field_name
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
347 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
348 '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
349 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
350 'rest' is an iterator to return the rest
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 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
353 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
354 Py_ssize_t *first_idx, FieldNameIterator *rest,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
355 AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
356 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
357 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
358 Py_ssize_t i = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
359 int field_name_is_empty;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
360 int using_numeric_index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
361
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
362 /* find the part up until the first '.' or '[' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
363 while (i < end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
364 switch (c = PyUnicode_READ_CHAR(str, i++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
365 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
366 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
367 /* 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
368 "rest" iterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
369 i--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
370 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
371 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
372 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
373 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
374 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
375 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
376
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
377 /* set up the return values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
378 SubString_init(first, str, start, i);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
379 FieldNameIterator_init(rest, str, i, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
380
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
381 /* 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
382 *first_idx = get_integer(first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
383 if (*first_idx == -1 && PyErr_Occurred())
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
384 return 0;
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 field_name_is_empty = first->start >= first->end;
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 /* 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
389 specified, then we're doing numeric indexing into args. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
390 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
391
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
392 /* 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
393 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
394 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
395 numbering if the field name is omitted. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
396
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
397 /* 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
398 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
399 in that class by itself. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
400 if (auto_number) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
401 /* 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
402 time we're either auto-numbering or manually numbering. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
403 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
404 auto_number->an_state = field_name_is_empty ?
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
405 ANS_AUTO : ANS_MANUAL;
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 /* 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
408 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
409 index. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
410 if (using_numeric_index)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
411 if (autonumber_state_error(auto_number->an_state,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
412 field_name_is_empty))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
413 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
414 /* 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
415 fields. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
416 if (field_name_is_empty)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
417 *first_idx = (auto_number->an_field_number)++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
418 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
419
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
420 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
421 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
422
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
423
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
424 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
425 get_field_object returns the object inside {}, before the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
426 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
427 the entire input string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
428 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
429 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
430 get_field_object(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
431 AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
432 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
433 PyObject *obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
434 int ok;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
435 int is_attribute;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
436 SubString name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
437 SubString first;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
438 Py_ssize_t index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
439 FieldNameIterator rest;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
440
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
441 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
442 &index, &rest, auto_number)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
443 goto error;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
446 if (index == -1) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
447 /* look up in kwargs */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
448 PyObject *key = SubString_new_object(&first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
449 if (key == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
450 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
451
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
452 /* Use PyObject_GetItem instead of PyDict_GetItem because this
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
453 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
454 a non-dict when called through format_map. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
455 if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
456 PyErr_SetObject(PyExc_KeyError, key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
457 Py_DECREF(key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
458 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
459 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
460 Py_DECREF(key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
461 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
462 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
463 /* 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
464 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
465 used with format_map(), where positional arguments are not
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
466 allowed. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
467 if (args == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
468 PyErr_SetString(PyExc_ValueError, "Format string contains "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
469 "positional fields");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
470 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
471 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
472
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
473 /* look up in args */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
474 obj = PySequence_GetItem(args, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
475 if (obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
476 goto error;
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 /* iterate over the rest of the field_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
480 while ((ok = FieldNameIterator_next(&rest, &is_attribute, &index,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
481 &name)) == 2) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
482 PyObject *tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
483
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
484 if (is_attribute)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
485 /* getattr lookup "." */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
486 tmp = getattr(obj, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
487 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
488 /* getitem lookup "[]" */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
489 if (index == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
490 tmp = getitem_str(obj, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
491 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
492 if (PySequence_Check(obj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
493 tmp = getitem_sequence(obj, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
494 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
495 /* not a sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
496 tmp = getitem_idx(obj, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
497 if (tmp == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
498 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
499
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
500 /* assign to obj */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
501 Py_DECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
502 obj = tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
503 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
504 /* end of iterator, this is the non-error case */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
505 if (ok == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
506 return obj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
507 error:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
508 Py_XDECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
509 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
510 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
511
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
512 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
513 /***************** Field rendering functions **************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
514 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
515
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 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
518 field object and field specification string generated by
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
519 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
520
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
521 render_field calls fieldobj.__format__(format_spec) method, and
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
522 appends to the output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
523 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
524 static int
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
525 render_field(PyObject *fieldobj, SubString *format_spec, _PyAccu *acc)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
526 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
527 int ok = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
528 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
529 PyObject *format_spec_object = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
530 PyObject *(*formatter)(PyObject *, PyObject *, Py_ssize_t, Py_ssize_t) = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
531
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
532 /* 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
533 call the formatter directly. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
534 if (PyUnicode_CheckExact(fieldobj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
535 formatter = _PyUnicode_FormatAdvanced;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
536 else if (PyLong_CheckExact(fieldobj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
537 formatter =_PyLong_FormatAdvanced;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
538 else if (PyFloat_CheckExact(fieldobj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
539 formatter = _PyFloat_FormatAdvanced;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
540
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
541 /* XXX: for 2.6, convert format_spec to the appropriate type
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
542 (unicode, str) */
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 if (formatter) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
545 /* 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
546 looked up, so call it directly, instead. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
547 result = formatter(fieldobj, format_spec->str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
548 format_spec->start, format_spec->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
549 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
550 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
551 /* 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
552 __format__ takes a string/unicode object for format_spec. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
553 if (format_spec->str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
554 format_spec_object = PyUnicode_Substring(format_spec->str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
555 format_spec->start,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
556 format_spec->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
557 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
558 format_spec_object = PyUnicode_New(0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
559 if (format_spec_object == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
560 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
561
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
562 result = PyObject_Format(fieldobj, format_spec_object);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
563 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
564 if (result == NULL || PyUnicode_READY(result) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
565 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
566
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
567 assert(PyUnicode_Check(result));
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
568 ok = output_data(acc, result, 0, PyUnicode_GET_LENGTH(result));
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
569 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
570 Py_XDECREF(format_spec_object);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
571 Py_XDECREF(result);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
572 return ok;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
573 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
574
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
575 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
576 parse_field(SubString *str, SubString *field_name, SubString *format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
577 Py_UCS4 *conversion)
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 /* 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
580 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
581 field_name_split. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
582
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
583 Py_UCS4 c = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
584
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
585 /* initialize these, as they may be empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
586 *conversion = '\0';
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
587 SubString_init(format_spec, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
588
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
589 /* 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
590 the string, or a ':' or '!' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
591 field_name->str = str->str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
592 field_name->start = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
593 while (str->start < str->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
594 switch ((c = PyUnicode_READ_CHAR(str->str, str->start++))) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
595 case ':':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
596 case '!':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
597 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
598 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
599 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
600 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
601 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
602 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
603
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
604 if (c == '!' || c == ':') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
605 /* we have a format specifier and/or a conversion */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
606 /* don't include the last character */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
607 field_name->end = str->start-1;
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 /* the format specifier is the rest of the string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
610 format_spec->str = str->str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
611 format_spec->start = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
612 format_spec->end = str->end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
613
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
614 /* see if there's a conversion specifier */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
615 if (c == '!') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
616 /* there must be another character present */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
617 if (format_spec->start >= format_spec->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
618 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
619 "end of format while looking for conversion "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
620 "specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
621 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
622 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
623 *conversion = PyUnicode_READ_CHAR(format_spec->str, format_spec->start++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
624
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
625 /* if there is another character, it must be a colon */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
626 if (format_spec->start < format_spec->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
627 c = PyUnicode_READ_CHAR(format_spec->str, format_spec->start++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
628 if (c != ':') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
629 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
630 "expected ':' after format specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
631 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
632 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
633 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
634 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
635 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
636 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
637 /* end of string, there's no format_spec or conversion */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
638 field_name->end = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
639
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
640 return 1;
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 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
644 /******* Output string allocation and escape-to-markup processing ******/
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
647 /* MarkupIterator breaks the string into pieces of either literal
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
648 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
649 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
650 use with the Formatter class */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
651
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
652 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
653 SubString str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
654 } MarkupIterator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
655
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
656 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
657 MarkupIterator_init(MarkupIterator *self, PyObject *str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
658 Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
659 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
660 SubString_init(&self->str, str, start, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
661 return 1;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
664 /* 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
665 string (or something to be expanded) */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
666 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
667 MarkupIterator_next(MarkupIterator *self, SubString *literal,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
668 int *field_present, SubString *field_name,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
669 SubString *format_spec, Py_UCS4 *conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
670 int *format_spec_needs_expanding)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
671 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
672 int at_end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
673 Py_UCS4 c = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
674 Py_ssize_t start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
675 int count;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
676 Py_ssize_t len;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
677 int markup_follows = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
678
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
679 /* initialize all of the output variables */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
680 SubString_init(literal, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
681 SubString_init(field_name, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
682 SubString_init(format_spec, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
683 *conversion = '\0';
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
684 *format_spec_needs_expanding = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
685 *field_present = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
686
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
687 /* 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
688 path. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
689 if (self->str.start >= self->str.end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
690 return 1;
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 start = self->str.start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
693
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
694 /* 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
695 escaped '{' or '}', or an unescaped '{'. In order to never
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
696 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
697 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
698 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
699 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
700 the second consecutive brace. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
701 while (self->str.start < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
702 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
703 case '{':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
704 case '}':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
705 markup_follows = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
706 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
707 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
708 continue;
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 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
711 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
712
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
713 at_end = self->str.start >= self->str.end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
714 len = self->str.start - start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
715
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
716 if ((c == '}') && (at_end ||
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
717 (c != PyUnicode_READ_CHAR(self->str.str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
718 self->str.start)))) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
719 PyErr_SetString(PyExc_ValueError, "Single '}' encountered "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
720 "in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
721 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
722 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
723 if (at_end && c == '{') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
724 PyErr_SetString(PyExc_ValueError, "Single '{' encountered "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
725 "in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
726 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
727 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
728 if (!at_end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
729 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
730 /* 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
731 markup object following us, just this literal text */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
732 self->str.start++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
733 markup_follows = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
734 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
735 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
736 len--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
737 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
738
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
739 /* record the literal text */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
740 literal->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
741 literal->start = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
742 literal->end = start + len;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
743
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
744 if (!markup_follows)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
745 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
746
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
747 /* this is markup, find the end of the string by counting nested
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
748 braces. note that this prohibits escaped braces, so that
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
749 format_specs cannot have braces in them. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
750 *field_present = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
751 count = 1;
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 start = self->str.start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
754
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
755 /* we know we can't have a zero length string, so don't worry
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
756 about that case */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
757 while (self->str.start < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
758 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
759 case '{':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
760 /* the format spec needs to be recursively expanded.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
761 this is an optimization, and not strictly needed */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
762 *format_spec_needs_expanding = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
763 count++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
764 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
765 case '}':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
766 count--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
767 if (count <= 0) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
768 /* we're done. parse and get out */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
769 SubString s;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
770
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
771 SubString_init(&s, self->str.str, start, self->str.start - 1);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
772 if (parse_field(&s, field_name, format_spec, conversion) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
773 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
774
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
775 /* success */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
776 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
777 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
778 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
779 }
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 /* end of string while searching for matching '}' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
783 PyErr_SetString(PyExc_ValueError, "unmatched '{' in format");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
784 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
785 }
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
788 /* do the !r or !s conversion on obj */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
789 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
790 do_conversion(PyObject *obj, Py_UCS4 conversion)
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 /* 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
793 might have returned a string? */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
794 switch (conversion) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
795 case 'r':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
796 return PyObject_Repr(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
797 case 's':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
798 return PyObject_Str(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
799 case 'a':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
800 return PyObject_ASCII(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
801 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
802 if (conversion > 32 && conversion < 127) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
803 /* 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
804 (assuming the execution character set is an ASCII
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
805 superset). */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
806 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
807 "Unknown conversion specifier %c",
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
808 (char)conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
809 } else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
810 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
811 "Unknown conversion specifier \\x%x",
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
812 (unsigned int)conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
813 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
814 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
815 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
816
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
817 /* given:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
818
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
819 {field_name!conversion:format_spec}
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
820
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
821 compute the result and write it to output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
822 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
823 just output the string directly, otherwise recursively expand the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
824 format_spec string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
825
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
826 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
827 are doing auto field numbering.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
828 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
829
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
830 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
831 output_markup(SubString *field_name, SubString *format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
832 int format_spec_needs_expanding, Py_UCS4 conversion,
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
833 _PyAccu *acc, PyObject *args, PyObject *kwargs,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
834 int recursion_depth, AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
835 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
836 PyObject *tmp = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
837 PyObject *fieldobj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
838 SubString expanded_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
839 SubString *actual_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
840 int result = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
841
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
842 /* convert field_name to an object */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
843 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
844 if (fieldobj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
845 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
846
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
847 if (conversion != '\0') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
848 tmp = do_conversion(fieldobj, conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
849 if (tmp == NULL || PyUnicode_READY(tmp) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
850 goto done;
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 /* do the assignment, transferring ownership: fieldobj = tmp */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
853 Py_DECREF(fieldobj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
854 fieldobj = tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
855 tmp = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
856 }
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 /* if needed, recurively compute the format_spec */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
859 if (format_spec_needs_expanding) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
860 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
861 auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
862 if (tmp == NULL || PyUnicode_READY(tmp) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
863 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
864
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
865 /* 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
866 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
867 render_field. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
868 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
869 actual_format_spec = &expanded_format_spec;
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 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
872 actual_format_spec = format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
873
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
874 if (render_field(fieldobj, actual_format_spec, acc) == 0)
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
875 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
876
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
877 result = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
878
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
879 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
880 Py_XDECREF(fieldobj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
881 Py_XDECREF(tmp);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
882
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
883 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
884 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
885
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
886 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
887 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
888 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
889 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
890 and to perform the markup to the output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
891 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
892 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
893 do_markup(SubString *input, PyObject *args, PyObject *kwargs,
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
894 _PyAccu *acc, int recursion_depth, AutoNumber *auto_number)
72475
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 MarkupIterator iter;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
897 int format_spec_needs_expanding;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
898 int result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
899 int field_present;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
900 SubString literal;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
901 SubString field_name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
902 SubString format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
903 Py_UCS4 conversion;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
904
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
905 MarkupIterator_init(&iter, input->str, input->start, input->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
906 while ((result = MarkupIterator_next(&iter, &literal, &field_present,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
907 &field_name, &format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
908 &conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
909 &format_spec_needs_expanding)) == 2) {
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
910 if (!output_data(acc, literal.str, literal.start, literal.end))
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
911 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
912 if (field_present)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
913 if (!output_markup(&field_name, &format_spec,
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
914 format_spec_needs_expanding, conversion, acc,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
915 args, kwargs, recursion_depth, auto_number))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
916 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
917 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
918 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
919 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
920
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
921
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 build_string allocates the output string and then
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
924 calls do_markup to do the heavy lifting.
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 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
927 build_string(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
928 int recursion_depth, AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
929 {
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
930 _PyAccu acc;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
931
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
932 /* check the recursion level */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
933 if (recursion_depth <= 0) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
934 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
935 "Max string recursion exceeded");
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
936 return NULL;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
937 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
938
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
939 if (_PyAccu_Init(&acc))
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
940 return NULL;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
941
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
942 if (!do_markup(input, args, kwargs, &acc, recursion_depth,
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
943 auto_number)) {
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
944 _PyAccu_Destroy(&acc);
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
945 return NULL;
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
946 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
947
72780
d49be9b017a2 Fix massive slowdown in string formatting with str.format.
Antoine Pitrou <solipsis@pitrou.net>
parents: 72750
diff changeset
948 return _PyAccu_Finish(&acc);
72475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
949 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
950
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 /*********** main routine ***********************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
953 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
954
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
955 /* this is the main entry point */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
956 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
957 do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
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 SubString input;
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 /* PEP 3101 says only 2 levels, so that
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
962 "{0:{1}}".format('abc', 's') # works
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
963 "{0:{1:{2}}}".format('abc', 's', '') # fails
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
964 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
965 int recursion_depth = 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
966
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
967 AutoNumber auto_number;
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 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
970 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
971
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
972 AutoNumber_Init(&auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
973 SubString_init(&input, self, 0, PyUnicode_GET_LENGTH(self));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
974 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
975 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
976
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
977 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
978 do_string_format_map(PyObject *self, PyObject *obj)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
979 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
980 return do_string_format(self, NULL, obj);
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
983
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 /*********** formatteriterator ******************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
986 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
987
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
988 /* 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
989 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
990 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
991 from Python. */
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 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
994 PyObject_HEAD
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
995
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
996 PyUnicodeObject *str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
997
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
998 MarkupIterator it_markup;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
999 } formatteriterobject;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1000
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1001 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1002 formatteriter_dealloc(formatteriterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1003 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1004 Py_XDECREF(it->str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1005 PyObject_FREE(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1006 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1007
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1008 /* returns a tuple:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1009 (literal, field_name, format_spec, conversion)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1010
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1011 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
1012 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
1013 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
1014 conversion is either None, or the string after the '!'
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 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1017 formatteriter_next(formatteriterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1018 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1019 SubString literal;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1020 SubString field_name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1021 SubString format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1022 Py_UCS4 conversion;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1023 int format_spec_needs_expanding;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1024 int field_present;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1025 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
1026 &field_name, &format_spec, &conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1027 &format_spec_needs_expanding);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1028
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1029 /* 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
1030 memory management needs to be done on them */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1031 assert(0 <= result && result <= 2);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1032 if (result == 0 || result == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1033 /* 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
1034 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1035 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1036 PyObject *literal_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1037 PyObject *field_name_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1038 PyObject *format_spec_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1039 PyObject *conversion_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1040 PyObject *tuple = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1041
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1042 literal_str = SubString_new_object(&literal);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1043 if (literal_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1044 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1045
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1046 field_name_str = SubString_new_object(&field_name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1047 if (field_name_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1048 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1049
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1050 /* 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
1051 format_spec (even if zero length), else return None */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1052 format_spec_str = (field_present ?
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1053 SubString_new_object_or_empty :
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1054 SubString_new_object)(&format_spec);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1055 if (format_spec_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1056 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1057
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1058 /* if the conversion is not specified, return a None,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1059 otherwise create a one length string with the conversion
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1060 character */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1061 if (conversion == '\0') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1062 conversion_str = Py_None;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1063 Py_INCREF(conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1064 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1065 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1066 conversion_str = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1067 &conversion, 1);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1068 if (conversion_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1069 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1070
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1071 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
1072 conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1073 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1074 Py_XDECREF(literal_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1075 Py_XDECREF(field_name_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1076 Py_XDECREF(format_spec_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1077 Py_XDECREF(conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1078 return tuple;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1079 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1080 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1081
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1082 static PyMethodDef formatteriter_methods[] = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1083 {NULL, NULL} /* sentinel */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1084 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1085
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1086 static PyTypeObject PyFormatterIter_Type = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1087 PyVarObject_HEAD_INIT(&PyType_Type, 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1088 "formatteriterator", /* tp_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1089 sizeof(formatteriterobject), /* tp_basicsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1090 0, /* tp_itemsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1091 /* methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1092 (destructor)formatteriter_dealloc, /* tp_dealloc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1093 0, /* tp_print */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1094 0, /* tp_getattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1095 0, /* tp_setattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1096 0, /* tp_reserved */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1097 0, /* tp_repr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1098 0, /* tp_as_number */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1099 0, /* tp_as_sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1100 0, /* tp_as_mapping */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1101 0, /* tp_hash */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1102 0, /* tp_call */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1103 0, /* tp_str */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1104 PyObject_GenericGetAttr, /* tp_getattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1105 0, /* tp_setattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1106 0, /* tp_as_buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1107 Py_TPFLAGS_DEFAULT, /* tp_flags */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1108 0, /* tp_doc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1109 0, /* tp_traverse */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1110 0, /* tp_clear */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1111 0, /* tp_richcompare */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1112 0, /* tp_weaklistoffset */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1113 PyObject_SelfIter, /* tp_iter */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1114 (iternextfunc)formatteriter_next, /* tp_iternext */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1115 formatteriter_methods, /* tp_methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1116 0,
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1119 /* unicode_formatter_parser is used to implement
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1120 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
1121 describing the parsed elements. It's a wrapper around
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1122 stringlib/string_format.h's MarkupIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1123 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1124 formatter_parser(PyObject *ignored, PyUnicodeObject *self)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1125 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1126 formatteriterobject *it;
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 if (!PyUnicode_Check(self)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1129 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
1130 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1131 }
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 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1134 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1135
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1136 it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1137 if (it == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1138 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1139
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1140 /* take ownership, give the object to the iterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1141 Py_INCREF(self);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1142 it->str = self;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1143
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1144 /* initialize the contained MarkupIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1145 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
1146 return (PyObject *)it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1147 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1148
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1149
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1150 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1151 /*********** fieldnameiterator ******************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1152 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1153
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 /* 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
1156 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
1157 wrapper around FieldNameIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1158
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1159 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1160 PyObject_HEAD
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1161
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1162 PyUnicodeObject *str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1163
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1164 FieldNameIterator it_field;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1165 } fieldnameiterobject;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1166
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1167 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1168 fieldnameiter_dealloc(fieldnameiterobject *it)
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 Py_XDECREF(it->str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1171 PyObject_FREE(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1172 }
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 /* returns a tuple:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1175 (is_attr, value)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1176 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
1177 false if we used index syntax (e.g., '[foo]')
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1178 value is an integer or string
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1179 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1180 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1181 fieldnameiter_next(fieldnameiterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1182 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1183 int result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1184 int is_attr;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1185 Py_ssize_t idx;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1186 SubString name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1187
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1188 result = FieldNameIterator_next(&it->it_field, &is_attr,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1189 &idx, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1190 if (result == 0 || result == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1191 /* 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
1192 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1193 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1194 PyObject* result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1195 PyObject* is_attr_obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1196 PyObject* obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1197
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1198 is_attr_obj = PyBool_FromLong(is_attr);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1199 if (is_attr_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1200 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1201
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1202 /* either an integer or a string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1203 if (idx != -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1204 obj = PyLong_FromSsize_t(idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1205 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1206 obj = SubString_new_object(&name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1207 if (obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1208 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1209
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1210 /* return a tuple of values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1211 result = PyTuple_Pack(2, is_attr_obj, obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1212
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1213 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1214 Py_XDECREF(is_attr_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1215 Py_XDECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1216 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1217 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1218 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1219
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1220 static PyMethodDef fieldnameiter_methods[] = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1221 {NULL, NULL} /* sentinel */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1222 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1223
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1224 static PyTypeObject PyFieldNameIter_Type = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1225 PyVarObject_HEAD_INIT(&PyType_Type, 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1226 "fieldnameiterator", /* tp_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1227 sizeof(fieldnameiterobject), /* tp_basicsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1228 0, /* tp_itemsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1229 /* methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1230 (destructor)fieldnameiter_dealloc, /* tp_dealloc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1231 0, /* tp_print */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1232 0, /* tp_getattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1233 0, /* tp_setattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1234 0, /* tp_reserved */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1235 0, /* tp_repr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1236 0, /* tp_as_number */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1237 0, /* tp_as_sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1238 0, /* tp_as_mapping */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1239 0, /* tp_hash */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1240 0, /* tp_call */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1241 0, /* tp_str */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1242 PyObject_GenericGetAttr, /* tp_getattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1243 0, /* tp_setattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1244 0, /* tp_as_buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1245 Py_TPFLAGS_DEFAULT, /* tp_flags */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1246 0, /* tp_doc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1247 0, /* tp_traverse */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1248 0, /* tp_clear */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1249 0, /* tp_richcompare */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1250 0, /* tp_weaklistoffset */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1251 PyObject_SelfIter, /* tp_iter */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1252 (iternextfunc)fieldnameiter_next, /* tp_iternext */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1253 fieldnameiter_methods, /* tp_methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1254 0};
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1255
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1256 /* unicode_formatter_field_name_split is used to implement
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1257 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
1258 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
1259 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
1260 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
1261 field_name_split. The iterator it returns is a
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1262 FieldNameIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1263 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1264 formatter_field_name_split(PyObject *ignored, PyUnicodeObject *self)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1265 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1266 SubString first;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1267 Py_ssize_t first_idx;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1268 fieldnameiterobject *it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1269
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1270 PyObject *first_obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1271 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1272
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1273 if (!PyUnicode_Check(self)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1274 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
1275 return NULL;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1278 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1279 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1280
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1281 it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1282 if (it == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1283 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1284
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1285 /* 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
1286 just to keep the field_name alive */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1287 Py_INCREF(self);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1288 it->str = self;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1289
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1290 /* 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
1291 first_obj in that case. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1292 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
1293 &first, &first_idx, &it->it_field, NULL))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1294 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1295
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1296 /* first becomes an integer, if possible; else a string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1297 if (first_idx != -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1298 first_obj = PyLong_FromSsize_t(first_idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1299 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1300 /* convert "first" into a string object */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1301 first_obj = SubString_new_object(&first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1302 if (first_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1303 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1304
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1305 /* return a tuple of values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1306 result = PyTuple_Pack(2, first_obj, it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1307
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1308 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1309 Py_XDECREF(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1310 Py_XDECREF(first_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1311 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1312 }