/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.util; import com.google.gwt.regexp.shared.MatchResult; import com.google.gwt.regexp.shared.RegExp; import java.math.BigDecimal; /** * Allow to manage bytes value by providing human values * Also human values can be transformed into some units * @author Florent Benoit */ public class Bytes { /** * Pattern to split size unit */ private static RegExp UNIT_PATTERN = RegExp.compile("(\\s*\\d*\\.?\\d+)(.*)"); /** * All units supported */ public static enum Unit { B(1), KiB(1024), KB(1e3), MiB(KiB.value * 1024), MB(1e6), GiB(MiB.value * 1024), GB(1e9), TiB(GiB.value * 1024), TB( 1e12), PiB(TiB.value * 1024), PB(1e15), EiB(PiB.value * 1024), EB(1e18); private double value; Unit(double value) { this.value = value; } public double getValue() { return value; } } /** * Utility class so private constructor. */ private Bytes() { } /** * Returns a simplified version of the given size. For example giving '4000MB' will return '4GB' * @param humanSize a stringified version * @return the new size by using the higher range value */ public static String toHumanSize(String humanSize) { // convert to bytes first return toHumanSize(fromHumanSize(humanSize)); } /** * Convert a value in bytes to value readable by humans * @param bytesValue the bytes value * @return the updated value */ public static String toHumanSize(long bytesValue) { if (0 == bytesValue) { return "0B"; } // it's on base 2 boolean powerOfTwo = false; if ((bytesValue & (bytesValue -1L)) == 0) { powerOfTwo = true; } // or an exact modulo like 1.5 long multiple = (long)(bytesValue / 1.5); if ((multiple & (multiple - 1L)) == 0) { powerOfTwo = true; } Unit unit = Unit.B; // power of two if (powerOfTwo) { if (bytesValue >= Unit.EiB.value) { unit = Unit.EiB; } else if (bytesValue >= Unit.PiB.value) { unit = Unit.PiB; } else if (bytesValue >= Unit.TiB.value) { unit = Unit.TiB; } else if (bytesValue >= Unit.GiB.value) { unit = Unit.GiB; } else if (bytesValue >= Unit.MiB.value) { unit = Unit.MiB; } else if (bytesValue >= Unit.KiB.value) { unit = Unit.KiB; } } else { // base 10 if (bytesValue >= Unit.EB.value) { unit = Unit.EB; } else if (bytesValue >= Unit.PB.value) { unit = Unit.PB; } else if (bytesValue >= Unit.TB.value) { unit = Unit.TB; } else if (bytesValue >= Unit.GB.value) { unit = Unit.GB; } else if (bytesValue >= Unit.MB.value) { unit = Unit.MB; } else if (bytesValue >= Unit.KB.value) { unit = Unit.KB; } } // one digit float double val = (bytesValue / unit.getValue()); double roundedValue = Math.round(val * 10.0) / 10.0; // Strip any trailing 0 BigDecimal myDecimal = BigDecimal.valueOf(roundedValue); BigDecimal updated = myDecimal.stripTrailingZeros(); return updated.toPlainString() + unit.name(); } /** * Convert human size unit to a bytes value * @param humanSize the human size to convert * @return the byes value */ public static long fromHumanSize(String humanSize) { // first convert it to bytes Pair<Double, Unit> value = splitValueAndUnit(humanSize); // now convert it to bytes return convertToBytes(value); } /** * */ protected static long convertToBytes(Pair<Double, Unit> value) { // first index is value, second one is unit return new Double(value.getFirst().doubleValue() * value.getSecond().getValue()).longValue(); } /** * Extract unit and values from the given string * @param humanSize the value to analyze * @return array with first index the value, second one the unit */ protected static Pair<Double, Unit> splitValueAndUnit(String humanSize) { MatchResult matchResult = UNIT_PATTERN.exec(humanSize); if (matchResult.getGroupCount() != 3 || matchResult.getGroup(2).isEmpty()) { throw new IllegalArgumentException("Unable to get unit in the given value '" + humanSize + "'"); } Double val = Double.parseDouble(matchResult.getGroup(1).trim()); Unit unitVal = Unit.valueOf(matchResult.getGroup(2).trim()); Pair<Double, Unit> value = new Pair<>(val, unitVal); return value; } }