aboutsummaryrefslogtreecommitdiffstats
path: root/util/human/units.lua
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2020-11-05 22:31:25 +0100
committerKim Alvefur <zash@zash.se>2020-11-05 22:31:25 +0100
commit238b2bfc1cdb65ae7d051c2f29c1427149317795 (patch)
tree58547de6e7795740633c1b93e67c217eb621fe8f /util/human/units.lua
parentce3e3808f5359f481f3ea063220ba71428b26ad5 (diff)
parent48521ba1538f797f5bef64f5fe5f3a9fb6e68f7f (diff)
downloadprosody-238b2bfc1cdb65ae7d051c2f29c1427149317795.tar.gz
prosody-238b2bfc1cdb65ae7d051c2f29c1427149317795.zip
Merge 0.11->trunk
Diffstat (limited to 'util/human/units.lua')
-rw-r--r--util/human/units.lua80
1 files changed, 80 insertions, 0 deletions
diff --git a/util/human/units.lua b/util/human/units.lua
new file mode 100644
index 00000000..af233e98
--- /dev/null
+++ b/util/human/units.lua
@@ -0,0 +1,80 @@
+local math_abs = math.abs;
+local math_ceil = math.ceil;
+local math_floor = math.floor;
+local math_log = math.log;
+local math_max = math.max;
+local math_min = math.min;
+local unpack = table.unpack or unpack; --luacheck: ignore 113
+
+if math_log(10, 10) ~= 1 then
+ -- Lua 5.1 COMPAT
+ local log10 = math.log10;
+ function math_log(n, base)
+ return log10(n) / log10(base);
+ end
+end
+
+local large = {
+ "k", 1000,
+ "M", 1000000,
+ "G", 1000000000,
+ "T", 1000000000000,
+ "P", 1000000000000000,
+ "E", 1000000000000000000,
+ "Z", 1000000000000000000000,
+ "Y", 1000000000000000000000000,
+}
+local small = {
+ "m", 0.001,
+ "μ", 0.000001,
+ "n", 0.000000001,
+ "p", 0.000000000001,
+ "f", 0.000000000000001,
+ "a", 0.000000000000000001,
+ "z", 0.000000000000000000001,
+ "y", 0.000000000000000000000001,
+}
+
+local binary = {
+ "Ki", 2^10,
+ "Mi", 2^20,
+ "Gi", 2^30,
+ "Ti", 2^40,
+ "Pi", 2^50,
+ "Ei", 2^60,
+ "Zi", 2^70,
+ "Yi", 2^80,
+}
+
+local function adjusted_unit(n, b)
+ local round = math_floor;
+ local prefixes = large;
+ local logbase = 1000;
+ if b == 'b' then
+ prefixes = binary;
+ logbase = 1024;
+ elseif n < 1 then
+ prefixes = small;
+ round = math_ceil;
+ end
+ local m = math_max(0, math_min(8, round(math_abs(math_log(math_abs(n), logbase)))));
+ local prefix, multiplier = unpack(prefixes, m * 2-1, m*2);
+ return multiplier or 1, prefix;
+end
+
+-- n: number, the number to format
+-- unit: string, the base unit
+-- b: optional enum 'b', thousands base
+local function format(n, unit, b) --> string
+ local fmt = "%.3g %s%s";
+ if n == 0 then
+ return fmt:format(n, "", unit);
+ end
+ local multiplier, prefix = adjusted_unit(n, b);
+ return fmt:format(n / multiplier, prefix or "", unit);
+end
+
+return {
+ adjust = adjusted_unit;
+ format = format;
+};