Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71e11ae9 authored by Juan Yescas's avatar Juan Yescas
Browse files

Add method to parse the size in FileUtils

The method parseSize() will parse the strings that match
the regular expression:

  "^((\\s*[-+]?[0-9]+)\\s*(B|K|KB|M|MB|G|GB|Ki|KiB|Mi|MiB|Gi|GiB)\\s*)$"

For example: 12GB, +100MB, 23MiB.

It will return the size in bytes.

Test: atest
Bug: 231718727
Change-Id: Id4b9084d2ff8a0a8bd23ddb8a7e10dcf17391c49
parent 3023a334
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
import android.text.TextUtils;
import android.util.DataUnit;
import android.util.Log;
import android.util.Slog;
import android.webkit.MimeTypeMap;
@@ -83,6 +84,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -1309,6 +1311,85 @@ public final class FileUtils {
        return val * pow;
    }

    private static long toBytes(long value, String unit) {
        unit = unit.toUpperCase();

        if (List.of("B").contains(unit)) {
            return value;
        }

        if (List.of("K", "KB").contains(unit)) {
            return DataUnit.KILOBYTES.toBytes(value);
        }

        if (List.of("M", "MB").contains(unit)) {
            return DataUnit.MEGABYTES.toBytes(value);
        }

        if (List.of("G", "GB").contains(unit)) {
            return DataUnit.GIGABYTES.toBytes(value);
        }

        if (List.of("KI", "KIB").contains(unit)) {
            return DataUnit.KIBIBYTES.toBytes(value);
        }

        if (List.of("MI", "MIB").contains(unit)) {
            return DataUnit.MEBIBYTES.toBytes(value);
        }

        if (List.of("GI", "GIB").contains(unit)) {
            return DataUnit.GIBIBYTES.toBytes(value);
        }

        return Long.MIN_VALUE;
    }

    /**
     * @param fmtSize The string that contains the size to be parsed. The
     *   expected format is:
     *
     *   <p>"^((\\s*[-+]?[0-9]+)\\s*(B|K|KB|M|MB|G|GB|Ki|KiB|Mi|MiB|Gi|GiB)\\s*)$"
     *
     *   <p>For example: 10Kb, 500GiB, 100mb. The unit is not case sensitive.
     *
     * @return the size in bytes. If {@code fmtSize} has invalid format, it
     *   returns {@link Long#MIN_VALUE}.
     * @hide
     */
    public static long parseSize(@Nullable String fmtSize) {
        if (fmtSize == null || fmtSize.isBlank()) {
            return Long.MIN_VALUE;
        }

        int sign = 1;
        fmtSize = fmtSize.trim();
        char first = fmtSize.charAt(0);
        if (first == '-' ||  first == '+') {
            if (first == '-') {
                sign = -1;
            }

            fmtSize = fmtSize.replace(first + "", "");
        }

        int index = 0;
        // Find the last index of the value in fmtSize.
        while (index < fmtSize.length() && Character.isDigit(fmtSize.charAt(index))) {
            index++;
        }

        // Check if number and units are present.
        if (index == 0 || index == fmtSize.length()) {
            return Long.MIN_VALUE;
        }

        long value = sign * Long.valueOf(fmtSize.substring(0, index));
        String unit = fmtSize.substring(index).trim();

        return toBytes(value, unit);
    }

    /**
     * Closes the given object quietly, ignoring any checked exceptions. Does
     * nothing if the given object is {@code null}.
+52 −2
Original line number Diff line number Diff line
@@ -58,10 +58,10 @@ import android.provider.DocumentsContract.Document;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import libcore.io.Streams;

import com.google.android.collect.Sets;

import libcore.io.Streams;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -523,6 +523,56 @@ public class FileUtilsTest {
        assertEquals(G64, roundStorageSize(G32 + 1));
    }

    @Test
    public void testParseSize() {
        assertEquals(0L, FileUtils.parseSize("0MB"));
        assertEquals(1_024L, FileUtils.parseSize("1024b"));
        assertEquals(-1L, FileUtils.parseSize(" -1 b "));
        assertEquals(0L, FileUtils.parseSize(" -0 gib "));
        assertEquals(1_000L, FileUtils.parseSize("1K"));
        assertEquals(1_000L, FileUtils.parseSize("1KB"));
        assertEquals(10_000L, FileUtils.parseSize("10KB"));
        assertEquals(100_000L, FileUtils.parseSize("100KB"));
        assertEquals(1_000_000L, FileUtils.parseSize("1000KB"));
        assertEquals(1_024_000L, FileUtils.parseSize("1000KiB"));
        assertEquals(70_000_000L, FileUtils.parseSize("070M"));
        assertEquals(70_000_000L, FileUtils.parseSize("070MB"));
        assertEquals(73_400_320L, FileUtils.parseSize("70MiB"));
        assertEquals(700_000_000L, FileUtils.parseSize("700000KB"));
        assertEquals(200_000_000L, FileUtils.parseSize("+200MB"));
        assertEquals(1_000_000_000L, FileUtils.parseSize("1000MB"));
        assertEquals(1_000_000_000L, FileUtils.parseSize("+1000 mb"));
        assertEquals(644_245_094_400L, FileUtils.parseSize("600GiB"));
        assertEquals(999_000_000_000L, FileUtils.parseSize("999GB"));
        assertEquals(999_000_000_000L, FileUtils.parseSize("999 gB"));
        assertEquals(9_999_000_000_000L, FileUtils.parseSize("9999GB"));
        assertEquals(9_000_000_000_000L, FileUtils.parseSize(" 9000 GB   "));
        assertEquals(1_234_000_000_000L, FileUtils.parseSize(" 1234 GB  "));
        assertEquals(1_234_567_890_000L, FileUtils.parseSize(" 1234567890 KB  "));
    }

    @Test
    public void testParseSize_invalidArguments() {
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize(null));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("null"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize(""));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("     "));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("KB"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("123 dd"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("Invalid"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" ABC890 KB  "));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("-=+90 KB  "));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("123"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("--123"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("-KB"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("++123"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+ 1 +"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+--+ 1 +"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize("1GB+"));
        assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" + 1234567890 KB  "));
    }

    @Test
    public void testTranslateMode() throws Exception {
        assertTranslate("r", O_RDONLY, MODE_READ_ONLY);