-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilesize.lua
executable file
·141 lines (120 loc) · 3.84 KB
/
filesize.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
-- lua-filesize, generate a human readable string describing the file size
-- See the LICENSE file for terms of use:
-- https://github.com/starius/lua-filesize/blob/master/LICENSE
-- AUTHORS: Boris Nagaev, Jason Xu
local si = {
base10 = {
bits = {"b", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb"},
bytes = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
},
base2 = {
bits = {"b", "Kib", "Mib", "Gib", "Tib", "Pib", "Eib", "Zib", "Yib"},
bytes = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
} -- see https://docs.ukcloud.com/articles/other/other-ref-gib.html
}
local function isNan(num)
-- http://lua-users.org/wiki/InfAndNanComparisons
-- NaN is the only value that doesn't equal itself
return num ~= num
end
local function roundNumber(num, digits)
local fmt = "%." .. digits .. "f"
return tonumber(fmt:format(num))
end
local function filesize(size, options)
-- copy options to o
local o = {}
for key, value in pairs(options or {}) do
o[key] = value
end
local function setDefault(name, default)
if o[name] == nil then
o[name] = default
end
end
setDefault("bits", false)
setDefault("unix", false)
setDefault("base", 2)
setDefault("round", o.unix and 1 or 2)
setDefault("spacer", o.unix and "" or " ")
setDefault("suffixes", {})
setDefault("output", "string")
setDefault("exponent", -1)
assert(not isNan(size), "Invalid arguments")
local ceil = (o.base > 2) and 1000 or 1024
local negative = (size < 0)
if negative then
-- Flipping a negative number to determine the size
size = -size
end
local result
-- Zero is now a special case because bytes divide by 1
if size == 0 then
result = {
0,
o.unix and "" or (o.bits and "b" or "B")
}
else
-- Determining the exponent
if o.exponent == -1 or isNan(o.exponent) then
o.exponent = math.floor(math.log(size) / math.log(ceil))
end
-- Exceeding supported length, time to reduce & multiply
if o.exponent > 8 then
o.exponent = 8
end
local val
if o.base == 2 then
val = size / math.pow(2, o.exponent * 10)
else
val = size / math.pow(1000, o.exponent)
end
if o.bits then
val = val * 8
if val > ceil then
val = val / ceil
o.exponent = o.exponent + 1
end
end
result = {
roundNumber(val, o.exponent > 0 and o.round or 0),
(o.base == 10 and o.exponent == 1) and (o.bits and "kb" or "kB") or
(si[o.base == 2 and "base2" or "base10"][o.bits and "bits" or "bytes"][o.exponent + 1])
}
if o.unix then
result[2] = result[2]:sub(1, 1)
if result[2] == "b" or result[2] == "B" then
result = {
math.floor(result[1]),
""
}
end
end
end
assert(result)
-- Decorating a 'diff'
if negative then
result[1] = -result[1]
end
-- Applying custom suffix
result[2] = o.suffixes[result[2]] or result[2]
-- Applying custom suffix
result[2] = o.suffixes[result[2]] or result[2]
-- Returning Array, Object, or String (default)
if o.output == "array" then
return result
elseif o.output == "exponent" then
return o.exponent
elseif o.output == "object" then
return {
value = result[1],
suffix = result[2]
}
elseif o.output == "string" then
local value = tostring(result[1])
value = value:gsub("%.0$", "")
local suffix = result[2]
return value .. o.spacer .. suffix
end
end
return filesize