mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-10 01:29:05 -04:00
embiggen notcurses_metric(3), add unit test #1107
This commit is contained in:
parent
9135663529
commit
dd8423dff3
@ -27,6 +27,8 @@ notcurses_metric - fixed-width numeric output with metric suffixes
|
||||
|
||||
**static inline const char* qprefix(uintmax_t ***val***, uintmax_t ***decimal***, char* ***buf***, int ***omitdec***);**
|
||||
|
||||
**static inline const char* iprefix(uintmax_t ***val***, uintmax_t ***decimal***, char* ***buf***, int ***omitdec***);**
|
||||
|
||||
**static inline const char* bprefix(uintmax_t ***val***, uintmax_t ***decimal***, char* ***buf***, int ***omitdec***);**
|
||||
|
||||
# DESCRIPTION
|
||||
@ -39,8 +41,8 @@ amounts of growth, but is designed for 1000 (**PREFIX**) or 1024
|
||||
and gibibits. **ncmetric** supports the large suffixes KMGTPEZY (Kilo, Mega,
|
||||
Giga, Tera, Peta, Exa, Zetta, and Yotta) and the small suffixes mµnpfazy
|
||||
(Milli, Micro, Nano, Pico, Femto, Atto, Zepto, and Yocto). This covers the
|
||||
range 10^-24 through 10^24. As **uintmax_t** is typically only 64 bits, this
|
||||
covers the entirety of its range.
|
||||
range 1e24 (one septillion) through 1e-24, sufficing for all possible values of
|
||||
a 64-bit **uintmax_t**.
|
||||
|
||||
**val** is the value being output, having been scaled by **decimal**.
|
||||
**decimal** will typically be 1; to represent values less than 1, **decimal**
|
||||
@ -51,31 +53,91 @@ must be at least:
|
||||
* **IPREFIXSTRLEN** + 1 bytes for a 1024-based value
|
||||
* **BPREFIXSTRLEN** + 1 bytes for a 1024-based value with an 'i' suffix
|
||||
|
||||
Three helper functions are provided to simplify these common cases:
|
||||
|
||||
```
|
||||
// Mega, kilo, gigafoo. Use PREFIXSTRLEN + 1 and PREFIXCOLUMNS.
|
||||
static inline const char*
|
||||
qprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
|
||||
return ncmetric(val, decimal, buf, omitdec, 1000, '\0');
|
||||
}
|
||||
|
||||
// Mibi, kebi, gibibytes sans 'i' suffix. Use IPREFIXSTRLEN + 1.
|
||||
static inline const char*
|
||||
iprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
|
||||
return ncmetric(val, decimal, buf, omitdec, 1024, '\0');
|
||||
}
|
||||
|
||||
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1 and BPREFIXCOLUMNS.
|
||||
static inline const char*
|
||||
bprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
|
||||
return ncmetric(val, decimal, buf, omitdec, 1024, 'i');
|
||||
}
|
||||
```
|
||||
|
||||
If **omitdec** is not zero, the decimal point and mantissa will be
|
||||
omitted if all digits to be displayed would be zero. The decimal point takes
|
||||
the current locale into account (see **setlocale(3)** and **localeconv(3)**).
|
||||
**mult** is the relative multiple for each suffix. **uprefix**, if not zero,
|
||||
will be used as a suffix following any metric suffix.
|
||||
|
||||
In general, the maximum-width output will take the form:
|
||||
The maximum number of columns is not directly related to the maximum number of
|
||||
bytes, since Unicode doesn't necessarily map to single-byte characters
|
||||
(including the 'µ' micro suffix). The corresponding defines for maximum column
|
||||
length are:
|
||||
|
||||
CCC.mmMu
|
||||
* **PREFIXCOLUMNS** (7)
|
||||
* **IPREFIXCOLUMNS** (8)
|
||||
* **BPREFIXCOLUMNS** (9)
|
||||
|
||||
Where C are digits of the characteristic (up to ceil(log10(**mult**)) digits),
|
||||
the decimal point follows, m are digits of the mantissa (up to 2), M is the
|
||||
metric suffix, and u is the **uprefix**. The minimum-width output will take
|
||||
the form:
|
||||
In general, the maximum-width output will take the form **CCC.mmMu**, where C
|
||||
are digits of the characteristic (up to ceil(log10(**mult**)) digits), the
|
||||
decimal point follows, m are digits of the mantissa (up to 2), M is the metric
|
||||
suffix, and u is the **uprefix**. The minimum-width output will take the form
|
||||
**C**. This minimal form can occur if **omitdec** is non-zero and a
|
||||
single-column value such as 5 is passed for **val**.
|
||||
|
||||
C
|
||||
Three more defines are provided to simplify formatted fixed-width output using
|
||||
the results of **ncmetric**. Each of these macros accepts a character buffer
|
||||
holding the result of the call, and expand to *two* arguments:
|
||||
|
||||
This can occur if **omitdec** is non-zero and a value such as 5 is passed
|
||||
for **val**.
|
||||
* **PREFIXFMT(x)**
|
||||
* **IPREFIXFMT(x)**
|
||||
* **BPREFIXFMT(x)**
|
||||
|
||||
These can be used in e.g. the following ungainly fashion:
|
||||
|
||||
**ncplane_printf(n, "%*s", PREFIXFMT(buf));**
|
||||
|
||||
to ensure that the output is always **PREFIXCOLUMNS** wide.
|
||||
|
||||
# RETURN VALUES
|
||||
|
||||
**NULL** if input parameters were invalid. Otherwise, a pointer to **buf**,
|
||||
filled in with the formatted output.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
**ncmetric(0, 1, buf, 0, 1000, '\0')**: "0.00".
|
||||
|
||||
**ncmetric(0, 1, buf, 1, 1000, '\0')**: "0".
|
||||
|
||||
**ncmetric(1023, 1, buf, 1, 1000, '\0')**: "1.02K".
|
||||
|
||||
**ncmetric(1023, 1, buf, 1, 1024, 'i')**: "1023".
|
||||
|
||||
**ncmetric(1024, 1, buf, 1, 1024, 'i')**: "1Ki".
|
||||
|
||||
**ncmetric(4096, 1, buf, 0, 1024, 'i')**: "4.00Ki".
|
||||
|
||||
**ncmetric(0x7fffffffffffffff, 1, buf, 0, 1000, '\0')**: "9.22E".
|
||||
|
||||
**ncmetric(0xffffffffffffffff, 1, buf, 0, 1000, '\0')**: "18.45E".
|
||||
|
||||
# BUGS
|
||||
|
||||
This function is difficult to understand.
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
**localeconv(3)**,
|
||||
|
@ -2608,6 +2608,30 @@ API struct ncplane* nctablet_plane(struct nctablet* t);
|
||||
API struct ncplane* nctablet_ncplane(struct nctablet* t)
|
||||
__attribute__ ((deprecated));
|
||||
|
||||
// Takes an arbitrarily large number, and prints it into a fixed-size buffer by
|
||||
// adding the necessary SI suffix. Usually, pass a |[IB]PREFIXSTRLEN+1|-sized
|
||||
// buffer to generate up to |[IB]PREFIXCOLUMNS| columns' worth of EGCs. The
|
||||
// characteristic can occupy up through |mult-1| characters (3 for 1000, 4 for
|
||||
// 1024). The mantissa can occupy either zero or two characters.
|
||||
//
|
||||
// Floating-point is never used, because an IEEE758 double can only losslessly
|
||||
// represent integers through 2^53-1.
|
||||
//
|
||||
// 2^64-1 is 18446744073709551615, 18.45E(xa). KMGTPEZY thus suffice to handle
|
||||
// an 89-bit uintmax_t. Beyond Z(etta) and Y(otta) lie lands unspecified by SI.
|
||||
// 2^-63 is 0.000000000000000000108, 1.08a(tto).
|
||||
// val: value to print
|
||||
// decimal: scaling. '1' if none has taken place.
|
||||
// buf: buffer in which string will be generated
|
||||
// omitdec: inhibit printing of all-0 decimal portions
|
||||
// mult: base of suffix system (almost always 1000 or 1024)
|
||||
// uprefix: character to print following suffix ('i' for kibibytes basically).
|
||||
// only printed if suffix is actually printed (input >= mult).
|
||||
//
|
||||
// You are encouraged to consult notcurses_metric(3).
|
||||
API const char* ncmetric(uintmax_t val, uintmax_t decimal, char* buf,
|
||||
int omitdec, uintmax_t mult, int uprefix);
|
||||
|
||||
// The number of columns is one fewer, as the STRLEN expressions must leave
|
||||
// an extra byte open in case 'µ' (U+00B5, 0xC2 0xB5) shows up. PREFIXCOLUMNS
|
||||
// is the maximum number of columns used by a mult == 1000 (standard)
|
||||
@ -2629,29 +2653,7 @@ API struct ncplane* nctablet_ncplane(struct nctablet* t)
|
||||
#define IPREFIXFMT(x) NCMETRIXFWIDTH((x), IPREFIXCOLUMNS), (x)
|
||||
#define BPREFIXFMT(x) NCMETRICFWIDTH((x), BPREFIXCOLUMNS), (x)
|
||||
|
||||
// Takes an arbitrarily large number, and prints it into a fixed-size buffer by
|
||||
// adding the necessary SI suffix. Usually, pass a |[IB]PREFIXSTRLEN+1|-sized
|
||||
// buffer to generate up to |[IB]PREFIXCOLUMNS| columns' worth of EGCs. The
|
||||
// characteristic can occupy up through |mult-1| characters (3 for 1000, 4 for
|
||||
// 1024). The mantissa can occupy either zero or two characters.
|
||||
//
|
||||
// Floating-point is never used, because an IEEE758 double can only losslessly
|
||||
// represent integers through 2^53-1.
|
||||
//
|
||||
// 2^64-1 is 18446744073709551615, 18.45E(xa). KMGTPEZY thus suffice to handle
|
||||
// an 89-bit uintmax_t. Beyond Z(etta) and Y(otta) lie lands unspecified by SI.
|
||||
// 2^-63 is 0.000000000000000000108, 1.08a(tto).
|
||||
// val: value to print
|
||||
// decimal: scaling. '1' if none has taken place.
|
||||
// buf: buffer in which string will be generated
|
||||
// omitdec: inhibit printing of all-0 decimal portions
|
||||
// mult: base of suffix system (almost always 1000 or 1024)
|
||||
// uprefix: character to print following suffix ('i' for kibibytes basically).
|
||||
// only printed if suffix is actually printed (input >= mult).
|
||||
API const char* ncmetric(uintmax_t val, uintmax_t decimal, char* buf,
|
||||
int omitdec, uintmax_t mult, int uprefix);
|
||||
|
||||
// Mega, kilo, gigafoo. Use PREFIXSTRLEN + 1.
|
||||
// Mega, kilo, gigafoo. Use PREFIXSTRLEN + 1 and PREFIXCOLUMNS.
|
||||
static inline const char*
|
||||
qprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
|
||||
return ncmetric(val, decimal, buf, omitdec, 1000, '\0');
|
||||
@ -2663,7 +2665,7 @@ iprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
|
||||
return ncmetric(val, decimal, buf, omitdec, 1024, '\0');
|
||||
}
|
||||
|
||||
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1.
|
||||
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1 and BPREFIXCOLUMNS.
|
||||
static inline const char*
|
||||
bprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
|
||||
return ncmetric(val, decimal, buf, omitdec, 1024, 'i');
|
||||
|
@ -67,6 +67,8 @@ TEST_CASE("Metric") {
|
||||
CHECK(!strcmp("1.00Ki", buf));
|
||||
impericize_ncmetric(4096, 1, buf, 1, 1000, '\0');
|
||||
CHECK(!strcmp("4.10K", buf));
|
||||
impericize_ncmetric(4096, 1, buf, 0, 1024, 'i');
|
||||
CHECK(!strcmp("4.00Ki", buf));
|
||||
impericize_ncmetric(4096, 1, buf, 1, 1024, 'i');
|
||||
CHECK(!strcmp("4Ki", buf));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user