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

com.addthis.basis.util.Numbers Maven / Gradle / Ivy

/*
 * 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.addthis.basis.util;

import java.util.Random;

import com.google.common.hash.Hashing;
import com.google.common.hash.HashFunction;

public class Numbers {
    private static final HashFunction fallbackHashFunc = Hashing.murmur3_128();


    /**
     * takes a number in a human readable format (5BM, 6GB, 102K) and returns a long.
     *
     * @param num a human readable format (5BM, 6GB, 102K)
     * @return a long number equivalent to the string representation
     */
    public static long parseHumanReadable(String num) {
        num = num.toUpperCase();
        if (num.endsWith("M") || num.endsWith("MB")) {
            return Long.parseLong(num.substring(0, num.indexOf("M"))) * 1024 * 1024;
        } else if (num.endsWith("MIB")) {
            return Long.parseLong(num.substring(0, num.indexOf("M"))) * 1000 * 1000;
        } else if (num.endsWith("K") || num.endsWith("KB")) {
            return Long.parseLong(num.substring(0, num.indexOf("K"))) * 1024;
        } else if (num.endsWith("KIB")) {
            return Long.parseLong(num.substring(0, num.indexOf("K"))) * 1000;
        } else if (num.endsWith("G") || num.endsWith("GB")) {
            return Long.parseLong(num.substring(0, num.indexOf("G"))) * 1024 * 1024 * 1024;
        } else if (num.endsWith("GIB")) {
            return Long.parseLong(num.substring(0, num.indexOf("G"))) * 1000 * 1000 * 1000;
        } else {
            return Long.parseLong(num);
        }
    }

    /**
     * integer
     */
    public static int parseInt(String val, int def, int radix) {
        try {
            return Integer.parseInt(val, radix);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * long
     */
    public static long parseLong(String val, long def, int radix) {
        try {
            return Long.parseLong(val, radix);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * float
     */
    public static float parseFloat(String val, float def) {
        try {
            return Float.parseFloat(val);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * double
     */
    public static double parseDouble(String val, double def) {
        try {
            return Double.parseDouble(val);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * Converts a base-encoded string to a long.
     * Does not handle negative numbers;
     */
    public static long longFromBase(String val, int base) {
        return longFromBase(val, base, false);
    }

    public static long longFromBase(String val, int base, boolean fallback) {
        if (base > basechars.length) {
            if (fallback) {
                return fallbackHashFunc.hashUnencodedChars(val).asLong();
            }
            throw new RuntimeException(base + " outside base range of 2-" + basechars.length);
        }
        long rv = 0;
        char cv[] = val.toCharArray();
        for (char aCv : cv) {
            rv *= base;
            int av = 0;
            if (aCv >= '0' && aCv <= '9') {
                av = aCv - '0';
            } else if (aCv >= 'a' && aCv <= 'z') {
                av = aCv - 'a' + 10;
            } else if (aCv >= 'A' && aCv <= 'Z') {
                av = aCv - 'A' + 36;
            } else {
                if (fallback) {
                    return fallbackHashFunc.hashUnencodedChars(val).asLong();
                }
                throw new RuntimeException("invalid base encoding: " + val);
            }
            if (av >= base) {
                if (fallback) {
                    return fallbackHashFunc.hashUnencodedChars(val).asLong();
                }
                throw new RuntimeException("chars outside of base range: " + val);
            }
            rv += av;
        }
        return rv;
    }

    /**
     * Converts a base-encoded string to an integer.
     * Does not handle negative numbers;
     */
    public static int intFromBase(String val, int base) {
        if (base > basechars.length) {
            throw new RuntimeException(base + " outside base range of 2-" + basechars.length);
        }
        int rv = 0;
        char cv[] = val.toCharArray();
        for (char aCv : cv) {
            rv *= base;
            if (aCv >= '0' && aCv <= '9') {
                rv += aCv - '0';
            } else if (aCv >= 'a' && aCv <= 'z') {
                rv += aCv - 'a' + 10;
            } else if (aCv >= 'A' && aCv <= 'Z') {
                rv += aCv - 'A' + 36;
            } else {
                throw new RuntimeException("invalid base encoding: " + val);
            }
        }
        return rv;
    }

    /**
     * Array of chars for generating numbers in alternate bases.
     */
    static final char basechars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

    public static final int MAX_BASE = basechars.length;
    /**
     * String containing zeros for pre-padding base-36 longs.
     */
    private static final String pads[] = new String[MAX_BASE];
    /**
     * Public pre-generated Random for what ailes you.
     */
    public static final Random random = new Random(System.currentTimeMillis());

    /**
     * Converts a long to a base-encoded string.  Does not handle negative numbers;
     */
    public static String toBase(long val, int base) {
        return toBase(val, base, -1);
    }

    public static String toBase(long val, int base, int minlen) {
        if (base > basechars.length) {
            throw new RuntimeException(base + " outside base range of 2-" + basechars.length);
        }
        char out[] = new char[128];
        for (int i = out.length - 1;; i--) {
            out[i] = basechars[(int) Math.abs(val % base)];
            val = val / base;
            if (--minlen <= 0 && (val == 0 || i == 0)) {
                return new String(out, i, out.length - i);
            }
        }
    }

    /**
     * Generates a random long in specified pre-padded with 0s.
     *
     * @return long in specified base pre-padded with 0s
     */
    static String nextLong(int base) {
        synchronized (pads) {
            String pad = pads[base - 1];
            if (pad == null) {
                pad = Bytes.clear(toBase(Long.MAX_VALUE, base), '0');
                pads[base - 1] = pad;
            }
            String nv = toBase(random.nextLong(), base);
            return pad.substring(nv.length()) + nv;
        }
    }

    /**
     * Array of bytes for generating hex strings.
     */
    public static final byte hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    public static final byte HEX[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    private static final boolean verboseHex = System.getProperty("xhex", "0").equals("1");

    public static String toHexString(byte b[]) {
        StringBuilder sb = new StringBuilder();
        for (byte c : b) {
            if (sb.length() > 0) {
                sb.append(' ');
            }
            char c1 = (char) hex[(c >> 4) & 0xf];
            char c2 = (char) hex[(c & 0xf)];
            sb.append(c1);
            sb.append(c2);
            if (verboseHex) {
                sb.append(' ');
                if (c >= 32 && c <= 126) {
                    sb.append((char) c);
                } else {
                    sb.append('.');
                }
            }
        }
        return sb.toString();
    }

    /**
     * Parse integer with given radix and default value on errors
     */
    public static int parseInt(int radix, String val, int def) {
        try {
            return Integer.parseInt(val, radix);
        } catch (Exception ex) {
            return def;
        }
    }

    /**
     * Parse integer with given radix and default value on errors
     */
    public static long parseLong(int radix, String val, long def) {
        try {
            return Long.parseLong(val, radix);
        } catch (Exception ex) {
            return def;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy