]>
Commit | Line | Data |
---|---|---|
53b2ba57 DM |
1 | /* NOTE: this API is -ONLY- for use with single byte character strings. */\r |
2 | /* Do not use it with Unicode. */\r | |
3 | \r | |
4 | /* the more complicated methods. parts of these should be pulled out into the\r | |
5 | shared code in bytes_methods.c to cut down on duplicate code bloat. */\r | |
6 | \r | |
7 | PyDoc_STRVAR(expandtabs__doc__,\r | |
8 | "B.expandtabs([tabsize]) -> copy of B\n\\r | |
9 | \n\\r | |
10 | Return a copy of B where all tab characters are expanded using spaces.\n\\r | |
11 | If tabsize is not given, a tab size of 8 characters is assumed.");\r | |
12 | \r | |
13 | static PyObject*\r | |
14 | stringlib_expandtabs(PyObject *self, PyObject *args)\r | |
15 | {\r | |
16 | const char *e, *p;\r | |
17 | char *q;\r | |
18 | Py_ssize_t i, j;\r | |
19 | PyObject *u;\r | |
20 | int tabsize = 8;\r | |
21 | \r | |
22 | if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))\r | |
23 | return NULL;\r | |
24 | \r | |
25 | /* First pass: determine size of output string */\r | |
26 | i = j = 0;\r | |
27 | e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);\r | |
28 | for (p = STRINGLIB_STR(self); p < e; p++) {\r | |
29 | if (*p == '\t') {\r | |
30 | if (tabsize > 0) {\r | |
31 | Py_ssize_t incr = tabsize - (j % tabsize);\r | |
32 | if (j > PY_SSIZE_T_MAX - incr)\r | |
33 | goto overflow;\r | |
34 | j += incr;\r | |
35 | }\r | |
36 | }\r | |
37 | else {\r | |
38 | if (j > PY_SSIZE_T_MAX - 1)\r | |
39 | goto overflow;\r | |
40 | j++;\r | |
41 | if (*p == '\n' || *p == '\r') {\r | |
42 | if (i > PY_SSIZE_T_MAX - j)\r | |
43 | goto overflow;\r | |
44 | i += j;\r | |
45 | j = 0;\r | |
46 | }\r | |
47 | }\r | |
48 | }\r | |
49 | \r | |
50 | if (i > PY_SSIZE_T_MAX - j)\r | |
51 | goto overflow;\r | |
52 | \r | |
53 | /* Second pass: create output string and fill it */\r | |
54 | u = STRINGLIB_NEW(NULL, i + j);\r | |
55 | if (!u)\r | |
56 | return NULL;\r | |
57 | \r | |
58 | j = 0;\r | |
59 | q = STRINGLIB_STR(u);\r | |
60 | \r | |
61 | for (p = STRINGLIB_STR(self); p < e; p++) {\r | |
62 | if (*p == '\t') {\r | |
63 | if (tabsize > 0) {\r | |
64 | i = tabsize - (j % tabsize);\r | |
65 | j += i;\r | |
66 | while (i--)\r | |
67 | *q++ = ' ';\r | |
68 | }\r | |
69 | }\r | |
70 | else {\r | |
71 | j++;\r | |
72 | *q++ = *p;\r | |
73 | if (*p == '\n' || *p == '\r')\r | |
74 | j = 0;\r | |
75 | }\r | |
76 | }\r | |
77 | \r | |
78 | return u;\r | |
79 | overflow:\r | |
80 | PyErr_SetString(PyExc_OverflowError, "result too long");\r | |
81 | return NULL;\r | |
82 | }\r | |
83 | \r | |
84 | Py_LOCAL_INLINE(PyObject *)\r | |
85 | pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)\r | |
86 | {\r | |
87 | PyObject *u;\r | |
88 | \r | |
89 | if (left < 0)\r | |
90 | left = 0;\r | |
91 | if (right < 0)\r | |
92 | right = 0;\r | |
93 | \r | |
94 | if (left == 0 && right == 0 && STRINGLIB_CHECK_EXACT(self)) {\r | |
95 | #if STRINGLIB_MUTABLE\r | |
96 | /* We're defined as returning a copy; If the object is mutable\r | |
97 | * that means we must make an identical copy. */\r | |
98 | return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r | |
99 | #else\r | |
100 | Py_INCREF(self);\r | |
101 | return (PyObject *)self;\r | |
102 | #endif /* STRINGLIB_MUTABLE */\r | |
103 | }\r | |
104 | \r | |
105 | u = STRINGLIB_NEW(NULL,\r | |
106 | left + STRINGLIB_LEN(self) + right);\r | |
107 | if (u) {\r | |
108 | if (left)\r | |
109 | memset(STRINGLIB_STR(u), fill, left);\r | |
110 | Py_MEMCPY(STRINGLIB_STR(u) + left,\r | |
111 | STRINGLIB_STR(self),\r | |
112 | STRINGLIB_LEN(self));\r | |
113 | if (right)\r | |
114 | memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),\r | |
115 | fill, right);\r | |
116 | }\r | |
117 | \r | |
118 | return u;\r | |
119 | }\r | |
120 | \r | |
121 | PyDoc_STRVAR(ljust__doc__,\r | |
122 | "B.ljust(width[, fillchar]) -> copy of B\n"\r | |
123 | "\n"\r | |
124 | "Return B left justified in a string of length width. Padding is\n"\r | |
125 | "done using the specified fill character (default is a space).");\r | |
126 | \r | |
127 | static PyObject *\r | |
128 | stringlib_ljust(PyObject *self, PyObject *args)\r | |
129 | {\r | |
130 | Py_ssize_t width;\r | |
131 | char fillchar = ' ';\r | |
132 | \r | |
133 | if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))\r | |
134 | return NULL;\r | |
135 | \r | |
136 | if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {\r | |
137 | #if STRINGLIB_MUTABLE\r | |
138 | /* We're defined as returning a copy; If the object is mutable\r | |
139 | * that means we must make an identical copy. */\r | |
140 | return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r | |
141 | #else\r | |
142 | Py_INCREF(self);\r | |
143 | return (PyObject*) self;\r | |
144 | #endif\r | |
145 | }\r | |
146 | \r | |
147 | return pad(self, 0, width - STRINGLIB_LEN(self), fillchar);\r | |
148 | }\r | |
149 | \r | |
150 | \r | |
151 | PyDoc_STRVAR(rjust__doc__,\r | |
152 | "B.rjust(width[, fillchar]) -> copy of B\n"\r | |
153 | "\n"\r | |
154 | "Return B right justified in a string of length width. Padding is\n"\r | |
155 | "done using the specified fill character (default is a space)");\r | |
156 | \r | |
157 | static PyObject *\r | |
158 | stringlib_rjust(PyObject *self, PyObject *args)\r | |
159 | {\r | |
160 | Py_ssize_t width;\r | |
161 | char fillchar = ' ';\r | |
162 | \r | |
163 | if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))\r | |
164 | return NULL;\r | |
165 | \r | |
166 | if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {\r | |
167 | #if STRINGLIB_MUTABLE\r | |
168 | /* We're defined as returning a copy; If the object is mutable\r | |
169 | * that means we must make an identical copy. */\r | |
170 | return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r | |
171 | #else\r | |
172 | Py_INCREF(self);\r | |
173 | return (PyObject*) self;\r | |
174 | #endif\r | |
175 | }\r | |
176 | \r | |
177 | return pad(self, width - STRINGLIB_LEN(self), 0, fillchar);\r | |
178 | }\r | |
179 | \r | |
180 | \r | |
181 | PyDoc_STRVAR(center__doc__,\r | |
182 | "B.center(width[, fillchar]) -> copy of B\n"\r | |
183 | "\n"\r | |
184 | "Return B centered in a string of length width. Padding is\n"\r | |
185 | "done using the specified fill character (default is a space).");\r | |
186 | \r | |
187 | static PyObject *\r | |
188 | stringlib_center(PyObject *self, PyObject *args)\r | |
189 | {\r | |
190 | Py_ssize_t marg, left;\r | |
191 | Py_ssize_t width;\r | |
192 | char fillchar = ' ';\r | |
193 | \r | |
194 | if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))\r | |
195 | return NULL;\r | |
196 | \r | |
197 | if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {\r | |
198 | #if STRINGLIB_MUTABLE\r | |
199 | /* We're defined as returning a copy; If the object is mutable\r | |
200 | * that means we must make an identical copy. */\r | |
201 | return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r | |
202 | #else\r | |
203 | Py_INCREF(self);\r | |
204 | return (PyObject*) self;\r | |
205 | #endif\r | |
206 | }\r | |
207 | \r | |
208 | marg = width - STRINGLIB_LEN(self);\r | |
209 | left = marg / 2 + (marg & width & 1);\r | |
210 | \r | |
211 | return pad(self, left, marg - left, fillchar);\r | |
212 | }\r | |
213 | \r | |
214 | PyDoc_STRVAR(zfill__doc__,\r | |
215 | "B.zfill(width) -> copy of B\n"\r | |
216 | "\n"\r | |
217 | "Pad a numeric string B with zeros on the left, to fill a field\n"\r | |
218 | "of the specified width. B is never truncated.");\r | |
219 | \r | |
220 | static PyObject *\r | |
221 | stringlib_zfill(PyObject *self, PyObject *args)\r | |
222 | {\r | |
223 | Py_ssize_t fill;\r | |
224 | PyObject *s;\r | |
225 | char *p;\r | |
226 | Py_ssize_t width;\r | |
227 | \r | |
228 | if (!PyArg_ParseTuple(args, "n:zfill", &width))\r | |
229 | return NULL;\r | |
230 | \r | |
231 | if (STRINGLIB_LEN(self) >= width) {\r | |
232 | if (STRINGLIB_CHECK_EXACT(self)) {\r | |
233 | #if STRINGLIB_MUTABLE\r | |
234 | /* We're defined as returning a copy; If the object is mutable\r | |
235 | * that means we must make an identical copy. */\r | |
236 | return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));\r | |
237 | #else\r | |
238 | Py_INCREF(self);\r | |
239 | return (PyObject*) self;\r | |
240 | #endif\r | |
241 | }\r | |
242 | else\r | |
243 | return STRINGLIB_NEW(\r | |
244 | STRINGLIB_STR(self),\r | |
245 | STRINGLIB_LEN(self)\r | |
246 | );\r | |
247 | }\r | |
248 | \r | |
249 | fill = width - STRINGLIB_LEN(self);\r | |
250 | \r | |
251 | s = pad(self, fill, 0, '0');\r | |
252 | \r | |
253 | if (s == NULL)\r | |
254 | return NULL;\r | |
255 | \r | |
256 | p = STRINGLIB_STR(s);\r | |
257 | if (p[fill] == '+' || p[fill] == '-') {\r | |
258 | /* move sign to beginning of string */\r | |
259 | p[0] = p[fill];\r | |
260 | p[fill] = '0';\r | |
261 | }\r | |
262 | \r | |
263 | return (PyObject*) s;\r | |
264 | }\r |