Home | History | Annotate | Download | only in stringlib
      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     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 *)
     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 }
    265