Implement a better num2str()
authorJens Axboe <jaxboe@fusionio.com>
Thu, 16 Sep 2010 07:35:34 +0000 (09:35 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Thu, 16 Sep 2010 07:35:34 +0000 (09:35 +0200)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Makefile
Makefile.FreeBSD
Makefile.NetBSD
Makefile.aix
Makefile.mac
Makefile.solaris
fio.h
lib/num2str.c [new file with mode: 0644]

index 13baee837bf4d0ff06b07038f4c88fded5f5ab2a..04cb60fa7ab80ca2aa2381226a586c63972dff43 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,7 @@ OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
 
 OBJS += lib/rand.o
 OBJS += lib/flist_sort.o
+OBJS += lib/num2str.o
 
 OBJS += crc/crc7.o
 OBJS += crc/crc16.o
index 5882961a867949155641a3ebf642641fc9dbb061..e4adfca5c611c67cca1e4bfd8985a593b6554c0f 100644 (file)
@@ -10,6 +10,7 @@ OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
 
 OBJS += lib/rand.o
 OBJS += lib/flist_sort.o
+OBJS += lib/num2str.o
 
 OBJS += crc/crc7.o
 OBJS += crc/crc16.o
index c223ab2e7dcf5b2295e14542fab3d48fd9aaf8d8..9378b195392cd75396a7019450f0a0a1a49c5ac6 100644 (file)
@@ -10,6 +10,7 @@ OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
 
 OBJS += lib/rand.o
 OBJS += lib/flist_sort.o
+OBJS += lib/num2str.o
 
 OBJS += crc/crc7.o
 OBJS += crc/crc16.o
index 83b5cf4d269096440d5c1af16b66fd020776afbf..32d22a33d78917fbefe8fdc0b19ab1e2a7929baa 100644 (file)
@@ -11,6 +11,7 @@ OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
 
 OBJS += lib/rand.o
 OBJS += lib/getopt_long.o
+OBJS += lib/num2str.o
 
 OBJS += crc/crc7.o
 OBJS += crc/crc16.o
index 77e5f035082246c65c2c82ada3ff6840c70f58c0..952364ae2d9fc41f8327fe8a56b7f798d13694f7 100644 (file)
@@ -10,6 +10,7 @@ OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
 
 OBJS += lib/rand.o
 OBJS += lib/flist_sort.o
+OBJS += lib/num2str.o
 
 OBJS += crc/crc7.o
 OBJS += crc/crc16.o
index 06020c261f396261d67db077fe36268f6ac87cfb..e7ff53cb057be1ddb6a082c29cd2f2e62985cb9a 100644 (file)
@@ -9,6 +9,7 @@ OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \
 
 OBJS += lib/rand.o
 OBJS += lib/flist_sort.o
+OBJS += lib/num2str.o
 
 OBJS += crc/crc7.o
 OBJS += crc/crc16.o
diff --git a/fio.h b/fio.h
index e8c025d6880e2d3613abf43578acf3efbbd8dab5..28104cd83b376f13fc10388df8b1cd73b20e68cd 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -568,6 +568,8 @@ extern void options_mem_dupe(struct thread_data *);
 extern void options_mem_free(struct thread_data *);
 extern void td_fill_rand_seeds(struct thread_data *);
 extern void add_job_opts(const char **);
+extern char *num2str(unsigned long, int, int, int);
+
 #define FIO_GETOPT_JOB         0x89988998
 #define FIO_NR_OPTIONS         (FIO_MAX_OPTS + 128)
 
@@ -653,49 +655,6 @@ static inline int fio_fill_issue_time(struct thread_data *td)
        return 0;
 }
 
-/*
- * Cheesy number->string conversion, complete with carry rounding error.
- */
-static inline char *num2str(unsigned long num, int maxlen, int base, int pow2)
-{
-       char postfix[] = { ' ', 'K', 'M', 'G', 'P', 'E' };
-       unsigned int thousand;
-       char *buf;
-       int i;
-
-       if (pow2)
-               thousand = 1024;
-       else
-               thousand = 1000;
-
-       buf = malloc(128);
-
-       for (i = 0; base > 1; i++)
-               base /= thousand;
-
-       do {
-               int len, carry = 0;
-
-               len = sprintf(buf, "%'lu", num);
-               if (len <= maxlen) {
-                       if (i >= 1) {
-                               buf[len] = postfix[i];
-                               buf[len + 1] = '\0';
-                       }
-                       return buf;
-               }
-
-               if ((num % thousand) >= (thousand / 2))
-                       carry = 1;
-
-               num /= thousand;
-               num += carry;
-               i++;
-       } while (i <= 5);
-
-       return buf;
-}
-
 static inline int __should_check_rate(struct thread_data *td,
                                      enum fio_ddir ddir)
 {
diff --git a/lib/num2str.c b/lib/num2str.c
new file mode 100644 (file)
index 0000000..e114cdf
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * Cheesy number->string conversion, complete with carry rounding error.
+ */
+char *num2str(unsigned long num, int maxlen, int base, int pow2)
+{
+       char postfix[] = { ' ', 'K', 'M', 'G', 'P', 'E' };
+       unsigned int thousand[] = { 1000, 1024 };
+       unsigned int modulo, decimals;
+       int post_index;
+       char tmp[32], fmt[8];
+       char *buf;
+
+       buf = malloc(128);
+
+       for (post_index = 0; base > 1; post_index++)
+               base /= thousand[!!pow2];
+
+       modulo = -1U;
+       while (post_index < sizeof(postfix)) {
+               sprintf(tmp, "%lu", num);
+               if (strlen(tmp) <= maxlen)
+                       break;
+
+               modulo = num % thousand[!!pow2];
+               num /= thousand[!!pow2];
+               post_index++;
+       }
+
+       if (modulo == -1U) {
+done:
+               sprintf(buf, "%lu%c", num, postfix[post_index]);
+               return buf;
+       }
+
+       sprintf(tmp, "%lu", num);
+       decimals = maxlen - strlen(tmp);
+       if (decimals <= 1)
+               goto done;
+
+       sprintf(fmt, "%%.%uu", decimals - 1);
+       sprintf(tmp, fmt, modulo);
+       sprintf(buf, "%lu.%s%c", num, tmp, postfix[post_index]);
+       return buf;
+}