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*
stringlib_expandtabs(PyObject * self,PyObject * args)14 stringlib_expandtabs(PyObject *self, PyObject *args)
15 {
16     const char *e, *p;
17     char *q;
18     Py_ssize_t i, j;
19     PyObject *u;
20     int tabsize = 8;
21 
22     if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
23         return NULL;
24 
25     /* First pass: determine size of output string */
26     i = j = 0;
27     e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
28     for (p = STRINGLIB_STR(self); p < e; p++) {
29         if (*p == '\t') {
30             if (tabsize > 0) {
31                 Py_ssize_t incr = tabsize - (j % tabsize);
32                 if (j > PY_SSIZE_T_MAX - incr)
33                     goto overflow;
34                 j += incr;
35             }
36         }
37         else {
38             if (j > PY_SSIZE_T_MAX - 1)
39                 goto overflow;
40             j++;
41             if (*p == '\n' || *p == '\r') {
42                 if (i > PY_SSIZE_T_MAX - j)
43                     goto overflow;
44                 i += j;
45                 j = 0;
46             }
47         }
48     }
49 
50     if (i > PY_SSIZE_T_MAX - j)
51         goto overflow;
52 
53     /* Second pass: create output string and fill it */
54     u = STRINGLIB_NEW(NULL, i + j);
55     if (!u)
56         return NULL;
57 
58     j = 0;
59     q = STRINGLIB_STR(u);
60 
61     for (p = STRINGLIB_STR(self); p < e; p++) {
62         if (*p == '\t') {
63             if (tabsize > 0) {
64                 i = tabsize - (j % tabsize);
65                 j += i;
66                 while (i--)
67                     *q++ = ' ';
68             }
69         }
70         else {
71             j++;
72             *q++ = *p;
73             if (*p == '\n' || *p == '\r')
74                 j = 0;
75         }
76     }
77 
78     return u;
79   overflow:
80     PyErr_SetString(PyExc_OverflowError, "result too long");
81     return NULL;
82 }
83 
84 Py_LOCAL_INLINE(PyObject *)
pad(PyObject * self,Py_ssize_t left,Py_ssize_t right,char fill)85 pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
86 {
87     PyObject *u;
88 
89     if (left < 0)
90         left = 0;
91     if (right < 0)
92         right = 0;
93 
94     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         return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
99 #else
100         Py_INCREF(self);
101         return (PyObject *)self;
102 #endif /* STRINGLIB_MUTABLE */
103     }
104 
105     u = STRINGLIB_NEW(NULL,
106 				   left + STRINGLIB_LEN(self) + right);
107     if (u) {
108         if (left)
109             memset(STRINGLIB_STR(u), fill, left);
110         Py_MEMCPY(STRINGLIB_STR(u) + left,
111 	       STRINGLIB_STR(self),
112 	       STRINGLIB_LEN(self));
113         if (right)
114             memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
115 		   fill, right);
116     }
117 
118     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 *
stringlib_ljust(PyObject * self,PyObject * args)128 stringlib_ljust(PyObject *self, PyObject *args)
129 {
130     Py_ssize_t width;
131     char fillchar = ' ';
132 
133     if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
134         return NULL;
135 
136     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         return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
141 #else
142         Py_INCREF(self);
143         return (PyObject*) self;
144 #endif
145     }
146 
147     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 *
stringlib_rjust(PyObject * self,PyObject * args)158 stringlib_rjust(PyObject *self, PyObject *args)
159 {
160     Py_ssize_t width;
161     char fillchar = ' ';
162 
163     if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))
164         return NULL;
165 
166     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         return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
171 #else
172         Py_INCREF(self);
173         return (PyObject*) self;
174 #endif
175     }
176 
177     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 *
stringlib_center(PyObject * self,PyObject * args)188 stringlib_center(PyObject *self, PyObject *args)
189 {
190     Py_ssize_t marg, left;
191     Py_ssize_t width;
192     char fillchar = ' ';
193 
194     if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))
195         return NULL;
196 
197     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         return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
202 #else
203         Py_INCREF(self);
204         return (PyObject*) self;
205 #endif
206     }
207 
208     marg = width - STRINGLIB_LEN(self);
209     left = marg / 2 + (marg & width & 1);
210 
211     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 *
stringlib_zfill(PyObject * self,PyObject * args)221 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     if (!PyArg_ParseTuple(args, "n:zfill", &width))
229         return NULL;
230 
231     if (STRINGLIB_LEN(self) >= width) {
232         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             return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
237 #else
238             Py_INCREF(self);
239             return (PyObject*) self;
240 #endif
241         }
242         else
243             return STRINGLIB_NEW(
244                 STRINGLIB_STR(self),
245                 STRINGLIB_LEN(self)
246             );
247     }
248 
249     fill = width - STRINGLIB_LEN(self);
250 
251     s = pad(self, fill, 0, '0');
252 
253     if (s == NULL)
254         return NULL;
255 
256     p = STRINGLIB_STR(s);
257     if (p[fill] == '+' || p[fill] == '-') {
258         /* move sign to beginning of string */
259         p[0] = p[fill];
260         p[fill] = '0';
261     }
262 
263     return (PyObject*) s;
264 }
265