blob: 0a2c5ffef5dd73a990df7823e0cb6a50ef57e7b1 [file] [log] [blame]
/*
* Copyright 2013-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.util.unit;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public enum SizeUnit {
BYTES(0),
KILOBYTES(1),
MEGABYTES(2),
GIGABYTES(3),
TERABYTES(4);
private final int ordinal;
private SizeUnit(int ordinal) {
this.ordinal = ordinal;
}
public int getOrdinal() {
return ordinal;
}
private static long multiplyByByteOrderOfMagnitude(double size, int magnitude) {
if (magnitude == 0) {
return (long) size;
} else if (magnitude > 0) {
return BigDecimal.valueOf(size).multiply(BigDecimal.valueOf(1024).pow(magnitude)).longValue();
} else {
return BigDecimal.valueOf(size).divide(
BigDecimal.valueOf(1024).pow(-1 * magnitude)).longValue();
}
}
private static ImmutableMap<String, SizeUnit> SHORT_TO_CODE =
ImmutableMap.<String, SizeUnit>builder()
.put("b", BYTES)
.put("kb", KILOBYTES)
.put("kilobytes", KILOBYTES)
.put("mb", MEGABYTES)
.put("megabytes", MEGABYTES)
.put("gb", GIGABYTES)
.put("gigabytes", GIGABYTES)
.put("tb", TERABYTES)
.put("terabytes", TERABYTES)
.build();
private static Pattern SIZE_PATTERN = Pattern.compile("([\\d]+(?:\\.[\\d]+)?)\\s*((?:" +
Joiner.on(")|(?:").join(SHORT_TO_CODE.keySet()) + "))",
Pattern.CASE_INSENSITIVE);
/**
* Parses a string that represents a size into the number of bytes represented by that string.
*/
public static long parseBytes(String input) throws NumberFormatException {
Matcher matcher = SIZE_PATTERN.matcher(input);
if (matcher.find()) {
String number = matcher.group(1);
SizeUnit sizeUnit = SHORT_TO_CODE.get(matcher.group(2).toLowerCase());
if (sizeUnit != null) {
try {
double value = Double.parseDouble(number);
return sizeUnit.toBytes(value);
} catch (NumberFormatException e) {
// If the number was so large as to overflow Long.MAX_VALUE, return LONG.MAX_VALUE.
return Long.MAX_VALUE;
}
}
}
throw new NumberFormatException(String.format("%s is not a valid file size", input));
}
public long toBytes(double size) {
return multiplyByByteOrderOfMagnitude(size, getOrdinal() - BYTES.getOrdinal());
}
public long toKilobytes(double size) {
return multiplyByByteOrderOfMagnitude(size, getOrdinal() - KILOBYTES.getOrdinal());
}
public long toMegabytes(double size) {
return multiplyByByteOrderOfMagnitude(size, getOrdinal() - MEGABYTES.getOrdinal());
}
public long toGigabytes(double size) {
return multiplyByByteOrderOfMagnitude(size, getOrdinal() - GIGABYTES.getOrdinal());
}
public long toTerabytes(double size) {
return multiplyByByteOrderOfMagnitude(size, getOrdinal() - TERABYTES.getOrdinal());
}
}