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