summaryrefslogtreecommitdiffstats
path: root/Objects/stringobject.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-12-03 01:55:38 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-12-03 01:55:38 (GMT)
commit9161c8b0a1902269a3fad313ed201137d803dcd4 (patch)
tree84dfb4b190e8a44e68db662efea25aaab98d6207 /Objects/stringobject.c
parent4b80085dddba9cfb06aa3ee74b65371a209c5ab0 (diff)
downloadcpython-9161c8b0a1902269a3fad313ed201137d803dcd4.zip
cpython-9161c8b0a1902269a3fad313ed201137d803dcd4.tar.gz
cpython-9161c8b0a1902269a3fad313ed201137d803dcd4.tar.bz2
PyString_FromFormatV, string_repr: document why these use sprintf
instead of PyOS_snprintf; add some relevant comments and asserts.
Diffstat (limited to 'Objects/stringobject.c')
-rw-r--r--Objects/stringobject.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 2e0d6d6..46bd99a 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -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;
}
}