]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
vsprintf-further-optimize-decimal-conversion-v2
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 25 Apr 2012 01:03:56 +0000 (11:03 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Mon, 30 Apr 2012 05:17:30 +0000 (15:17 +1000)
Here is a new version. I also plugged a hole in num_to_str() -
it was assuming it's safe to call put_dec() for num=0.
(We never tripped over it before because the single caller
of num_to_str() takes care of that case).

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Cc: Michal Nazarewicz <mina86@mina86.com>
Cc: Douglas W Jones <jones@cs.uiowa.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/asm-generic/bitsperlong.h
lib/vsprintf.c

index 4ae54e07de83d2b970d88807f662bcfe300f2ddc..a7b0914348fd0fce08ed7cb42bbe2c8fbacbf8f9 100644 (file)
@@ -28,5 +28,9 @@
 #error Inconsistent word size. Check asm/bitsperlong.h
 #endif
 
+#ifndef BITS_PER_LONG_LONG
+#define BITS_PER_LONG_LONG 64
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_GENERIC_BITS_PER_LONG */
index f8ae3b3c8adfff8f82a62fbd3bc0c9d32f6e92e9..c7e8563f8a374190059c168e45fa28aeceb0c347 100644 (file)
@@ -116,7 +116,7 @@ int skip_atoi(const char **s)
  * (with permission from the author, Douglas W. Jones).
  */
 
-#if BITS_PER_LONG != 32 || (~(0ULL)>>1) != ((1ULL<<63)-1)
+#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
 /* Formats correctly any integer in [0, 999999999] */
 static noinline_for_stack
 char *put_dec_full9(char *buf, unsigned q)
@@ -215,7 +215,7 @@ char *put_dec_trunc8(char *buf, unsigned r)
  * Else (if long is 32 bits and long long is 64 bits) we use second one.
  */
 
-#if BITS_PER_LONG != 32 || ((~0ULL)>>1) != ((1ULL<<63)-1)
+#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
 
 /* First algorithm: generic */
 
@@ -233,7 +233,7 @@ char *put_dec(char *buf, unsigned long long n)
 
 #else
 
-/* Second algorithm: valid only for 32-bit longs, 64-bit long longs */
+/* Second algorithm: valid only for 64-bit long longs */
 
 static noinline_for_stack
 char *put_dec_full4(char *buf, unsigned q)
@@ -296,6 +296,7 @@ char *put_dec(char *buf, unsigned long long n)
 }
 
 #endif
+
 /*
  * Convert passed number to decimal string.
  * Returns the length of string.  On buffer overflow, returns 0.
@@ -307,7 +308,13 @@ int num_to_str(char *buf, int size, unsigned long long num)
        char tmp[sizeof(num) * 3];
        int idx, len;
 
-       len = put_dec(tmp, num) - tmp;
+       /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */
+       if (num <= 9) {
+               tmp[0] = '0' + num;
+               len = 1;
+       } else {
+               len = put_dec(tmp, num) - tmp;
+       }
 
        if (len > size)
                return 0;