All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.coherence.common.util.Bandwidth Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */
package com.oracle.coherence.common.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A {@link Bandwidth} represents an amount of memory (measured in bits) being
 * transferred per second.
 * 

* Measurements are based on the decimal system as outlined by the IEC. *

* eg: In this implementation 1 kbps = 1000 bits per second, not 1024 bits per second * * @author cp, bko 2011.07.15 */ public class Bandwidth { // ----- constructors ----------------------------------------------- /** * Construct a {@link Bandwidth} by parsing the specified {@link String}. * * @param s The {@link String} containing the definition of a {@link Bandwidth} */ public Bandwidth(String s) { s = (s == null) ? null : s.trim(); if ((s == null) || s.isEmpty()) { throw new IllegalArgumentException("An empty or null string was provided. Expected a bandwidth"); } if (!s.equals("0")) { Matcher matcher = REGEX_PATTERN.matcher(s); if (!matcher.matches()) { throw new IllegalArgumentException(String.format("The specified %s [%s] is invalid.", this.getClass().getName(), s)); } // determine the rate (using group 3) Rate rate = Rate.fromSuffix(matcher.group(3)); // determine the magnitude (using group 2) Magnitude magnitude = Magnitude.fromSuffix(matcher.group(2)); // determine the amount (using group 1) double cUnits = Double.valueOf(matcher.group(1)); m_cBits = rate.toBits(Math.round(cUnits * magnitude.getFactor())); } } /** * Construct a {@link Bandwidth} given a specified units and {@link Rate}. *

* As the amount is a double precision value, the resulting {@link Bandwidth} will be rounded to the closest unit. * * @param cUnits The number of units of the {@link Magnitude} and {@link Rate}. * @param rate The {@link Rate} */ public Bandwidth(double cUnits, Rate rate) { assert cUnits >= 0.0; m_cBits = rate.toBits(Math.round(cUnits)); } /** * Construct a {@link Bandwidth} given a specified units and {@link Rate}. * * @param cUnits The number of units of the {@link Magnitude} and {@link Rate}. * @param rate The {@link Rate} */ public Bandwidth(int cUnits, Rate rate) { this((long) cUnits, rate); } /** * Construct a {@link Bandwidth} give a specified number of bytes. * * @param cBytes The number of bytes in the memory size * @param rate The {@link Rate} */ public Bandwidth(long cBytes, Rate rate) { assert cBytes >= 0; m_cBits = rate.toBits(cBytes); } // ----- Bandwidth methods --------------------------------------------- /** * Obtain the {@link Bandwidth} as a value in the specified {@link Magnitude}. * * @param magnitude The {@link Magnitude} * * @return The maximum number of units of the specified {@link Magnitude} * for the {@link Bandwidth}. */ public long as(Magnitude magnitude) { return m_cBits / magnitude.getFactor(); } /** * Obtain the {@link Bandwidth} as a value in the specified {@link Rate}. * * @param rate The {@link Rate} * * @return The number of units of the specified {@link Rate} * for the {@link Bandwidth}. */ public long as(Rate rate) { return rate.fromBits(m_cBits); } /** * Obtains a {@link String} representation of the {@link Bandwidth} (in {@link Rate#BITS}). * * @param fExact Indicates an exact value is required or if a rounded value will suffice. * * @return A {@link String} */ public String toString(boolean fExact) { Magnitude magnitude = Magnitude.BASE; long nBits = m_cBits; // find the highest magnitude to represent the number appropriately while ((magnitude.next() != null) && (nBits >= magnitude.next().getFactor()) && ((fExact && (nBits % magnitude.next().getFactor()) % (magnitude.next().getFactor() / 4) == 0) ||!fExact)) { magnitude = magnitude.next(); } long cMagnitudeUnits = nBits / magnitude.getFactor(); long nRemainder = nBits % magnitude.getFactor(); int cSignificantDigits = 3; StringBuilder bldrString = new StringBuilder(); bldrString.append(cMagnitudeUnits); int cDigits = bldrString.length(); int cRemainingDigits = cSignificantDigits - cDigits; if ((cRemainingDigits > 0) && (nRemainder > 0)) { int nSignificanceFactor = (int) Math.pow(10, cRemainingDigits); long nDecimals = (long) Math.floor(nRemainder * (double) nSignificanceFactor / magnitude.getFactor()); if (nDecimals > 0) { bldrString.append("."); int cLeadingZeros = cRemainingDigits - (int)Math.log10(nDecimals) - 1; for (int i = 0; i < cLeadingZeros; i++) { bldrString.append('0'); } bldrString.append(nDecimals); } } bldrString.append(magnitude.getSuffix()); bldrString.append("b/s"); return bldrString.toString(); } // ----- Object methods ------------------------------------------------- /** * {@inheritDoc} */ @Override public int hashCode() { return 31 + (int) (m_cBits ^ (m_cBits >>> 32)); } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { return (this == obj) || ((obj != null) && (obj instanceof Bandwidth) && ((Bandwidth) obj).m_cBits == m_cBits); } /** * {@inheritDoc} */ @Override public String toString() { return toString(false); } // ----- Magnitude Enumeration ------------------------------------------ /** * A {@link Magnitude} of {@link Bandwidth}. */ public enum Magnitude { BASE(1L, ""), KILO(1000L, "kilo"), MEGA(1000000L, "mega"), GIGA(1000000000L, "giga"), TERA(1000000000000L, "tera"), PETA(1000000000000000L, "peta"), EXA(1000000000000000000L, "exa"); // ----- constructors ----------------------------------------------- /** * Construct a {@link Magnitude} * * @param nFactor The factor of the {@link Magnitude} * @param sDescription The description of the {@link Magnitude} */ Magnitude(long nFactor, String sDescription) { DESCRIPTION = sDescription.trim(); SUFFIX = DESCRIPTION.isEmpty() ? "" : DESCRIPTION.substring(0, 1); FACTOR = nFactor; } // ----- Magnitude methods ------------------------------------------ /** * Obtain the name of the {@link Magnitude}. For example, a kilo has the * description "kilo". * * @return The {@link Magnitude}'s description */ public String getDescription() { return DESCRIPTION; } /** * Obtain the suffix of the {@link Magnitude}. * * @return A {@link String} */ public String getSuffix() { return SUFFIX; } /** * Obtain the factor of the {@link Magnitude}. * * @return The factor */ public long getFactor() { return FACTOR; } /** * Determine if the passed suffix is compatible with this {@link Magnitude}'s suffix, ignoring case. * * @param s The suffix to test * * @return true iff the passed string is compatible with the suffix of this {@link Magnitude}. */ public boolean isSuffix(String s) { return s.equalsIgnoreCase(SUFFIX); } /** * Obtain the next order of {@link Magnitude} (above this one). * * @return The next order of {@link Magnitude} above this one or null if this is * the {@link #HIGHEST}. */ public Magnitude next() { if (this.equals(Magnitude.HIGHEST)) { return null; } else { return Magnitude.VALUES[this.ordinal() + 1]; } } /** * Obtain the previous order of {@link Magnitude} (above this one). * * @return The previous order of {@link Magnitude} or null if this is * the {@link #LOWEST}. */ public Magnitude previous() { if (this.equals(Magnitude.LOWEST)) { return null; } else { return Magnitude.VALUES[this.ordinal() - 1]; } } // ----- helpers ---------------------------------------------------- /** * Determine the {@link Magnitude} given the specified suffix. * * @param sSuffix The proposed suffix * * @return A {@link Magnitude} with the specified suffix */ public static Magnitude fromSuffix(String sSuffix) { sSuffix = sSuffix.trim(); if (sSuffix.length() == 0) { return Magnitude.BASE; } else if (sSuffix.length() > 0) { for (Magnitude magnitude : Magnitude.VALUES) { if (magnitude.isSuffix(sSuffix)) { return magnitude; } } } throw new IllegalArgumentException(String.format("Unknown %s suffix [%s]", Magnitude.class.getName(), sSuffix)); } // ----- data members ----------------------------------------------- /** * The description of this {@link Magnitude}. For example, a kilo has the name "kilo". */ private final String DESCRIPTION; /** * The number of order of the magnitude. For example, a kilo is 1000. */ private final long FACTOR; /** * The suffix that represents this {@link Magnitude}. For example, a kilobyte has the suffix "K". */ private final String SUFFIX; // ----- constants -------------------------------------------------- /** * Cached copy of the values array to avoid garbage creation */ private static final Magnitude[] VALUES = Magnitude.values(); /** * The lowest defined order of {@link Magnitude}. */ public final static Magnitude LOWEST = Magnitude.VALUES[0]; /** * The highest defined order of {@link Magnitude}. */ public final static Magnitude HIGHEST = Magnitude.VALUES[Magnitude.VALUES.length - 1]; } // ----- Rate Enumeration ----------------------------------------------- /** * A {@link Rate} of a {@link Bandwidth} per second. */ public enum Rate { BITS(0, "b"), BYTES(3, "B"); // ----- constructors ----------------------------------------------- /** * Construct a {@link Rate}. * * @param cShift The binary (left) shift that the {@link Rate} requires to convert to a number of bits * @param sSuffix The suffix for the {@link Rate} */ Rate(int cShift, String sSuffix) { SHIFT = cShift; SUFFIX = sSuffix; } // ----- Rate methods ----------------------------------------------- /** * Determine the name of the {@link Rate}. * * @return "bits" or "bytes" */ public String getDescription() { return name().toLowerCase(); } /** * Obtain the suffix that identifies the {@link Rate}. * * @return "b" for "bits", or "B" for "bytes" */ public String getSuffix() { return SUFFIX; } /** * Convert the specified number of units of this {@link Rate} into a bits {@link Rate}. * * @param cUnits The number of units of this {@link Rate} * * @return The number of {@link Rate#BITS} units. */ public long toBits(long cUnits) { return cUnits << SHIFT; } /** * Convert the specified number of bits to units of this {@link Rate}. * * @param cBits The number of bits. * * @return The number of units of this {@link Rate}. */ public long fromBits(long cBits) { return cBits >> SHIFT; } // ----- helpers ---------------------------------------------------- /** * Convert a number of units of the specified {@link Rate} to another {@link Rate}. * * @param cUnits The number of units * @param rateFrom The {@link Rate} to convert from * @param rateTo The {@link Rate} to convert to * * @return the number of bits */ public static long convert(long cUnits, Rate rateFrom, Rate rateTo) { if (rateFrom.equals(rateTo)) { return cUnits; } else { return rateTo.fromBits(rateFrom.toBits(cUnits)); } } /** * Determine the {@link Rate} given the specified suffix. * * @param sSuffix The proposed suffix * * @return A {@link Rate} with the specified suffix */ public static Rate fromSuffix(String sSuffix) { sSuffix = sSuffix.trim(); if (sSuffix.length() == 0) { return Rate.BITS; } else if (sSuffix.length() > 0) { for (Rate rate : Rate.VALUES) { if (rate.getSuffix().equals(sSuffix)) { return rate; } } } throw new IllegalArgumentException(String.format("Unknown %s suffix [%s]", Rate.class.getName(), sSuffix)); } // ----- data members ----------------------------------------------- /** * Cached copy of the values array to avoid garbage creation */ private static final Rate[] VALUES = Rate.values(); /** * The binary shift that the {@link Rate} requires to convert a number * of units to or from the corresponding number of bytes. */ private final int SHIFT; /** * The one-character suffix for the {@link Rate}. */ private final String SUFFIX; } // ----- data members --------------------------------------------------- /** * The number of {@link Rate#BITS} in the {@link Bandwidth}. */ private long m_cBits; // ----- constants ------------------------------------------------------ /** * The pre-compiled regular expression {@link Pattern} to match * a {@link Bandwidth} specified as a {@link String}. */ private static final Pattern REGEX_PATTERN = Pattern.compile("([0-9]+(?:\\.[0-9]+)?)([kKMmGgTtPpEe]?)/?([Bb]?)[Pp/]?[Ss]"); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy