jim 99/05/21 20:49:33
Modified: src/ap ap_snprintf.c
Log:
Provide some "faster" versions of the
conversion functions when the number value doesn't warrant use of
quads
Revision Changes Path
1.32 +89 -6 apache-1.3/src/ap/ap_snprintf.c
Index: ap_snprintf.c
===================================================================
RCS file: /export/home/cvs/apache-1.3/src/ap/ap_snprintf.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- ap_snprintf.c 1999/05/22 01:46:48 1.31
+++ ap_snprintf.c 1999/05/22 03:49:32 1.32
@@ -344,7 +344,57 @@
* The caller provides a buffer for the string: that is the buf_end argument
* which is a pointer to the END of the buffer + 1 (i.e. if the buffer
* is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * Note: we have 2 versions. One is used when we need to use quads (conv_10),
+ * the other isn't (conv_10_l). We're assuming the latter is faster.
*/
+static char *conv_10_l(register wide_int num, register bool_int is_unsigned,
+ register bool_int *is_negative, char *buf_end,
+ register int *len)
+{
+ register char *p = buf_end;
+ register u_wide_int magnitude;
+
+ if (is_unsigned) {
+ magnitude = (u_wide_int) num;
+ *is_negative = FALSE;
+ }
+ else {
+ *is_negative = (num < 0);
+
+ /*
+ * On a 2's complement machine, negating the most negative integer
+ * results in a number that cannot be represented as a signed integer.
+ * Here is what we do to obtain the number's magnitude:
+ * a. add 1 to the number
+ * b. negate it (becomes positive)
+ * c. convert it to unsigned
+ * d. add 1
+ */
+ if (*is_negative) {
+ wide_int t = num + 1;
+
+ magnitude = ((u_wide_int) -t) + 1;
+ }
+ else
+ magnitude = (u_wide_int) num;
+ }
+
+ /*
+ * We use a do-while loop so that we write at least 1 digit
+ */
+ do {
+ register u_wide_int new_magnitude = magnitude / 10;
+
+ *--p = (char) (magnitude - new_magnitude * 10 + '0');
+ magnitude = new_magnitude;
+ }
+ while (magnitude);
+
+ *len = buf_end - p;
+ return (p);
+}
+
static char *conv_10(register widest_int num, register bool_int is_unsigned,
register bool_int *is_negative, char *buf_end,
register int *len)
@@ -352,6 +402,14 @@
register char *p = buf_end;
register u_widest_int magnitude;
+ /*
+ * If the value is less than the maximum unsigned long value,
+ * then we know we aren't using quads, so use the faster function
+ */
+ if (num <= ULONG_MAX)
+ return(conv_10_l( (wide_int)num, is_unsigned, is_negative,
+ buf_end, len));
+
if (is_unsigned) {
magnitude = (u_widest_int) num;
*is_negative = FALSE;
@@ -401,13 +459,13 @@
bool_int is_negative;
int sub_len;
- p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len);
+ p = conv_10_l((addr & 0x000000FF) , TRUE, &is_negative, p,
&sub_len);
*--p = '.';
- p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len);
+ p = conv_10_l((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p,
&sub_len);
*--p = '.';
- p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
+ p = conv_10_l((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p,
&sub_len);
*--p = '.';
- p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
+ p = conv_10_l((addr & 0xFF000000) >> 24, TRUE, &is_negative, p,
&sub_len);
*len = buf_end - p;
return (p);
@@ -421,7 +479,7 @@
bool_int is_negative;
int sub_len;
- p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
+ p = conv_10_l(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
*--p = ':';
p = conv_in_addr(&si->sin_addr, p, &sub_len);
@@ -498,7 +556,7 @@
*s++ = format; /* either e or E */
decimal_point--;
if (decimal_point != 0) {
- p = conv_10((widest_int) decimal_point, FALSE,
&exponent_is_negative,
+ p = conv_10_l((wide_int) decimal_point, FALSE,
&exponent_is_negative,
&temp[EXPONENT_LENGTH], &t_len);
*s++ = exponent_is_negative ? '-' : '+';
@@ -531,7 +589,29 @@
* The caller provides a buffer for the string: that is the buf_end argument
* which is a pointer to the END of the buffer + 1 (i.e. if the buffer
* is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * As with conv_10, we have a faster version which is used when
+ * the number isn't quad size.
*/
+static char *conv_p2_l(register u_wide_int num, register int nbits,
+ char format, char *buf_end, register int *len)
+{
+ register int mask = (1 << nbits) - 1;
+ register char *p = buf_end;
+ static const char low_digits[] = "0123456789abcdef";
+ static const char upper_digits[] = "0123456789ABCDEF";
+ register const char *digits = (format == 'X') ? upper_digits :
low_digits;
+
+ do {
+ *--p = digits[num & mask];
+ num >>= nbits;
+ }
+ while (num);
+
+ *len = buf_end - p;
+ return (p);
+}
+
static char *conv_p2(register u_widest_int num, register int nbits,
char format, char *buf_end, register int *len)
{
@@ -540,6 +620,9 @@
static const char low_digits[] = "0123456789abcdef";
static const char upper_digits[] = "0123456789ABCDEF";
register const char *digits = (format == 'X') ? upper_digits :
low_digits;
+
+ if (num <= ULONG_MAX)
+ return(conv_p2_l( (u_wide_int)num, nbits, format, buf_end, len));
do {
*--p = digits[num & mask];