The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libzutil/zutil_nicenum.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   24  */
   25 
   26 #include <ctype.h>
   27 #include <math.h>
   28 #include <stdio.h>
   29 #include <libzutil.h>
   30 #include <string.h>
   31 
   32 /*
   33  * Return B_TRUE if "str" is a number string, B_FALSE otherwise.
   34  * Works for integer and floating point numbers.
   35  */
   36 boolean_t
   37 zfs_isnumber(const char *str)
   38 {
   39         if (!*str)
   40                 return (B_FALSE);
   41 
   42         for (; *str; str++)
   43                 if (!(isdigit(*str) || (*str == '.')))
   44                         return (B_FALSE);
   45 
   46         /*
   47          * Numbers should not end with a period ("." ".." or "5." are
   48          * not valid)
   49          */
   50         if (str[strlen(str) - 1] == '.') {
   51                 return (B_FALSE);
   52         }
   53 
   54         return (B_TRUE);
   55 }
   56 
   57 /*
   58  * Convert a number to an appropriately human-readable output.
   59  */
   60 void
   61 zfs_nicenum_format(uint64_t num, char *buf, size_t buflen,
   62     enum zfs_nicenum_format format)
   63 {
   64         uint64_t n = num;
   65         int index = 0;
   66         const char *u;
   67         const char *units[3][7] = {
   68             [ZFS_NICENUM_1024] = {"", "K", "M", "G", "T", "P", "E"},
   69             [ZFS_NICENUM_BYTES] = {"B", "K", "M", "G", "T", "P", "E"},
   70             [ZFS_NICENUM_TIME] = {"ns", "us", "ms", "s", "?", "?", "?"}
   71         };
   72 
   73         const int units_len[] = {[ZFS_NICENUM_1024] = 6,
   74             [ZFS_NICENUM_BYTES] = 6,
   75             [ZFS_NICENUM_TIME] = 4};
   76 
   77         const int k_unit[] = {  [ZFS_NICENUM_1024] = 1024,
   78             [ZFS_NICENUM_BYTES] = 1024,
   79             [ZFS_NICENUM_TIME] = 1000};
   80 
   81         double val;
   82 
   83         if (format == ZFS_NICENUM_RAW) {
   84                 snprintf(buf, buflen, "%llu", (u_longlong_t)num);
   85                 return;
   86         } else if (format == ZFS_NICENUM_RAWTIME && num > 0) {
   87                 snprintf(buf, buflen, "%llu", (u_longlong_t)num);
   88                 return;
   89         } else if (format == ZFS_NICENUM_RAWTIME && num == 0) {
   90                 snprintf(buf, buflen, "%s", "-");
   91                 return;
   92         }
   93 
   94         while (n >= k_unit[format] && index < units_len[format]) {
   95                 n /= k_unit[format];
   96                 index++;
   97         }
   98 
   99         u = units[format][index];
  100 
  101         /* Don't print zero latencies since they're invalid */
  102         if ((format == ZFS_NICENUM_TIME) && (num == 0)) {
  103                 (void) snprintf(buf, buflen, "-");
  104         } else if ((index == 0) || ((num %
  105             (uint64_t)powl(k_unit[format], index)) == 0)) {
  106                 /*
  107                  * If this is an even multiple of the base, always display
  108                  * without any decimal precision.
  109                  */
  110                 (void) snprintf(buf, buflen, "%llu%s", (u_longlong_t)n, u);
  111 
  112         } else {
  113                 /*
  114                  * We want to choose a precision that reflects the best choice
  115                  * for fitting in 5 characters.  This can get rather tricky when
  116                  * we have numbers that are very close to an order of magnitude.
  117                  * For example, when displaying 10239 (which is really 9.999K),
  118                  * we want only a single place of precision for 10.0K.  We could
  119                  * develop some complex heuristics for this, but it's much
  120                  * easier just to try each combination in turn.
  121                  */
  122                 int i;
  123                 for (i = 2; i >= 0; i--) {
  124                         val = (double)num /
  125                             (uint64_t)powl(k_unit[format], index);
  126 
  127                         /*
  128                          * Don't print floating point values for time.  Note,
  129                          * we use floor() instead of round() here, since
  130                          * round can result in undesirable results.  For
  131                          * example, if "num" is in the range of
  132                          * 999500-999999, it will print out "1000us".  This
  133                          * doesn't happen if we use floor().
  134                          */
  135                         if (format == ZFS_NICENUM_TIME) {
  136                                 if (snprintf(buf, buflen, "%d%s",
  137                                     (unsigned int) floor(val), u) <= 5)
  138                                         break;
  139 
  140                         } else {
  141                                 if (snprintf(buf, buflen, "%.*f%s", i,
  142                                     val, u) <= 5)
  143                                         break;
  144                         }
  145                 }
  146         }
  147 }
  148 
  149 /*
  150  * Convert a number to an appropriately human-readable output.
  151  */
  152 void
  153 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
  154 {
  155         zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_1024);
  156 }
  157 
  158 /*
  159  * Convert a time to an appropriately human-readable output.
  160  * @num:        Time in nanoseconds
  161  */
  162 void
  163 zfs_nicetime(uint64_t num, char *buf, size_t buflen)
  164 {
  165         zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_TIME);
  166 }
  167 
  168 /*
  169  * Print out a raw number with correct column spacing
  170  */
  171 void
  172 zfs_niceraw(uint64_t num, char *buf, size_t buflen)
  173 {
  174         zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_RAW);
  175 }
  176 
  177 /*
  178  * Convert a number of bytes to an appropriately human-readable output.
  179  */
  180 void
  181 zfs_nicebytes(uint64_t num, char *buf, size_t buflen)
  182 {
  183         zfs_nicenum_format(num, buf, buflen, ZFS_NICENUM_BYTES);
  184 }

Cache object: d19c9b3501c3b4963efa9c41ef47aa3f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.