/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Gabriel Roldan (OpenGeo) 2010
*
*/
package org.geowebcache.diskquota.storage;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* Enumerates the various storage units according to the power of two based units (instead of
* the more common commercial prefixes, often used but not entirely correct)
*/
public enum StorageUnit {
/**
* Byte
*/
B(BigDecimal.ONE), //
/**
* Kibibyte (2<sup>10</sup> Bytes)
*/
KiB(B.bytes.multiply(BigDecimal.valueOf(1024))), //
/**
* Mebibyte (2<sup>20</sup> Bytes)
*/
MiB(KiB.bytes.multiply(BigDecimal.valueOf(1024))), //
/**
* Gibibyte (2<sup>30</sup> Bytes)
*/
GiB(MiB.bytes.multiply(BigDecimal.valueOf(1024))), //
/**
* Tebibyte (2<sup>40</sup> Bytes)
*/
TiB(GiB.bytes.multiply(BigDecimal.valueOf(1024))), //
/**
* Pebibyte (2<sup>50</sup> Bytes)
*/
PiB(TiB.bytes.multiply(BigDecimal.valueOf(1024))), //
/**
* Exibyte (2<sup>60</sup> Bytes)
*/
EiB(PiB.bytes.multiply(BigDecimal.valueOf(1024))), //
/**
* Zebibyte (2<sup>70</sup> Bytes)
*/
ZiB(EiB.bytes.multiply(BigDecimal.valueOf(1024))),
/**
* Yobibyte (2<sup>80</sup> Bytes)
*/
YiB(ZiB.bytes.multiply(BigDecimal.valueOf(1024)));
private final BigDecimal bytes;
private StorageUnit(final BigDecimal bytes) {
this.bytes = bytes;
}
public final BigInteger toBytes(double value) {
return toBytes(BigDecimal.valueOf(value));
}
public final BigInteger toBytes(BigDecimal value) {
BigDecimal toBytes = bytes.multiply(value);
return toBytes.toBigInteger();
}
public final BigDecimal fromBytes(BigInteger value) {
return new BigDecimal(value).divide(bytes);
}
public BigDecimal convertTo(double value, StorageUnit target) {
return convertTo(BigDecimal.valueOf(value), target);
}
public final BigDecimal convertTo(BigDecimal value, StorageUnit target) {
return target.fromBytes(toBytes(value));
}
/**
* Returns the most appropriate storage unit to represent the given amount
*
* @param value
* @param units
* @return
*/
public static StorageUnit bestFit(double value, StorageUnit units) {
return bestFit(BigDecimal.valueOf(value), units);
}
/**
* Returns the most appropriate storage unit to represent the given amount
*
* @param value
* @param units
* @return
*/
public static StorageUnit bestFit(BigDecimal value, StorageUnit units) {
BigDecimal bytes = new BigDecimal(units.toBytes(value));
// use compareTo because BigDecimal.equals does not consider 1.0 and 1.00 to be equal, so
// can't do, for example, bytes.min(TiB.bytes).equals(YiB.bytes)
if (bytes.compareTo(YiB.bytes) >= 0) {
return YiB;
}
if (bytes.compareTo(ZiB.bytes) >= 0) {
return ZiB;
}
if (bytes.compareTo(EiB.bytes) >= 0) {
return EiB;
}
if (bytes.compareTo(PiB.bytes) >= 0) {
return PiB;
}
if (bytes.compareTo(TiB.bytes) >= 0) {
return TiB;
}
if (bytes.compareTo(GiB.bytes) >= 0) {
return GiB;
}
if (bytes.compareTo(MiB.bytes) >= 0) {
return MiB;
}
if (bytes.compareTo(KiB.bytes) >= 0) {
return KiB;
}
return B;
}
public static StorageUnit bestFit(BigInteger bytes) {
return bestFit(new BigDecimal(bytes), B);
}
/**
* Returns {@code MB} instead of {@code MiB}, {@code GB} instead of {@code GiB}, etc.
*/
public String toNiceString() {
String s = toString();
if (B == this) {
return s;
}
return new StringBuilder().append(s.charAt(0)).append(s.charAt(2)).toString();
}
}