Add print_human_readable_size() function.
[pintos-anon] / src / lib / stdio.c
index d223d1065a61ca2f6df986bc219aad0b48f0afdd..3549d4e9fd70f854880cb9a87cc26bfcee8f91d4 100644 (file)
@@ -1,5 +1,7 @@
-#include <ctype.h>
 #include <stdio.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <round.h>
 #include <stdint.h>
 #include <string.h>
 
@@ -198,6 +200,9 @@ __vprintf (const char *format, va_list args,
               case INT:
                 value = va_arg (args, int);
                 break;
+              case INTMAX:
+                value = va_arg (args, intmax_t);
+                break;
               case LONG:
                 value = va_arg (args, long);
                 break;
@@ -239,6 +244,9 @@ __vprintf (const char *format, va_list args,
               case INT:
                 value = va_arg (args, unsigned);
                 break;
+              case INTMAX:
+                value = va_arg (args, uintmax_t);
+                break;
               case LONG:
                 value = va_arg (args, unsigned long);
                 break;
@@ -461,31 +469,27 @@ format_integer (uintmax_t value, bool negative, const struct integer_base *b,
   const char *signifier;        /* b->signifier or "". */
   int precision;                /* Rendered precision. */
   int pad_cnt;                  /* # of pad characters to fill field width. */
-  int group_cnt;                /* # of digits grouped so far. */
+  int digit_cnt;                /* # of digits output so far. */
 
   /* Accumulate digits into buffer.
      This algorithm produces digits in reverse order, so later we
      will output the buffer's content in reverse.  This is also
      the reason that later we append zeros and the sign. */
   cp = buf;
-  group_cnt = 0;
+  digit_cnt = 0;
   while (value > 0) 
     {
-      if ((c->flags & GROUP) && group_cnt++ == b->group) 
-        {
-          *cp++ = ',';
-          group_cnt = 0; 
-        }
+      if ((c->flags & GROUP) && digit_cnt > 0 && digit_cnt % b->group == 0)
+        *cp++ = ',';
       *cp++ = b->digits[value % b->base];
       value /= b->base;
+      digit_cnt++;
     }
 
   /* Append enough zeros to match precision.
      If requested precision is 0, then a value of zero is
      rendered as a null string, otherwise as "0". */
   precision = c->precision < 0 ? 1 : c->precision;
-  if (precision < 0)
-    precision = 1;
   while (cp - buf < precision && cp - buf < (int) sizeof buf - 8)
     *cp++ = '0';
 
@@ -553,39 +557,72 @@ __printf (const char *format,
   va_end (args);
 }
 \f
-/* Dumps the SIZE bytes in BUFFER to the console as hex bytes
-   arranged 16 per line.  If ASCII is true then the corresponding
-   ASCII characters are also rendered alongside. */   
+/* Dumps the SIZE bytes in BUF to the console as hex bytes
+   arranged 16 per line.  Numeric offsets are also included,
+   starting at OFS for the first byte in BUF.  If ASCII is true
+   then the corresponding ASCII characters are also rendered
+   alongside. */   
 void
-hex_dump (const void *buffer, size_t size, bool ascii)
+hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii)
 {
-  const size_t n_per_line = 16; /* Maximum bytes per line. */
-  size_t n;                     /* Number of bytes in this line. */
-  const uint8_t *p;             /* Start of current line in buffer. */
+  const uint8_t *buf = buf_;
+  const size_t per_line = 16; /* Maximum bytes per line. */
 
-  for (p = buffer; p < (uint8_t *) buffer + size; p += n) 
+  while (size > 0)
     {
+      size_t start, end, n;
       size_t i;
-
+      
       /* Number of bytes on this line. */
-      n = (uint8_t *) (buffer + size) - p;
-      if (n > n_per_line)
-        n = n_per_line;
+      start = ofs % per_line;
+      end = per_line;
+      if (end - start > size)
+        end = start + size;
+      n = end - start;
 
       /* Print line. */
-      for (i = 0; i < n; i++) 
-        printf ("%c%02x", i == n_per_line / 2 ? '-' : ' ', (unsigned) p[i]);
+      printf ("%08jx  ", (uintmax_t) ROUND_DOWN (ofs, per_line));
+      for (i = 0; i < start; i++)
+        printf ("   ");
+      for (; i < end; i++) 
+        printf ("%02hhx%c",
+                buf[i - start], i == per_line / 2 - 1? '-' : ' ');
       if (ascii) 
         {
-          for (; i < n_per_line; i++)
+          for (; i < per_line; i++)
             printf ("   ");
-          printf (" |");
-          for (i = 0; i < n; i++)
-            printf ("%c", isprint (p[i]) ? p[i] : '.');
-          for (; i < n_per_line; i++)
+          printf ("|");
+          for (i = 0; i < start; i++)
+            printf (" ");
+          for (; i < end; i++)
+            printf ("%c",
+                    isprint (buf[i - start]) ? buf[i - start] : '.');
+          for (; i < per_line; i++)
             printf (" ");
           printf ("|");
         }
       printf ("\n");
+
+      ofs += n;
+      buf += n;
+      size -= n;
+    }
+}
+
+/* Prints SIZE, which represents a number of bytes, in a
+   human-readable format, e.g. "256 kB". */
+void
+print_human_readable_size (uint64_t size) 
+{
+  if (size == 1)
+    printf ("1 byte");
+  else 
+    {
+      static const char *factors[] = {"bytes", "kB", "MB", "GB", "TB", NULL};
+      const char **fp;
+
+      for (fp = factors; size >= 1024 && fp[1] != NULL; fp++)
+        size /= 1024;
+      printf ("%"PRIu64" %s", *fp);
     }
 }