annotate Objects/stringlib/unicode_format.h @ 72751:d760b345d7bd

Fix compilation warnings under 64-bit Windows
author Antoine Pitrou <solipsis@pitrou.net>
date Thu, 06 Oct 2011 15:44:15 +0200
parents 1a0715386d27
children d49be9b017a2
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 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
118 char *data;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
119 Py_UCS4 maxchar;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
120 unsigned int kind;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
121 Py_ssize_t pos, size;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
122 Py_ssize_t size_increment;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
123 } OutputString;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
124
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
125 /* initialize an OutputString object, reserving size characters */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
126 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
127 output_initialize(OutputString *output, Py_ssize_t size)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
128 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
129 output->data = PyMem_Malloc(size);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
130 if (output->data == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
131 PyErr_NoMemory();
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
132 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
133 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
134
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
135 output->maxchar = 127;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
136 output->kind = PyUnicode_1BYTE_KIND;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
137 output->pos = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
138 output->size = size;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
139 output->size_increment = INITIAL_SIZE_INCREMENT;
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 return 1;
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 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
145 output_extend reallocates the output string buffer.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
146 It returns a status: 0 for a failed reallocation,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
147 1 for success.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
148 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
149
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
150 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
151 output_extend(OutputString *output, Py_ssize_t count)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
152 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
153 Py_ssize_t maxlen = output->size + count + output->size_increment;
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 output->data = PyMem_Realloc(output->data, maxlen << (output->kind-1));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
156 output->size = maxlen;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
157 if (output->data == 0) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
158 PyErr_NoMemory();
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
159 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
160 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
161 if (output->size_increment < MAX_SIZE_INCREMENT)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
162 output->size_increment *= SIZE_MULTIPLIER;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
163 return 1;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
166 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
167 output_widen(OutputString *output, Py_UCS4 maxchar)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
168 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
169 int kind;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
170 void *data;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
171 Py_ssize_t i;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
172 if (maxchar <= output->maxchar)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
173 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
174 if (maxchar < 256) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
175 output->maxchar = 255;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
176 return 1;
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 if (maxchar < 65536) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
179 output->maxchar = 65535;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
180 kind = 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
181 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
182 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
183 output->maxchar = 1<<21;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
184 kind = 3;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
185 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
186 data = PyMem_Malloc(output->size << (kind-1));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
187 if (data == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
188 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
189 for (i = 0; i < output->size; i++)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
190 PyUnicode_WRITE(kind, data, i,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
191 PyUnicode_READ(output->kind, output->data, i));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
192 PyMem_Free(output->data);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
193 output->data = data;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
194 output->kind = kind;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
195 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
196 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
197
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 output_data dumps characters into our output string
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
200 buffer.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
201
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
202 In some cases, it has to reallocate the string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
203
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
204 It returns a status: 0 for a failed reallocation,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
205 1 for success.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
206 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
207 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
208 output_data(OutputString *output, PyObject *s, Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
209 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
210 Py_ssize_t i;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
211 int kind;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
212 if ((output->pos + end - start > output->size) &&
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
213 !output_extend(output, end - start))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
214 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
215 kind = PyUnicode_KIND(s);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
216 if (PyUnicode_MAX_CHAR_VALUE(s) > output->maxchar) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
217 Py_UCS4 maxchar = output->maxchar;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
218 for (i = start; i < end; i++)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
219 if (PyUnicode_READ(kind, PyUnicode_DATA(s), i) > maxchar)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
220 maxchar = PyUnicode_READ(kind, PyUnicode_DATA(s), i);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
221 if (!output_widen(output, maxchar))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
222 return 0;
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 for (i = start; i < end; i++)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
225 PyUnicode_WRITE(output->kind, output->data, output->pos++,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
226 PyUnicode_READ(kind, PyUnicode_DATA(s), i));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
227 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
228 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
229
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 /*********** Format string parsing -- integers and identifiers *********/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
232 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
233
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
234 static Py_ssize_t
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
235 get_integer(const SubString *str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
236 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
237 Py_ssize_t accumulator = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
238 Py_ssize_t digitval;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
239 Py_ssize_t i;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
240
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
241 /* empty string is an error */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
242 if (str->start >= str->end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
243 return -1;
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 for (i = str->start; i < str->end; i++) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
246 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
247 if (digitval < 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
248 return -1;
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 Detect possible overflow before it happens:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
251
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
252 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
253 accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
254 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
255 if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
256 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
257 "Too many decimal digits in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
258 return -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
259 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
260 accumulator = accumulator * 10 + digitval;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
261 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
262 return accumulator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
263 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
264
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
265 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
266 /******** Functions to get field objects and specification strings ******/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
267 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
268
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
269 /* do the equivalent of obj.name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
270 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
271 getattr(PyObject *obj, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
272 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
273 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
274 PyObject *str = SubString_new_object(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
275 if (str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
276 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
277 newobj = PyObject_GetAttr(obj, str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
278 Py_DECREF(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
279 return newobj;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
282 /* 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
283 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
284 getitem_sequence(PyObject *obj, Py_ssize_t idx)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
285 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
286 return PySequence_GetItem(obj, idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
287 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
288
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
289 /* 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
290 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
291 getitem_idx(PyObject *obj, Py_ssize_t idx)
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 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
294 PyObject *idx_obj = PyLong_FromSsize_t(idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
295 if (idx_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
296 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
297 newobj = PyObject_GetItem(obj, idx_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
298 Py_DECREF(idx_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
299 return newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
300 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
301
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
302 /* do the equivalent of obj[name] */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
303 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
304 getitem_str(PyObject *obj, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
305 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
306 PyObject *newobj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
307 PyObject *str = SubString_new_object(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
308 if (str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
309 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
310 newobj = PyObject_GetItem(obj, str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
311 Py_DECREF(str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
312 return newobj;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
315 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
316 /* 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
317 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
318 lifetime of the iterator. can be empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
319 SubString str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
320
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
321 /* index to where we are inside field_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
322 Py_ssize_t index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
323 } FieldNameIterator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
324
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
325
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
326 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
327 FieldNameIterator_init(FieldNameIterator *self, PyObject *s,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
328 Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
329 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
330 SubString_init(&self->str, s, start, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
331 self->index = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
332 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
333 }
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 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
336 _FieldNameIterator_attr(FieldNameIterator *self, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
337 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
338 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
339
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
340 name->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
341 name->start = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
342
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
343 /* return everything until '.' or '[' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
344 while (self->index < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
345 c = PyUnicode_READ_CHAR(self->str.str, self->index++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
346 switch (c) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
347 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
348 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
349 /* 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
350 self->index--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
351 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
352 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
353 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
354 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
355 break;
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 /* end of string is okay */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
358 name->end = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
359 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
360 }
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 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
363 _FieldNameIterator_item(FieldNameIterator *self, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
364 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
365 int bracket_seen = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
366 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
367
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
368 name->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
369 name->start = self->index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
370
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
371 /* return everything until ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
372 while (self->index < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
373 c = PyUnicode_READ_CHAR(self->str.str, self->index++);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
374 switch (c) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
375 case ']':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
376 bracket_seen = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
377 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
378 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
379 continue;
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 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
382 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
383 /* make sure we ended with a ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
384 if (!bracket_seen) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
385 PyErr_SetString(PyExc_ValueError, "Missing ']' in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
386 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
387 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
388
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
389 /* end of string is okay */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
390 /* don't include the ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
391 name->end = self->index-1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
392 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
393 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
394
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
395 /* 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
396 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
397 FieldNameIterator_next(FieldNameIterator *self, int *is_attribute,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
398 Py_ssize_t *name_idx, SubString *name)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
399 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
400 /* check at end of input */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
401 if (self->index >= self->str.end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
402 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
403
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
404 switch (PyUnicode_READ_CHAR(self->str.str, self->index++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
405 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
406 *is_attribute = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
407 if (_FieldNameIterator_attr(self, name) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
408 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
409 *name_idx = -1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
410 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
411 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
412 *is_attribute = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
413 if (_FieldNameIterator_item(self, name) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
414 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
415 *name_idx = get_integer(name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
416 if (*name_idx == -1 && PyErr_Occurred())
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
417 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
418 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
419 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
420 /* Invalid character follows ']' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
421 PyErr_SetString(PyExc_ValueError, "Only '.' or '[' may "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
422 "follow ']' in format field specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
423 return 0;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
426 /* empty string is an error */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
427 if (name->start == name->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
428 PyErr_SetString(PyExc_ValueError, "Empty attribute in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
429 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
430 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
431
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
432 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
433 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
434
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
435
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
436 /* input: field_name
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
437 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
438 '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
439 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
440 'rest' is an iterator to return the rest
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
441 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
442 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
443 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
444 Py_ssize_t *first_idx, FieldNameIterator *rest,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
445 AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
446 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
447 Py_UCS4 c;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
448 Py_ssize_t i = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
449 int field_name_is_empty;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
450 int using_numeric_index;
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 /* find the part up until the first '.' or '[' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
453 while (i < end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
454 switch (c = PyUnicode_READ_CHAR(str, i++)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
455 case '[':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
456 case '.':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
457 /* 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
458 "rest" iterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
459 i--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
460 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
461 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
462 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
463 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
464 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
465 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
466
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
467 /* set up the return values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
468 SubString_init(first, str, start, i);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
469 FieldNameIterator_init(rest, str, i, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
470
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
471 /* 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
472 *first_idx = get_integer(first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
473 if (*first_idx == -1 && PyErr_Occurred())
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
474 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
475
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
476 field_name_is_empty = first->start >= first->end;
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 /* 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
479 specified, then we're doing numeric indexing into args. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
480 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
481
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
482 /* 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
483 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
484 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
485 numbering if the field name is omitted. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
486
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
487 /* 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
488 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
489 in that class by itself. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
490 if (auto_number) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
491 /* 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
492 time we're either auto-numbering or manually numbering. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
493 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
494 auto_number->an_state = field_name_is_empty ?
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
495 ANS_AUTO : ANS_MANUAL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
496
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
497 /* 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
498 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
499 index. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
500 if (using_numeric_index)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
501 if (autonumber_state_error(auto_number->an_state,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
502 field_name_is_empty))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
503 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
504 /* 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
505 fields. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
506 if (field_name_is_empty)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
507 *first_idx = (auto_number->an_field_number)++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
508 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
509
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
510 return 1;
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
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 get_field_object returns the object inside {}, before the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
516 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
517 the entire input string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
518 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
519 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
520 get_field_object(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
521 AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
522 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
523 PyObject *obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
524 int ok;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
525 int is_attribute;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
526 SubString name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
527 SubString first;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
528 Py_ssize_t index;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
529 FieldNameIterator rest;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
530
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
531 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
532 &index, &rest, auto_number)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
533 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
534 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
535
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
536 if (index == -1) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
537 /* look up in kwargs */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
538 PyObject *key = SubString_new_object(&first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
539 if (key == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
540 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
541
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
542 /* Use PyObject_GetItem instead of PyDict_GetItem because this
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
543 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
544 a non-dict when called through format_map. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
545 if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
546 PyErr_SetObject(PyExc_KeyError, key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
547 Py_DECREF(key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
548 goto error;
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 Py_DECREF(key);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
551 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
552 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
553 /* 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
554 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
555 used with format_map(), where positional arguments are not
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
556 allowed. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
557 if (args == NULL) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
558 PyErr_SetString(PyExc_ValueError, "Format string contains "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
559 "positional fields");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
560 goto error;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
563 /* look up in args */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
564 obj = PySequence_GetItem(args, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
565 if (obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
566 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
567 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
568
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
569 /* iterate over the rest of the field_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
570 while ((ok = FieldNameIterator_next(&rest, &is_attribute, &index,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
571 &name)) == 2) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
572 PyObject *tmp;
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 if (is_attribute)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
575 /* getattr lookup "." */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
576 tmp = getattr(obj, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
577 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
578 /* getitem lookup "[]" */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
579 if (index == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
580 tmp = getitem_str(obj, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
581 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
582 if (PySequence_Check(obj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
583 tmp = getitem_sequence(obj, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
584 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
585 /* not a sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
586 tmp = getitem_idx(obj, index);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
587 if (tmp == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
588 goto error;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
589
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
590 /* assign to obj */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
591 Py_DECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
592 obj = tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
593 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
594 /* end of iterator, this is the non-error case */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
595 if (ok == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
596 return obj;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
597 error:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
598 Py_XDECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
599 return NULL;
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
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 /***************** Field rendering functions **************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
604 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
605
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
606 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
607 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
608 field object and field specification string generated by
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
609 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
610
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
611 render_field calls fieldobj.__format__(format_spec) method, and
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
612 appends to the output.
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 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
615 render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
616 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
617 int ok = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
618 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
619 PyObject *format_spec_object = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
620 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
621
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
622 /* 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
623 call the formatter directly. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
624 if (PyUnicode_CheckExact(fieldobj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
625 formatter = _PyUnicode_FormatAdvanced;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
626 else if (PyLong_CheckExact(fieldobj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
627 formatter =_PyLong_FormatAdvanced;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
628 else if (PyFloat_CheckExact(fieldobj))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
629 formatter = _PyFloat_FormatAdvanced;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
630
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
631 /* 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
632 (unicode, str) */
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 if (formatter) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
635 /* 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
636 looked up, so call it directly, instead. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
637 result = formatter(fieldobj, format_spec->str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
638 format_spec->start, format_spec->end);
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 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
641 /* 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
642 __format__ takes a string/unicode object for format_spec. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
643 if (format_spec->str)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
644 format_spec_object = PyUnicode_Substring(format_spec->str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
645 format_spec->start,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
646 format_spec->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
647 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
648 format_spec_object = PyUnicode_New(0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
649 if (format_spec_object == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
650 goto done;
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 result = PyObject_Format(fieldobj, format_spec_object);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
653 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
654 if (result == NULL || PyUnicode_READY(result) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
655 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
656
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
657 assert(PyUnicode_Check(result));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
658 ok = output_data(output, result, 0, PyUnicode_GET_LENGTH(result));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
659 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
660 Py_XDECREF(format_spec_object);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
661 Py_XDECREF(result);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
662 return ok;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
665 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
666 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
667 Py_UCS4 *conversion)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
668 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
669 /* 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
670 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
671 field_name_split. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
672
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
675 /* initialize these, as they may be empty */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
676 *conversion = '\0';
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
677 SubString_init(format_spec, NULL, 0, 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 /* 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
680 the string, or a ':' or '!' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
681 field_name->str = str->str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
682 field_name->start = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
683 while (str->start < str->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
684 switch ((c = PyUnicode_READ_CHAR(str->str, str->start++))) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
685 case ':':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
686 case '!':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
687 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
688 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
689 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
690 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
691 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
692 }
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 if (c == '!' || c == ':') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
695 /* we have a format specifier and/or a conversion */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
696 /* don't include the last character */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
697 field_name->end = str->start-1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
698
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
699 /* the format specifier is the rest of the string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
700 format_spec->str = str->str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
701 format_spec->start = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
702 format_spec->end = str->end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
703
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
704 /* see if there's a conversion specifier */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
705 if (c == '!') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
706 /* there must be another character present */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
707 if (format_spec->start >= format_spec->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
708 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
709 "end of format while looking for conversion "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
710 "specifier");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
711 return 0;
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 *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
714
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
715 /* 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
716 if (format_spec->start < format_spec->end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
717 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
718 if (c != ':') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
719 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
720 "expected ':' after format specifier");
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 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
724 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
725 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
726 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
727 /* 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
728 field_name->end = str->start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
729
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
730 return 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
731 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
732
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
733 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
734 /******* Output string allocation and escape-to-markup processing ******/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
735 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
736
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
737 /* MarkupIterator breaks the string into pieces of either literal
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
738 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
739 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
740 use with the Formatter class */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
741
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
742 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
743 SubString str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
744 } MarkupIterator;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
745
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
746 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
747 MarkupIterator_init(MarkupIterator *self, PyObject *str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
748 Py_ssize_t start, Py_ssize_t end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
749 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
750 SubString_init(&self->str, str, start, end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
751 return 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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
754 /* 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
755 string (or something to be expanded) */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
756 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
757 MarkupIterator_next(MarkupIterator *self, SubString *literal,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
758 int *field_present, SubString *field_name,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
759 SubString *format_spec, Py_UCS4 *conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
760 int *format_spec_needs_expanding)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
761 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
762 int at_end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
763 Py_UCS4 c = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
764 Py_ssize_t start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
765 int count;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
766 Py_ssize_t len;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
767 int markup_follows = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
768
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
769 /* initialize all of the output variables */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
770 SubString_init(literal, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
771 SubString_init(field_name, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
772 SubString_init(format_spec, NULL, 0, 0);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
773 *conversion = '\0';
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
774 *format_spec_needs_expanding = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
775 *field_present = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
776
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
777 /* 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
778 path. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
779 if (self->str.start >= self->str.end)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
780 return 1;
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 start = self->str.start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
783
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
784 /* 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
785 escaped '{' or '}', or an unescaped '{'. In order to never
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
786 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
787 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
788 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
789 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
790 the second consecutive brace. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
791 while (self->str.start < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
792 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
793 case '{':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
794 case '}':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
795 markup_follows = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
796 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
797 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
798 continue;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
799 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
800 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
801 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
802
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
803 at_end = self->str.start >= self->str.end;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
804 len = self->str.start - start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
805
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
806 if ((c == '}') && (at_end ||
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
807 (c != PyUnicode_READ_CHAR(self->str.str,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
808 self->str.start)))) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
809 PyErr_SetString(PyExc_ValueError, "Single '}' encountered "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
810 "in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
811 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
812 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
813 if (at_end && c == '{') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
814 PyErr_SetString(PyExc_ValueError, "Single '{' encountered "
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
815 "in format string");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
816 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
817 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
818 if (!at_end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
819 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
820 /* 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
821 markup object following us, just this literal text */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
822 self->str.start++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
823 markup_follows = 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
824 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
825 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
826 len--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
827 }
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 /* record the literal text */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
830 literal->str = self->str.str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
831 literal->start = start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
832 literal->end = start + len;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
833
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
834 if (!markup_follows)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
835 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
836
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
837 /* 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
838 braces. note that this prohibits escaped braces, so that
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
839 format_specs cannot have braces in them. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
840 *field_present = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
841 count = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
842
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
843 start = self->str.start;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
844
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
845 /* 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
846 about that case */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
847 while (self->str.start < self->str.end) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
848 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
849 case '{':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
850 /* the format spec needs to be recursively expanded.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
851 this is an optimization, and not strictly needed */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
852 *format_spec_needs_expanding = 1;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
853 count++;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
854 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
855 case '}':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
856 count--;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
857 if (count <= 0) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
858 /* we're done. parse and get out */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
859 SubString s;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
860
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
861 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
862 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
863 return 0;
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 /* success */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
866 return 2;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
867 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
868 break;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
869 }
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
872 /* end of string while searching for matching '}' */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
873 PyErr_SetString(PyExc_ValueError, "unmatched '{' in format");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
874 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
875 }
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
878 /* do the !r or !s conversion on obj */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
879 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
880 do_conversion(PyObject *obj, Py_UCS4 conversion)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
881 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
882 /* 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
883 might have returned a string? */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
884 switch (conversion) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
885 case 'r':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
886 return PyObject_Repr(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
887 case 's':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
888 return PyObject_Str(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
889 case 'a':
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
890 return PyObject_ASCII(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
891 default:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
892 if (conversion > 32 && conversion < 127) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
893 /* 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
894 (assuming the execution character set is an ASCII
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
895 superset). */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
896 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
897 "Unknown conversion specifier %c",
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
898 (char)conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
899 } else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
900 PyErr_Format(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
901 "Unknown conversion specifier \\x%x",
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
902 (unsigned int)conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
903 return NULL;
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 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
906
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
907 /* given:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
908
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
909 {field_name!conversion:format_spec}
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
910
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
911 compute the result and write it to output.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
912 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
913 just output the string directly, otherwise recursively expand the
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
914 format_spec string.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
915
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
916 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
917 are doing auto field numbering.
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
918 */
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 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
921 output_markup(SubString *field_name, SubString *format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
922 int format_spec_needs_expanding, Py_UCS4 conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
923 OutputString *output, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
924 int recursion_depth, AutoNumber *auto_number)
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 PyObject *tmp = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
927 PyObject *fieldobj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
928 SubString expanded_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
929 SubString *actual_format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
930 int result = 0;
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 /* convert field_name to an object */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
933 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
934 if (fieldobj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
935 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
936
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
937 if (conversion != '\0') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
938 tmp = do_conversion(fieldobj, conversion);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
939 if (tmp == NULL || PyUnicode_READY(tmp) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
940 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
941
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
942 /* do the assignment, transferring ownership: fieldobj = tmp */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
943 Py_DECREF(fieldobj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
944 fieldobj = tmp;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
945 tmp = NULL;
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
948 /* if needed, recurively compute the format_spec */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
949 if (format_spec_needs_expanding) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
950 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
951 auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
952 if (tmp == NULL || PyUnicode_READY(tmp) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
953 goto done;
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 /* 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
956 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
957 render_field. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
958 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
959 actual_format_spec = &expanded_format_spec;
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 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
962 actual_format_spec = format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
963
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
964 if (render_field(fieldobj, actual_format_spec, output) == 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
965 goto done;
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 result = 1;
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 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
970 Py_XDECREF(fieldobj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
971 Py_XDECREF(tmp);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
972
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
973 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
974 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
975
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 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
978 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
979 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
980 and to perform the markup to the output.
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 static int
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
983 do_markup(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
984 OutputString *output, int recursion_depth, AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
985 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
986 MarkupIterator iter;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
987 int format_spec_needs_expanding;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
988 int result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
989 int field_present;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
990 SubString literal;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
991 SubString field_name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
992 SubString format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
993 Py_UCS4 conversion;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
994
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
995 MarkupIterator_init(&iter, input->str, input->start, input->end);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
996 while ((result = MarkupIterator_next(&iter, &literal, &field_present,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
997 &field_name, &format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
998 &conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
999 &format_spec_needs_expanding)) == 2) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1000 if (!output_data(output, literal.str, literal.start, literal.end))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1001 return 0;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1002 if (field_present)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1003 if (!output_markup(&field_name, &format_spec,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1004 format_spec_needs_expanding, conversion, output,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1005 args, kwargs, recursion_depth, auto_number))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1006 return 0;
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 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1009 }
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1012 /*
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1013 build_string allocates the output string and then
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1014 calls do_markup to do the heavy lifting.
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 build_string(SubString *input, PyObject *args, PyObject *kwargs,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1018 int recursion_depth, AutoNumber *auto_number)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1019 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1020 OutputString output;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1021 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1022
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1023 output.data = NULL; /* needed so cleanup code always works */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1024
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1025 /* check the recursion level */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1026 if (recursion_depth <= 0) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1027 PyErr_SetString(PyExc_ValueError,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1028 "Max string recursion exceeded");
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1029 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1030 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1031
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1032 /* initial size is the length of the format string, plus the size
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1033 increment. seems like a reasonable default */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1034 if (!output_initialize(&output,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1035 input->end - input->start +
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1036 INITIAL_SIZE_INCREMENT))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1037 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1038
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1039 if (!do_markup(input, args, kwargs, &output, recursion_depth,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1040 auto_number)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1041 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1042 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1043
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1044 result = PyUnicode_New(output.pos, output.maxchar);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1045 if (!result)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1046 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1047 memcpy(PyUnicode_DATA(result), output.data, output.pos << (output.kind-1));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1048
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1049 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1050 if (output.data)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1051 PyMem_Free(output.data);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1052 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1053 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1054
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1055 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1056 /*********** main routine ***********************************************/
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1059 /* this is the main entry point */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1060 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1061 do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1062 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1063 SubString input;
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 /* PEP 3101 says only 2 levels, so that
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1066 "{0:{1}}".format('abc', 's') # works
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1067 "{0:{1:{2}}}".format('abc', 's', '') # fails
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1068 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1069 int recursion_depth = 2;
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 AutoNumber auto_number;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1072
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1073 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1074 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1075
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1076 AutoNumber_Init(&auto_number);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1077 SubString_init(&input, self, 0, PyUnicode_GET_LENGTH(self));
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1078 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
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 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1082 do_string_format_map(PyObject *self, PyObject *obj)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1083 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1084 return do_string_format(self, NULL, obj);
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
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1087
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1088 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1089 /*********** formatteriterator ******************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1090 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1091
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1092 /* 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
1093 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
1094 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
1095 from Python. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1096
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1097 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1098 PyObject_HEAD
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1099
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1100 PyUnicodeObject *str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1101
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1102 MarkupIterator it_markup;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1103 } formatteriterobject;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1104
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1105 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1106 formatteriter_dealloc(formatteriterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1107 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1108 Py_XDECREF(it->str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1109 PyObject_FREE(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1110 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1111
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1112 /* returns a tuple:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1113 (literal, field_name, format_spec, conversion)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1114
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1115 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
1116 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
1117 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
1118 conversion is either None, or the string after the '!'
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1119 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1120 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1121 formatteriter_next(formatteriterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1122 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1123 SubString literal;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1124 SubString field_name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1125 SubString format_spec;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1126 Py_UCS4 conversion;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1127 int format_spec_needs_expanding;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1128 int field_present;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1129 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
1130 &field_name, &format_spec, &conversion,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1131 &format_spec_needs_expanding);
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 /* 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
1134 memory management needs to be done on them */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1135 assert(0 <= result && result <= 2);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1136 if (result == 0 || result == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1137 /* 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
1138 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1139 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1140 PyObject *literal_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1141 PyObject *field_name_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1142 PyObject *format_spec_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1143 PyObject *conversion_str = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1144 PyObject *tuple = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1145
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1146 literal_str = SubString_new_object(&literal);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1147 if (literal_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1148 goto done;
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 field_name_str = SubString_new_object(&field_name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1151 if (field_name_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1152 goto done;
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 /* 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
1155 format_spec (even if zero length), else return None */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1156 format_spec_str = (field_present ?
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1157 SubString_new_object_or_empty :
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1158 SubString_new_object)(&format_spec);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1159 if (format_spec_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1160 goto done;
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 /* if the conversion is not specified, return a None,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1163 otherwise create a one length string with the conversion
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1164 character */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1165 if (conversion == '\0') {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1166 conversion_str = Py_None;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1167 Py_INCREF(conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1168 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1169 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1170 conversion_str = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1171 &conversion, 1);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1172 if (conversion_str == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1173 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1174
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1175 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
1176 conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1177 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1178 Py_XDECREF(literal_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1179 Py_XDECREF(field_name_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1180 Py_XDECREF(format_spec_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1181 Py_XDECREF(conversion_str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1182 return tuple;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1183 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1184 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1185
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1186 static PyMethodDef formatteriter_methods[] = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1187 {NULL, NULL} /* sentinel */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1188 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1189
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1190 static PyTypeObject PyFormatterIter_Type = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1191 PyVarObject_HEAD_INIT(&PyType_Type, 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1192 "formatteriterator", /* tp_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1193 sizeof(formatteriterobject), /* tp_basicsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1194 0, /* tp_itemsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1195 /* methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1196 (destructor)formatteriter_dealloc, /* tp_dealloc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1197 0, /* tp_print */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1198 0, /* tp_getattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1199 0, /* tp_setattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1200 0, /* tp_reserved */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1201 0, /* tp_repr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1202 0, /* tp_as_number */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1203 0, /* tp_as_sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1204 0, /* tp_as_mapping */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1205 0, /* tp_hash */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1206 0, /* tp_call */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1207 0, /* tp_str */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1208 PyObject_GenericGetAttr, /* tp_getattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1209 0, /* tp_setattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1210 0, /* tp_as_buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1211 Py_TPFLAGS_DEFAULT, /* tp_flags */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1212 0, /* tp_doc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1213 0, /* tp_traverse */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1214 0, /* tp_clear */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1215 0, /* tp_richcompare */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1216 0, /* tp_weaklistoffset */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1217 PyObject_SelfIter, /* tp_iter */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1218 (iternextfunc)formatteriter_next, /* tp_iternext */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1219 formatteriter_methods, /* tp_methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1220 0,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1221 };
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 /* unicode_formatter_parser is used to implement
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1224 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
1225 describing the parsed elements. It's a wrapper around
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1226 stringlib/string_format.h's MarkupIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1227 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1228 formatter_parser(PyObject *ignored, PyUnicodeObject *self)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1229 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1230 formatteriterobject *it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1231
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1232 if (!PyUnicode_Check(self)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1233 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
1234 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1235 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1236
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1237 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1238 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1239
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1240 it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1241 if (it == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1242 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1243
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1244 /* take ownership, give the object to the iterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1245 Py_INCREF(self);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1246 it->str = self;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1247
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1248 /* initialize the contained MarkupIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1249 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
1250 return (PyObject *)it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1251 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1252
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1253
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1254 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1255 /*********** fieldnameiterator ******************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1256 /************************************************************************/
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1257
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1258
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1259 /* 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
1260 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
1261 wrapper around FieldNameIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1262
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1263 typedef struct {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1264 PyObject_HEAD
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 PyUnicodeObject *str;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1267
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1268 FieldNameIterator it_field;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1269 } fieldnameiterobject;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1270
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1271 static void
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1272 fieldnameiter_dealloc(fieldnameiterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1273 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1274 Py_XDECREF(it->str);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1275 PyObject_FREE(it);
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 /* returns a tuple:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1279 (is_attr, value)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1280 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
1281 false if we used index syntax (e.g., '[foo]')
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1282 value is an integer or string
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1283 */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1284 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1285 fieldnameiter_next(fieldnameiterobject *it)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1286 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1287 int result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1288 int is_attr;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1289 Py_ssize_t idx;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1290 SubString name;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1291
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1292 result = FieldNameIterator_next(&it->it_field, &is_attr,
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1293 &idx, &name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1294 if (result == 0 || result == 1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1295 /* 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
1296 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1297 else {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1298 PyObject* result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1299 PyObject* is_attr_obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1300 PyObject* obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1301
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1302 is_attr_obj = PyBool_FromLong(is_attr);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1303 if (is_attr_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1304 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1305
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1306 /* either an integer or a string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1307 if (idx != -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1308 obj = PyLong_FromSsize_t(idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1309 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1310 obj = SubString_new_object(&name);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1311 if (obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1312 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1313
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1314 /* return a tuple of values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1315 result = PyTuple_Pack(2, is_attr_obj, obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1316
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1317 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1318 Py_XDECREF(is_attr_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1319 Py_XDECREF(obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1320 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1321 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1322 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1323
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1324 static PyMethodDef fieldnameiter_methods[] = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1325 {NULL, NULL} /* sentinel */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1326 };
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1327
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1328 static PyTypeObject PyFieldNameIter_Type = {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1329 PyVarObject_HEAD_INIT(&PyType_Type, 0)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1330 "fieldnameiterator", /* tp_name */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1331 sizeof(fieldnameiterobject), /* tp_basicsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1332 0, /* tp_itemsize */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1333 /* methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1334 (destructor)fieldnameiter_dealloc, /* tp_dealloc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1335 0, /* tp_print */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1336 0, /* tp_getattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1337 0, /* tp_setattr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1338 0, /* tp_reserved */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1339 0, /* tp_repr */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1340 0, /* tp_as_number */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1341 0, /* tp_as_sequence */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1342 0, /* tp_as_mapping */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1343 0, /* tp_hash */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1344 0, /* tp_call */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1345 0, /* tp_str */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1346 PyObject_GenericGetAttr, /* tp_getattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1347 0, /* tp_setattro */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1348 0, /* tp_as_buffer */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1349 Py_TPFLAGS_DEFAULT, /* tp_flags */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1350 0, /* tp_doc */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1351 0, /* tp_traverse */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1352 0, /* tp_clear */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1353 0, /* tp_richcompare */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1354 0, /* tp_weaklistoffset */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1355 PyObject_SelfIter, /* tp_iter */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1356 (iternextfunc)fieldnameiter_next, /* tp_iternext */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1357 fieldnameiter_methods, /* tp_methods */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1358 0};
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1359
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1360 /* unicode_formatter_field_name_split is used to implement
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1361 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
1362 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
1363 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
1364 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
1365 field_name_split. The iterator it returns is a
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1366 FieldNameIterator */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1367 static PyObject *
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1368 formatter_field_name_split(PyObject *ignored, PyUnicodeObject *self)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1369 {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1370 SubString first;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1371 Py_ssize_t first_idx;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1372 fieldnameiterobject *it;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1373
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1374 PyObject *first_obj = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1375 PyObject *result = NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1376
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1377 if (!PyUnicode_Check(self)) {
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1378 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
1379 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1380 }
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1381
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1382 if (PyUnicode_READY(self) == -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1383 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1384
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1385 it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1386 if (it == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1387 return NULL;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1388
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1389 /* 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
1390 just to keep the field_name alive */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1391 Py_INCREF(self);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1392 it->str = self;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1393
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1394 /* 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
1395 first_obj in that case. */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1396 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
1397 &first, &first_idx, &it->it_field, NULL))
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1398 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1399
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1400 /* first becomes an integer, if possible; else a string */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1401 if (first_idx != -1)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1402 first_obj = PyLong_FromSsize_t(first_idx);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1403 else
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1404 /* convert "first" into a string object */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1405 first_obj = SubString_new_object(&first);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1406 if (first_obj == NULL)
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1407 goto done;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1408
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1409 /* return a tuple of values */
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1410 result = PyTuple_Pack(2, first_obj, it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1411
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1412 done:
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1413 Py_XDECREF(it);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1414 Py_XDECREF(first_obj);
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1415 return result;
8beaa9a37387 Implement PEP 393.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1416 }