From bfbbaa4e458735b6410c686a806c512f6fac7e2a Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 01 Jun 2007 11:05:50 +0000
Subject: [PATCH] Add a new method for retrieving the "best-fit" size unit appropriate for a given number of bytes. This is intended for use in user interfaces since the value returned maybe a floating point value and subject to small errors. For LDAP encoding/decoding we still have the original getBestFitUnit() method but it has been renamed to getBestFitUnitExact(). Both methods are class methods.
---
opends/src/server/org/opends/server/admin/SizeUnit.java | 199 ++++++++++++++++++++++++++++++++++---------------
1 files changed, 137 insertions(+), 62 deletions(-)
diff --git a/opends/src/server/org/opends/server/admin/SizeUnit.java b/opends/src/server/org/opends/server/admin/SizeUnit.java
index df735b2..8f58bbf 100644
--- a/opends/src/server/org/opends/server/admin/SizeUnit.java
+++ b/opends/src/server/org/opends/server/admin/SizeUnit.java
@@ -46,24 +46,9 @@
BYTES(1L, "b", "bytes"),
/**
- * A kilo-byte unit.
+ * A gibi-byte unit.
*/
- KILO_BYTES(1000L, "kb", "kilobytes"),
-
- /**
- * A kibi-byte unit.
- */
- KIBI_BYTES(1024L, "kib", "kibibytes"),
-
- /**
- * A mega-byte unit.
- */
- MEGA_BYTES((long) 1000 * 1000, "mb", "megabytes"),
-
- /**
- * A mebi-byte unit.
- */
- MEBI_BYTES((long) 1024 * 1024, "mib", "mebibytes"),
+ GIBI_BYTES((long) 1024 * 1024 * 1024, "gib", "gibibytes"),
/**
* A giga-byte unit.
@@ -71,19 +56,34 @@
GIGA_BYTES((long) 1000 * 1000 * 1000, "gb", "gigabytes"),
/**
- * A gibi-byte unit.
+ * A kibi-byte unit.
*/
- GIBI_BYTES((long) 1024 * 1024 * 1024, "gib", "gibibytes"),
+ KIBI_BYTES(1024L, "kib", "kibibytes"),
/**
- * A tera-byte unit.
+ * A kilo-byte unit.
*/
- TERA_BYTES((long) 1000 * 1000 * 1000 * 1000, "tb", "terabytes"),
+ KILO_BYTES(1000L, "kb", "kilobytes"),
+
+ /**
+ * A mebi-byte unit.
+ */
+ MEBI_BYTES((long) 1024 * 1024, "mib", "mebibytes"),
+
+ /**
+ * A mega-byte unit.
+ */
+ MEGA_BYTES((long) 1000 * 1000, "mb", "megabytes"),
/**
* A tebi-byte unit.
*/
- TEBI_BYTES((long) 1024 * 1024 * 1024 * 1024, "tib", "tebibytes");
+ TEBI_BYTES((long) 1024 * 1024 * 1024 * 1024, "tib", "tebibytes"),
+
+ /**
+ * A tera-byte unit.
+ */
+ TERA_BYTES((long) 1000 * 1000 * 1000 * 1000, "tb", "terabytes");
// A lookup table for resolving a unit from its name.
private static final Map<String, SizeUnit> nameToUnit;
@@ -99,15 +99,120 @@
/**
+ * Gets the best-fit unit for the specified number of bytes. The
+ * returned unit will be able to represent the number of bytes using
+ * a decimal number comprising of an integer part which is greater
+ * than zero. Bigger units are chosen in preference to smaller units
+ * and binary units are only returned if they are an exact fit. If
+ * the number of bytes is zero then the {@link #BYTES} unit is
+ * always returned. For example:
+ *
+ * <pre>
+ * getBestFitUnit(0) // BYTES
+ * getBestFitUnit(999) // BYTES
+ * getBestFitUnit(1000) // KILO_BYTES
+ * getBestFitUnit(1024) // KIBI_BYTES
+ * getBestFitUnit(1025) // KILO_BYTES
+ * getBestFitUnit(999999) // KILO_BYTES
+ * getBestFitUnit(1000000) // MEGA_BYTES
+ * </pre>
+ *
+ * @param bytes
+ * The number of bytes.
+ * @return Returns the best fit unit.
+ * @throws IllegalArgumentException
+ * If <code>bytes</code> is negative.
+ * @see #getBestFitUnitExact(long)
+ */
+ public static SizeUnit getBestFitUnit(long bytes)
+ throws IllegalArgumentException {
+ if (bytes < 0) {
+ throw new IllegalArgumentException("negative number of bytes: " + bytes);
+ } else if (bytes == 0) {
+ // Always use bytes for zero values.
+ return BYTES;
+ } else {
+ // Determine best fit: prefer non-binary units unless binary
+ // fits exactly.
+ SizeUnit[] nonBinary = new SizeUnit[] { TERA_BYTES, GIGA_BYTES,
+ MEGA_BYTES, KILO_BYTES };
+ SizeUnit[] binary = new SizeUnit[] { TEBI_BYTES, GIBI_BYTES, MEBI_BYTES,
+ KIBI_BYTES };
+
+ for (int i = 0; i < nonBinary.length; i++) {
+ if ((bytes % binary[i].getSize()) == 0) {
+ return binary[i];
+ } else if ((bytes / nonBinary[i].getSize()) > 0) {
+ return nonBinary[i];
+ }
+ }
+
+ return BYTES;
+ }
+ }
+
+
+
+ /**
+ * Gets the best-fit unit for the specified number of bytes which
+ * can represent the provided value using an integral value. Bigger
+ * units are chosen in preference to smaller units. If the number of
+ * bytes is zero then the {@link #BYTES} unit is always returned.
+ * For example:
+ *
+ * <pre>
+ * getBestFitUnitExact(0) // BYTES
+ * getBestFitUnitExact(999) // BYTES
+ * getBestFitUnitExact(1000) // KILO_BYTES
+ * getBestFitUnitExact(1024) // KIBI_BYTES
+ * getBestFitUnitExact(1025) // BYTES
+ * getBestFitUnitExact(999999) // BYTES
+ * getBestFitUnitExact(1000000) // MEGA_BYTES
+ * </pre>
+ *
+ * @param bytes
+ * The number of bytes.
+ * @return Returns the best fit unit can represent the provided
+ * value using an integral value.
+ * @throws IllegalArgumentException
+ * If <code>bytes</code> is negative.
+ * @see #getBestFitUnit(long)
+ */
+ public static SizeUnit getBestFitUnitExact(long bytes)
+ throws IllegalArgumentException {
+ if (bytes < 0) {
+ throw new IllegalArgumentException("negative number of bytes: " + bytes);
+ } else if (bytes == 0) {
+ // Always use bytes for zero values.
+ return BYTES;
+ } else {
+ // Determine best fit.
+ SizeUnit[] units = new SizeUnit[] { TEBI_BYTES, TERA_BYTES, GIBI_BYTES,
+ GIGA_BYTES, MEBI_BYTES, MEGA_BYTES, KIBI_BYTES, KILO_BYTES };
+
+ for (SizeUnit unit : units) {
+ if ((bytes % unit.getSize()) == 0) {
+ return unit;
+ }
+ }
+
+ return BYTES;
+ }
+ }
+
+
+
+ /**
* Get the unit corresponding to the provided unit name.
*
* @param s
- * The name of the unit. Can be the abbreviated or long name and can
- * contain white space and mixed case characters.
+ * The name of the unit. Can be the abbreviated or long
+ * name and can contain white space and mixed case
+ * characters.
* @return Returns the unit corresponding to the provided unit name.
* @throws IllegalArgumentException
- * If the provided name did not correspond to a known memory size
- * unit.
+ * If the provided name did not correspond to a known
+ * memory size unit.
*/
public static SizeUnit getUnit(String s) throws IllegalArgumentException {
SizeUnit unit = nameToUnit.get(s.trim().toLowerCase());
@@ -188,14 +293,14 @@
return unit.toBytes(d);
}
- // The size of the unit in bytes.
- private final long sz;
+ // The long name of the unit.
+ private final String longName;
// The abbreviation of the unit.
private final String shortName;
- // The long name of the unit.
- private final String longName;
+ // The size of the unit in bytes.
+ private final long sz;
@@ -222,37 +327,6 @@
/**
- * Get the best-fit unit for the specified amount in this unit. The returned
- * unit will be able to represent the amount using an integral value (i.e. no
- * fractional part).For example, if this unit is kilo-bytes and the amount
- * 2000 is provided, then the best fit unit is mega-bytes: 2mb. Similarly, if
- * the amount is 0.5, then the best fit unit will by bytes: 500b.
- * <p>
- * Only non-binary units are considered (i.e. kilo, mega, etc).
- *
- * @param amount
- * The amount of this unit.
- * @return Returns the best-fit unit for the specified amount in this unit.
- */
- public SizeUnit getBestFitUnit(double amount) {
- long bytes = toBytes(amount);
- if (bytes == 0) {
- return this;
- } else if (bytes > 0) {
- // use array of SizeUnits; EnumSet iterates in natural order
- for (SizeUnit unit : new SizeUnit[]{TERA_BYTES, GIGA_BYTES, MEGA_BYTES,
- KILO_BYTES }) {
- if ((bytes % unit.sz) == 0) {
- return unit;
- }
- }
- }
- return BYTES;
- }
-
-
-
- /**
* Get the long name of this unit.
*
* @return Returns the long name of this unit.
@@ -301,7 +375,8 @@
/**
* {@inheritDoc}
* <p>
- * This implementation returns the abbreviated name of this size unit.
+ * This implementation returns the abbreviated name of this size
+ * unit.
*/
@Override
public String toString() {
--
Gitblit v1.10.0