| 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 | }
|
|---|