~kris/dots

srice

ref: e9b48d06a8541f3eda5c4db90382ab3c77183afb srice/.config/conky/lean-conky/lib/external/filesize.lua -rw-r--r-- 3.9 KiB
e9b48d06 — Kris Yotam xprofile: systemd-aware pipewire start + blueman-applet; sb-internet: tolerate missing /proc/net/wireless 2 months ago
                                                                                
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
142
-- 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