-package org.argeo.app.api;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.ThreadLocalRandom;
-
-/** A range of numerical IDs (typically numerical uid or gid). */
-public class IdRange {
- // see https://systemd.io/UIDS-GIDS/#special-distribution-uid-ranges
- final static long MIN_INCLUDED = Long.parseUnsignedLong("66000");
- final static long MAX_EXCLUDED = Long.parseUnsignedLong("4294967294");
-
- // We use long as a de facto unsigned int
-
- /** included */
- private final long min;
- /** included */
- private final long max;
-
- public IdRange(long min, long max) {
- this.min = min;
- this.max = max;
- }
-
- public IdRange(long minPow10) {
- this(minPow10, maxFromMinPow10(minPow10));
- }
-
- public long getMin() {
- return min;
- }
-
- public long getMax() {
- return max;
- }
-
- @Override
- public int hashCode() {
- return (int) min;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof IdRange idRange) {
- return min == idRange.min && max == idRange.max;
- } else
- return false;
- }
-
- @Override
- public String toString() {
- return "[" + Long.toUnsignedString(min) + "," + Long.toUnsignedString(max) + "]";
- }
-
- /*
- * RANGE GENERATION
- */
- public static synchronized Set<IdRange> randomRanges10000(int count, Set<IdRange> forbiddenRanges) {
- Set<IdRange> res = new HashSet<>();
-
- for (int i = 0; i < count; i++) {
- IdRange newRange = null;
- do {
- newRange = randomRange10000();
- } while (overlap(newRange, res) || overlap(newRange, forbiddenRanges));
- res.add(newRange);
- }
- return res;
- }
-
- public static synchronized IdRange randomRange10000() {
- // TODO make it more generic
- long minPred = 7l;
- long maxPred = 429496l;
-
- long rand = ThreadLocalRandom.current().nextLong(minPred, maxPred);
- long min = rand * 10000l;
- return new IdRange(min);
- }
-
- public static boolean overlap(IdRange idRange, Set<IdRange> idRanges) {
- for (IdRange other : idRanges) {
- if (overlap(idRange, other))
- return true;
- }
- return false;
- }
-
- public static boolean overlap(IdRange idRange, IdRange other) {
- // see
- // https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-if-two-ranges-overlap
- return idRange.min <= other.max && other.min <= idRange.max;
- }
-
- /*
- * UTILITIES
- */
-
- private static long maxFromMinPow10(long minPow10) {
- if ((minPow10 % 100) != 0) {
- throw new IllegalArgumentException(minPow10 + " must at least ends with two zeroes");
- }
- int exp = 2;
- exp: for (int i = exp + 1; i < 10; i++) {
- if ((minPow10 % pow10(i)) != 0)
- break exp;
- exp++;
- }
-// System.out.println(exp);
-
- long max = minPow10 + pow10(exp) - 1;
- return max;
- }
-
- /** Power of 10. */
- private static long pow10(int exp) {
- if (exp == 0)
- return 1;
- else
- return 10 * pow10(exp - 1);
- }
-
- public static void main(String... args) {
- System.out.println(maxFromMinPow10(100));
- System.out.println(maxFromMinPow10(78500));
- System.out.println(maxFromMinPow10(716850000));
-
-// System.out.println(pow10(6));
-// System.out.println(maxFromMinPow10(12));
-// System.out.println(maxFromMinPow10(124));
-// System.out.println(maxFromMinPow10(99814565));
- }
-}