-
Notifications
You must be signed in to change notification settings - Fork 1
/
ByteCount.cs
125 lines (110 loc) · 2.94 KB
/
ByteCount.cs
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
using System;
namespace FLogS
{
struct ByteCount
{
public ByteCount() { bytes = 0.0; prefix = -1; }
private ByteCount(double b, short p) { bytes = b; prefix = p; }
public double bytes;
public short prefix;
private readonly static string[] prefixes = ["k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"]; // Always futureproof...
public void Adjust(int factor, bool absolute = true)
{
if (!absolute)
factor = (short)(prefix - factor);
while (prefix != factor)
Magnitude(Math.Sign(prefix - factor));
}
public void Magnitude(int factor)
{
bytes *= Math.Pow(1024, factor);
prefix -= (short)factor;
}
public void Simplify()
{
while (bytes >= 921.6 && prefix < prefixes.Length)
Magnitude(-1);
while (bytes < 0.9 && prefix > -1)
Magnitude(1);
}
public static ByteCount operator -(ByteCount a, ByteCount b)
{
ByteCount c, d;
if (Math.Abs(a.prefix - b.prefix) > 3) // Special accommodations must be made if the disparity in magnitude would normally result in an int overflow.
{
c = new(a.bytes, a.prefix);
d = new(b.bytes, b.prefix);
c.Adjust(Math.Abs(a.prefix - b.prefix) / 2);
d.Adjust(c.prefix);
c.bytes -= d.bytes;
c.Simplify();
return c;
}
c = new(a.bytes, a.prefix);
c.Adjust(b.prefix);
c.bytes -= b.bytes;
c.Simplify();
return c;
}
public static ByteCount operator +(ByteCount a, ByteCount b)
{
ByteCount c, d;
if (Math.Abs(a.prefix - b.prefix) > 3)
{
c = new(a.bytes, a.prefix);
d = new(b.bytes, b.prefix);
c.Adjust(Math.Abs(a.prefix - b.prefix) / 2);
d.Adjust(c.prefix);
c.bytes += d.bytes;
c.Simplify();
return c;
}
c = new(a.bytes, a.prefix);
c.Adjust(b.prefix);
c.bytes += b.bytes;
c.Simplify();
return c;
}
public static ByteCount operator +(ByteCount a, int b)
{
ByteCount c = new(a.bytes, a.prefix);
ByteCount d = new(b, -1);
c.Adjust((c.prefix + 1) / 2);
d.Adjust(c.prefix);
c.bytes += d.bytes;
c.Simplify();
return c;
}
public static ByteCount operator +(ByteCount a, uint b)
{
ByteCount c = new(a.bytes, a.prefix);
ByteCount d = new(b, -1);
c.Adjust((c.prefix + 1) / 2);
d.Adjust(c.prefix);
c.bytes += d.bytes;
c.Simplify();
return c;
}
public static ByteCount operator +(ByteCount a, long b)
{
ByteCount c = new(a.bytes, a.prefix);
ByteCount d = new(b, -1);
c.Adjust((c.prefix + 1) / 2);
d.Adjust(c.prefix);
c.bytes += d.bytes;
c.Simplify();
return c;
}
/// <summary>
/// Return the size of this byte counter, formatted with the most appropriate metric prefix. This function does not preserve manual adjustments to the counter's magnitude.
/// </summary>
/// <returns>The byte counter size, in the format "0.0 xB", where 'x' is a metric prefix.</returns>
public override string ToString()
{
Simplify();
if (prefix == -1)
return $"{bytes:N0} B";
return $"{bytes:N1} {prefixes[prefix]}B";
}
}
}