blob: cae6ea113a1dbea47272602d70bd28263290d3fd [file] [log] [blame]
Gregory P. Smith60d241f2007-10-16 06:31:30 +00001/* NOTE: this API is -ONLY- for use with single byte character strings. */
2/* Do not use it with Unicode. */
3
Gregory P. Smith60d241f2007-10-16 06:31:30 +00004/* the more complicated methods. parts of these should be pulled out into the
5 shared code in bytes_methods.c to cut down on duplicate code bloat. */
6
7PyDoc_STRVAR(expandtabs__doc__,
Ezio Melotti745d54d2013-11-16 19:10:57 +02008"B.expandtabs(tabsize=8) -> copy of B\n\
Gregory P. Smith60d241f2007-10-16 06:31:30 +00009\n\
10Return a copy of B where all tab characters are expanded using spaces.\n\
11If tabsize is not given, a tab size of 8 characters is assumed.");
12
13static PyObject*
Ezio Melotti745d54d2013-11-16 19:10:57 +020014stringlib_expandtabs(PyObject *self, PyObject *args, PyObject *kwds)
Gregory P. Smith60d241f2007-10-16 06:31:30 +000015{
16 const char *e, *p;
17 char *q;
Benjamin Peterson23cf4032014-03-30 19:47:57 -040018 Py_ssize_t i, j;
Gregory P. Smith60d241f2007-10-16 06:31:30 +000019 PyObject *u;
Ezio Melotti745d54d2013-11-16 19:10:57 +020020 static char *kwlist[] = {"tabsize", 0};
Gregory P. Smith60d241f2007-10-16 06:31:30 +000021 int tabsize = 8;
Ezio Melotti6b027722013-04-21 04:07:51 +030022
Ezio Melotti745d54d2013-11-16 19:10:57 +020023 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:expandtabs",
24 kwlist, &tabsize))
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000025 return NULL;
Ezio Melotti6b027722013-04-21 04:07:51 +030026
Gregory P. Smith60d241f2007-10-16 06:31:30 +000027 /* First pass: determine size of output string */
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000028 i = j = 0;
Gregory P. Smith60d241f2007-10-16 06:31:30 +000029 e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
Benjamin Peterson23cf4032014-03-30 19:47:57 -040030 for (p = STRINGLIB_STR(self); p < e; p++) {
Gregory P. Smith60d241f2007-10-16 06:31:30 +000031 if (*p == '\t') {
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000032 if (tabsize > 0) {
Benjamin Peterson23cf4032014-03-30 19:47:57 -040033 Py_ssize_t incr = tabsize - (j % tabsize);
34 if (j > PY_SSIZE_T_MAX - incr)
35 goto overflow;
36 j += incr;
Gregory P. Smith60d241f2007-10-16 06:31:30 +000037 }
38 }
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000039 else {
Benjamin Peterson23cf4032014-03-30 19:47:57 -040040 if (j > PY_SSIZE_T_MAX - 1)
41 goto overflow;
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000042 j++;
43 if (*p == '\n' || *p == '\r') {
Benjamin Peterson23cf4032014-03-30 19:47:57 -040044 if (i > PY_SSIZE_T_MAX - j)
45 goto overflow;
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000046 i += j;
47 j = 0;
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000048 }
49 }
Gregory P. Smith60d241f2007-10-16 06:31:30 +000050 }
Ezio Melotti6b027722013-04-21 04:07:51 +030051
Benjamin Peterson23cf4032014-03-30 19:47:57 -040052 if (i > PY_SSIZE_T_MAX - j)
53 goto overflow;
Benjamin Peterson0ad60982014-03-30 19:52:22 -040054
Gregory P. Smith60d241f2007-10-16 06:31:30 +000055 /* Second pass: create output string and fill it */
56 u = STRINGLIB_NEW(NULL, i + j);
57 if (!u)
58 return NULL;
Ezio Melotti6b027722013-04-21 04:07:51 +030059
Gregory P. Smith60d241f2007-10-16 06:31:30 +000060 j = 0;
61 q = STRINGLIB_STR(u);
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000062
Benjamin Peterson23cf4032014-03-30 19:47:57 -040063 for (p = STRINGLIB_STR(self); p < e; p++) {
Gregory P. Smith60d241f2007-10-16 06:31:30 +000064 if (*p == '\t') {
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000065 if (tabsize > 0) {
66 i = tabsize - (j % tabsize);
67 j += i;
68 while (i--)
69 *q++ = ' ';
70 }
71 }
72 else {
Gregory P. Smith60d241f2007-10-16 06:31:30 +000073 j++;
Antoine Pitrou8d4e5052009-01-13 22:59:11 +000074 *q++ = *p;
Gregory P. Smith60d241f2007-10-16 06:31:30 +000075 if (*p == '\n' || *p == '\r')
76 j = 0;
77 }
Benjamin Peterson23cf4032014-03-30 19:47:57 -040078 }
Ezio Melotti6b027722013-04-21 04:07:51 +030079
Gregory P. Smith60d241f2007-10-16 06:31:30 +000080 return u;
Benjamin Peterson23cf4032014-03-30 19:47:57 -040081 overflow:
82 PyErr_SetString(PyExc_OverflowError, "result too long");
83 return NULL;
Gregory P. Smith60d241f2007-10-16 06:31:30 +000084}
85
86Py_LOCAL_INLINE(PyObject *)
87pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
88{
89 PyObject *u;
90
91 if (left < 0)
92 left = 0;
93 if (right < 0)
94 right = 0;
95
96 if (left == 0 && right == 0 && STRINGLIB_CHECK_EXACT(self)) {
97#if STRINGLIB_MUTABLE
98 /* We're defined as returning a copy; If the object is mutable
99 * that means we must make an identical copy. */
100 return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
101#else
102 Py_INCREF(self);
103 return (PyObject *)self;
104#endif /* STRINGLIB_MUTABLE */
105 }
106
107 u = STRINGLIB_NEW(NULL,
108 left + STRINGLIB_LEN(self) + right);
109 if (u) {
110 if (left)
111 memset(STRINGLIB_STR(u), fill, left);
112 Py_MEMCPY(STRINGLIB_STR(u) + left,
113 STRINGLIB_STR(self),
114 STRINGLIB_LEN(self));
115 if (right)
116 memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
117 fill, right);
118 }
119
120 return u;
121}
122
123PyDoc_STRVAR(ljust__doc__,
Guido van Rossum98297ee2007-11-06 21:34:58 +0000124"B.ljust(width[, fillchar]) -> copy of B\n"
Gregory P. Smith60d241f2007-10-16 06:31:30 +0000125"\n"
126"Return B left justified in a string of length width. Padding is\n"
127"done using the specified fill character (default is a space).");
128
129static PyObject *
130stringlib_ljust(PyObject *self, PyObject *args)
131{
132 Py_ssize_t width;
133 char fillchar = ' ';
134
135 if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
136 return NULL;
137
138 if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
139#if STRINGLIB_MUTABLE
140 /* We're defined as returning a copy; If the object is mutable
141 * that means we must make an identical copy. */
142 return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
143#else
144 Py_INCREF(self);
145 return (PyObject*) self;
146#endif
147 }
148
149 return pad(self, 0, width - STRINGLIB_LEN(self), fillchar);
150}
151
152
153PyDoc_STRVAR(rjust__doc__,
Guido van Rossum98297ee2007-11-06 21:34:58 +0000154"B.rjust(width[, fillchar]) -> copy of B\n"
Gregory P. Smith60d241f2007-10-16 06:31:30 +0000155"\n"
156"Return B right justified in a string of length width. Padding is\n"
157"done using the specified fill character (default is a space)");
158
159static PyObject *
160stringlib_rjust(PyObject *self, PyObject *args)
161{
162 Py_ssize_t width;
163 char fillchar = ' ';
164
165 if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))
166 return NULL;
167
168 if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
169#if STRINGLIB_MUTABLE
170 /* We're defined as returning a copy; If the object is mutable
171 * that means we must make an identical copy. */
172 return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
173#else
174 Py_INCREF(self);
175 return (PyObject*) self;
176#endif
177 }
178
179 return pad(self, width - STRINGLIB_LEN(self), 0, fillchar);
180}
181
182
183PyDoc_STRVAR(center__doc__,
Guido van Rossum98297ee2007-11-06 21:34:58 +0000184"B.center(width[, fillchar]) -> copy of B\n"
Gregory P. Smith60d241f2007-10-16 06:31:30 +0000185"\n"
Guido van Rossum98297ee2007-11-06 21:34:58 +0000186"Return B centered in a string of length width. Padding is\n"
187"done using the specified fill character (default is a space).");
Gregory P. Smith60d241f2007-10-16 06:31:30 +0000188
189static PyObject *
190stringlib_center(PyObject *self, PyObject *args)
191{
192 Py_ssize_t marg, left;
193 Py_ssize_t width;
194 char fillchar = ' ';
195
196 if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))
197 return NULL;
198
199 if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
200#if STRINGLIB_MUTABLE
201 /* We're defined as returning a copy; If the object is mutable
202 * that means we must make an identical copy. */
203 return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
204#else
205 Py_INCREF(self);
206 return (PyObject*) self;
207#endif
208 }
209
210 marg = width - STRINGLIB_LEN(self);
211 left = marg / 2 + (marg & width & 1);
212
213 return pad(self, left, marg - left, fillchar);
214}
215
216PyDoc_STRVAR(zfill__doc__,
Guido van Rossum98297ee2007-11-06 21:34:58 +0000217"B.zfill(width) -> copy of B\n"
Gregory P. Smith60d241f2007-10-16 06:31:30 +0000218"\n"
219"Pad a numeric string B with zeros on the left, to fill a field\n"
220"of the specified width. B is never truncated.");
221
222static PyObject *
223stringlib_zfill(PyObject *self, PyObject *args)
224{
225 Py_ssize_t fill;
226 PyObject *s;
227 char *p;
228 Py_ssize_t width;
229
230 if (!PyArg_ParseTuple(args, "n:zfill", &width))
231 return NULL;
232
233 if (STRINGLIB_LEN(self) >= width) {
234 if (STRINGLIB_CHECK_EXACT(self)) {
235#if STRINGLIB_MUTABLE
236 /* We're defined as returning a copy; If the object is mutable
237 * that means we must make an identical copy. */
238 return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
239#else
240 Py_INCREF(self);
241 return (PyObject*) self;
242#endif
243 }
244 else
245 return STRINGLIB_NEW(
246 STRINGLIB_STR(self),
247 STRINGLIB_LEN(self)
248 );
249 }
250
251 fill = width - STRINGLIB_LEN(self);
252
253 s = pad(self, fill, 0, '0');
254
255 if (s == NULL)
256 return NULL;
257
258 p = STRINGLIB_STR(s);
259 if (p[fill] == '+' || p[fill] == '-') {
260 /* move sign to beginning of string */
261 p[0] = p[fill];
262 p[fill] = '0';
263 }
264
265 return (PyObject*) s;
266}