]> granicus.if.org Git - python/commitdiff
PyString_FromFormatV, string_repr: document why these use sprintf
authorTim Peters <tim.peters@gmail.com>
Mon, 3 Dec 2001 01:55:38 +0000 (01:55 +0000)
committerTim Peters <tim.peters@gmail.com>
Mon, 3 Dec 2001 01:55:38 +0000 (01:55 +0000)
instead of PyOS_snprintf; add some relevant comments and asserts.

Objects/stringobject.c

index 2e0d6d65ae22ab1a0ab922f6244c1c2b4106bed2..46bd99adb5aac63ff5edc6b203d93c430865b8ab 100644 (file)
@@ -179,7 +179,7 @@ PyString_FromFormatV(const char *format, va_list vargs)
                        /* skip the 'l' in %ld, since it doesn't change the
                           width.  although only %d is supported (see
                           "expand" section below), others can be easily
-                          add */
+                          added */
                        if (*f == 'l' && *(f+1) == 'd')
                                ++f;
                        
@@ -192,8 +192,9 @@ PyString_FromFormatV(const char *format, va_list vargs)
                                break;
                        case 'd': case 'i': case 'x':
                                (void) va_arg(count, int);
-                               /* 20 bytes should be enough to hold a 64-bit
-                                  integer */
+                               /* 20 bytes is enough to hold a 64-bit
+                                  integer.  Decimal takes the most space.
+                                  This isn't enough for octal. */
                                n += 20;
                                break;
                        case 's':
@@ -205,6 +206,7 @@ PyString_FromFormatV(const char *format, va_list vargs)
                                /* maximum 64-bit pointer representation:
                                 * 0xffffffffffffffff
                                 * so 19 characters is enough.
+                                * XXX I count 18 -- what's the extra for?
                                 */
                                n += 19;
                                break;
@@ -223,6 +225,8 @@ PyString_FromFormatV(const char *format, va_list vargs)
        }
  expand:
        /* step 2: fill the buffer */
+       /* Since we've analyzed how much space we need for the worst case,
+          use sprintf directly instead of the slower PyOS_snprintf. */
        string = PyString_FromStringAndSize(NULL, n);
        if (!string)
                return NULL;
@@ -640,9 +644,12 @@ string_repr(register PyStringObject *op)
                if (strchr(op->ob_sval, '\'') && !strchr(op->ob_sval, '"'))
                        quote = '"';
 
-               p = ((PyStringObject *)v)->ob_sval;
+               p = PyString_AS_STRING(v);
                *p++ = quote;
                for (i = 0; i < op->ob_size; i++) {
+                       /* There's at least enough room for a hex escape
+                          and a closing quote. */
+                       assert(newsize - (p - PyString_AS_STRING(v)) >= 5);
                        c = op->ob_sval[i];
                        if (c == quote || c == '\\')
                                *p++ = '\\', *p++ = c;
@@ -653,16 +660,20 @@ string_repr(register PyStringObject *op)
                        else if (c == '\r')
                                *p++ = '\\', *p++ = 'r';
                        else if (c < ' ' || c >= 0x7f) {
+                               /* For performance, we don't want to call
+                                  PyOS_snprintf here (extra layers of
+                                  function call). */
                                sprintf(p, "\\x%02x", c & 0xff);
                                 p += 4;
                        }
                        else
                                *p++ = c;
                }
+               assert(newsize - (p - PyString_AS_STRING(v)) >= 1);
                *p++ = quote;
                *p = '\0';
                _PyString_Resize(
-                       &v, (int) (p - ((PyStringObject *)v)->ob_sval));
+                       &v, (int) (p - PyString_AS_STRING(v)));
                return v;
        }
 }