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 | stringlib_expandtabs(PyObject *self, PyObject *args)
|
---|
15 | {
|
---|
16 | const char *e, *p;
|
---|
17 | char *q;
|
---|
18 | size_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 | j += tabsize - (j % tabsize);
|
---|
32 | if (j > PY_SSIZE_T_MAX) {
|
---|
33 | PyErr_SetString(PyExc_OverflowError,
|
---|
34 | "result is too long");
|
---|
35 | return NULL;
|
---|
36 | }
|
---|
37 | }
|
---|
38 | }
|
---|
39 | else {
|
---|
40 | j++;
|
---|
41 | if (*p == '\n' || *p == '\r') {
|
---|
42 | i += j;
|
---|
43 | j = 0;
|
---|
44 | if (i > PY_SSIZE_T_MAX) {
|
---|
45 | PyErr_SetString(PyExc_OverflowError,
|
---|
46 | "result is too long");
|
---|
47 | return NULL;
|
---|
48 | }
|
---|
49 | }
|
---|
50 | }
|
---|
51 |
|
---|
52 | if ((i + j) > PY_SSIZE_T_MAX) {
|
---|
53 | PyErr_SetString(PyExc_OverflowError, "result is too long");
|
---|
54 | return NULL;
|
---|
55 | }
|
---|
56 |
|
---|
57 | /* Second pass: create output string and fill it */
|
---|
58 | u = STRINGLIB_NEW(NULL, i + j);
|
---|
59 | if (!u)
|
---|
60 | return NULL;
|
---|
61 |
|
---|
62 | j = 0;
|
---|
63 | q = STRINGLIB_STR(u);
|
---|
64 |
|
---|
65 | for (p = STRINGLIB_STR(self); p < e; p++)
|
---|
66 | if (*p == '\t') {
|
---|
67 | if (tabsize > 0) {
|
---|
68 | i = tabsize - (j % tabsize);
|
---|
69 | j += i;
|
---|
70 | while (i--)
|
---|
71 | *q++ = ' ';
|
---|
72 | }
|
---|
73 | }
|
---|
74 | else {
|
---|
75 | j++;
|
---|
76 | *q++ = *p;
|
---|
77 | if (*p == '\n' || *p == '\r')
|
---|
78 | j = 0;
|
---|
79 | }
|
---|
80 |
|
---|
81 | return u;
|
---|
82 | }
|
---|
83 |
|
---|
84 | Py_LOCAL_INLINE(PyObject *)
|
---|
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 *
|
---|
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 *
|
---|
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 *
|
---|
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 *
|
---|
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 | }
|
---|