diff --git a/java/tatsuki/build.gradle b/java/tatsuki/build.gradle index 5a98cdc..ecf6f2e 100644 --- a/java/tatsuki/build.gradle +++ b/java/tatsuki/build.gradle @@ -16,7 +16,7 @@ dependencies { } java { - sourceCompatibility JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_17 withSourcesJar() toolchain { diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/BigBitFlagSet.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/BigBitFlagSet.java deleted file mode 100644 index 3229ab0..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/BigBitFlagSet.java +++ /dev/null @@ -1,76 +0,0 @@ -package fr.louisdevie.tatsuki; - -import java.math.BigInteger; -import java.util.Iterator; -import java.util.NoSuchElementException; - -public class BigBitFlagSet implements FlagSet { - public BigInteger empty() { - return BigInteger.ZERO; - } - - public BigInteger union(BigInteger first, BigInteger second) { - return first.or(second); - } - - public BigInteger intersection(BigInteger first, BigInteger second) { - return first.and(second); - } - - public BigInteger difference(BigInteger first, BigInteger second) { - return first.andNot(second); - } - - public boolean isSuperset(BigInteger first, BigInteger second) { - return first.and(second).equals(second); - } - - public Iterable enumerate(BigInteger flags) { - return new IterableBitFlags(flags); - } - - public BigInteger minimum(BigInteger flags) { - return BigInteger.ZERO; - } - - public BigInteger maximum(BigInteger flags) { - return BigInteger.ZERO; - } - - private record IterableBitFlags(BigInteger value) implements Iterable { - public Iterator iterator() { - return new BitFlagsIterator(this.value); - } - } - - private static class BitFlagsIterator implements Iterator { - private BigInteger value; - private BigInteger current; - - public BitFlagsIterator(BigInteger value) { - this.value = value; - this.current = BigInteger.ONE; - } - - public boolean hasNext() { - return !this.value.equals(BigInteger.ZERO); - } - - public BigInteger next() { - if (this.value.equals(BigInteger.ZERO)) { - throw new NoSuchElementException(); - } - - while (!this.value.testBit(0)) { - this.value = this.value.shiftRight(1); - this.current = this.current.shiftLeft(1); - } - - BigInteger element = this.current; - this.value = this.value.shiftRight(1); - this.current = this.current.shiftLeft(1); - - return element; - } - } -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/BitFlagSet.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/BitFlagSet.java deleted file mode 100644 index 0f1c388..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/BitFlagSet.java +++ /dev/null @@ -1,75 +0,0 @@ -package fr.louisdevie.tatsuki; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public class BitFlagSet implements FlagSet { - public Integer empty() { - return 0; - } - - public Integer union(Integer first, Integer second) { - return first | second; - } - - public Integer intersection(Integer first, Integer second) { - return first & second; - } - - public Integer difference(Integer first, Integer second) { - return first & ~second; - } - - public boolean isSuperset(Integer first, Integer second) { - return (first & second) == second; - } - - public Iterable enumerate(Integer flags) { - return new IterableBitFlags(flags); - } - - public Integer minimum(Integer flags) { - return 0; - } - - public Integer maximum(Integer flags) { - return 0; - } - - private record IterableBitFlags(int value) implements Iterable { - public Iterator iterator() { - return new BitFlagsIterator(this.value); - } - } - - private static class BitFlagsIterator implements Iterator { - private int value; - private int current; - - public BitFlagsIterator(int value) { - this.value = value; - this.current = 1; - } - - public boolean hasNext() { - return this.value != 0; - } - - public Integer next() { - if (this.value == 0) { - throw new NoSuchElementException(); - } - - while ((this.value & 1) == 0) { - this.value >>= 1; - this.current <<= 1; - } - - int element = this.current; - this.value >>= 1; - this.current <<= 1; - - return element; - } - } -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagDefinition.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagDefinition.java new file mode 100644 index 0000000..86d96fe --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagDefinition.java @@ -0,0 +1,75 @@ +package fr.louisdevie.tatsuki; + +import java.util.Optional; + +/** + * Represents a single flag defined in a {@link FlagGraph}. + * + * @param A set of this type of flags. + */ +public interface FlagDefinition { + /** + * The alias of the flag. + */ + Optional getAlias(); + + /** + * A set containing the value of the flag, or multiple values if it is a composed flag. + */ + S values(); + + /** + * Test if this flag and all its parents are present in the set. + * + * @param set A set of flags. + * @return {@code true} if the set includes this flags and its parents. + */ + boolean isIn(S set); + + /** + * Add this flag and all its parents to the set. + * + * @param set A set of flags. + * @return A new set of flags containing the flags from the {@code set}, this flag and its parents. + */ + S addTo(S set); + + /** + * Removes this flag and all its children from the set. + * + * @param set A set of flags. + * @return A new set of flags containing the flags from the {@code set} except this flag and its children. + */ + S removeFrom(S set); + + /** + * Adds or removes this flag from the set depending on the specified boolean value. + * If {@code value} is {@code true}, flags will be added so that {@link #isIn} returns {@code true.} + * If {@code value} is {@code false}, flags will be removed so that {@link #isIn} returns {@code false.} + * + * @param set A set of flags. + * @return A new set of flags. + */ + default S setIn(S set, boolean value) { + if (value) { + return this.addTo(set); + } else { + return this.removeFrom(set); + } + } + + /** + * Add this flag and all its parents to the set if they aren't already present, + * and removes this flag otherwise. + * + * @param set A set of flags. + * @return A new set of flags. + */ + default S toggle(S set) { + if (!this.isIn(set)) { + return this.addTo(set); + } else { + return this.removeFrom(set); + } + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagGraph.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagGraph.java new file mode 100644 index 0000000..fafa1c0 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagGraph.java @@ -0,0 +1,123 @@ +package fr.louisdevie.tatsuki; + +import java.util.Collection; +import java.util.Optional; +import java.util.Set; + +/** + * Represents a group of flags of type {@link V} and the relationships between + * them. + * + * @param The type of the flag values. + * @param The type used to contain the flags. + */ +public interface FlagGraph { + /** + * Returns the number of definitions in this graph. + */ + int size(); + + /** + * Returns {@code true} if this graph contains no definitions. + */ + boolean isEmpty(); + + /** + * Returns {@code true} if this graph contains a definition with the specified alias. + */ + boolean containsAlias(String alias); + + /** + * Returns {@code true} if this graph contains a definition with the specified value. + */ + boolean containsValue(V value); + + /** + * Returns {@code true} if the specified definition belongs to this graph. + */ + boolean containsDefinition(FlagDefinition definition); + + /** + * Returns the flag definition with the specified alias. + * + * @param alias The alias of the flag. + * + * @return An {@link Optional} of the corresponding definition, or an empty + * {@link Optional} if there is no definition with this alias. + */ + Optional> definitionNamed(String alias); + + /** + * Returns the flag definition with the specified value. + * + * @param value The base value of the flag. + * + * @return An {@link Optional} of the corresponding definition, or an empty + * {@link Optional} if there is no definition with this value. + */ + Optional> definitionOf(V value); + + /** + * Returns a {@link Set} view of the aliases defined in this graph. + */ + Set aliasSet(); + + /** + * Returns a {@link Set} view of the values defined in this graph. + */ + Set valueSet(); + + /** + * Returns a list of all the defined flags. + */ + Collection> definitions(); + + /** + * Creates a set of flags from a list of aliases. + */ + S named(String... aliases); + + /** + * Checks whether the first set of flags includes at least one of the flags + * from the second set. If there is no required flags, the result will always be `false`. + * A flag is considered to be part of the set only if all of its parents are + * present too. + * + * @param flags - A set of flags. + * @param required - The flags to search for in the first set. + */ + boolean hasAny(S flags, S required); + + /** + * Checks whether the first set of flags includes all the flags from the + * second set. If there is no required flags, the result will always be `true`. + * A flag is considered to be part of the set only if all of its parents are + * present too. + * + * @param flags - A set of flags. + * @param required - The flags to search for in the first set. + */ + boolean hasAll(S flags, S required); + + /** + * Filters a flag set so that it only contains the flags that were defined + * in this set. If a flags is missing some of its parents, it will not be + * included in the result. + * + * @param flags The set of flags to filter. + * @return A new set of flags. + * @see #maximum + */ + S minimum(S flags); + + /** + * Filters a flag set so that it only contains the flags that were defined + * in this set. If a flags is missing some of its parents, they will be + * added to the result. + * + * @param flags The set of flags to filter. + * @return A new set of flags. + * @see #minimum + */ + S maximum(S flags); +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagSet.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagSet.java deleted file mode 100644 index 2ec2b67..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagSet.java +++ /dev/null @@ -1,82 +0,0 @@ -package fr.louisdevie.tatsuki; - -/** - * Represents a group of flags of type {@link F} and the relationships between - * them. It also provides methods to use {@link S} as a set of those flags. - * - * @param The type of values in the set. - * @param The type to be used as a set. - */ -public interface FlagSet { - /** - * Creates an empty set of flags. - */ - S empty(); - - /** - * Computes the union of two sets of flags. - * - * @param first The first set of flags. - * @param second The second set of flags. - * @return A new set that contains the flags of both sets. - */ - S union(S first, S second); - - /** - * Computes the intersection of two set of flags. - * - * @param first The first set of flags. - * @param second The second set of flags. - * @return A new set that contains the flags that appear both in the first - * set and the second set. - */ - S intersection(S first, S second); - - /** - * Computes the difference of two set of flags. - * - * @param first The first set of flags. - * @param second The second set of flags (that will be subtracted from the - * first). - * @return A new set that contains the flags of the first set that do not - * appear in the second. - */ - S difference(S first, S second); - - /** - * Checks whether the first set of flags is a superset of the second. - * - * @param first The first set of flags. - * @param second The second set of flags. - */ - boolean isSuperset(S first, S second); - - /** - * Returns an iterable over the individual flags in a set. - * - * @param flags A set of flags. - */ - Iterable enumerate(S flags); - - /** - * Filters a flag set so that it only contains the flags that were defined - * in this set. If a flags is missing some of its parents, it will not be - * included in the result. - * - * @param flags The set of flags to filter. - * @return A new set of flags. - * @see #maximum - */ - S minimum(S flags); - - /** - * Filters a flag set so that it only contains the flags that were defined - * in this set. If a flags is missing some of its parents, they will be - * added to the result. - * - * @param flags The set of flags to filter. - * @return A new set of flags. - * @see #minimum - */ - S maximum(S flags); -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagSetBuilder.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagSetBuilder.java deleted file mode 100644 index 6302f87..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/FlagSetBuilder.java +++ /dev/null @@ -1,12 +0,0 @@ -package fr.louisdevie.tatsuki; - -import fr.louisdevie.tatsuki.builders.BitFlagSetBuilder; -import fr.louisdevie.tatsuki.builders.syntax.DefineFlag; -import fr.louisdevie.tatsuki.builders.syntax.SelectFlagSetType; - -public class FlagSetBuilder implements SelectFlagSetType { - public DefineFlag useBitFlags() { - return new BitFlagSetBuilder(); - } -} - diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/LongBitFlagSet.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/LongBitFlagSet.java deleted file mode 100644 index e13953e..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/LongBitFlagSet.java +++ /dev/null @@ -1,75 +0,0 @@ -package fr.louisdevie.tatsuki; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -public class LongBitFlagSet implements FlagSet { - public Long empty() { - return 0L; - } - - public Long union(Long first, Long second) { - return first | second; - } - - public Long intersection(Long first, Long second) { - return first & second; - } - - public Long difference(Long first, Long second) { - return first & ~second; - } - - public boolean isSuperset(Long first, Long second) { - return (first & second) == second; - } - - public Iterable enumerate(Long flags) { - return new IterableBitFlags(flags); - } - - public Long minimum(Long flags) { - return 0L; - } - - public Long maximum(Long flags) { - return 0L; - } - - private record IterableBitFlags(long value) implements Iterable { - public Iterator iterator() { - return new BitFlagsIterator(this.value); - } - } - - private static class BitFlagsIterator implements Iterator { - private long value; - private long current; - - public BitFlagsIterator(long value) { - this.value = value; - this.current = 1L; - } - - public boolean hasNext() { - return this.value != 0L; - } - - public Long next() { - if (this.value == 0L) { - throw new NoSuchElementException(); - } - - while ((this.value & 1L) == 0L) { - this.value >>= 1; - this.current <<= 1; - } - - long element = this.current; - this.value >>= 1; - this.current <<= 1; - - return element; - } - } -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BigBitFlagGraph.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BigBitFlagGraph.java new file mode 100644 index 0000000..75d6e78 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BigBitFlagGraph.java @@ -0,0 +1,88 @@ +package fr.louisdevie.tatsuki.bitflags; + +import fr.louisdevie.tatsuki.FlagGraph; +import fr.louisdevie.tatsuki.FlagDefinition; + +import java.math.BigInteger; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public class BigBitFlagGraph implements FlagGraph { + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsAlias(String alias) { + return false; + } + + @Override + public boolean containsValue(BigInteger value) { + return false; + } + + @Override + public boolean containsDefinition(FlagDefinition definition) { + return false; + } + + @Override + public Optional> definitionNamed(String alias) { + return Optional.empty(); + } + + @Override + public Optional> definitionOf(BigInteger value) { + return Optional.empty(); + } + + @Override + public Set aliasSet() { + return Set.of(); + } + + @Override + public Set valueSet() { + return Set.of(); + } + + @Override + public Collection> definitions() { + return List.of(); + } + + @Override + public BigInteger named(String... aliases) { + return null; + } + + @Override + public boolean hasAny(BigInteger flags, BigInteger required) { + return false; + } + + @Override + public boolean hasAll(BigInteger flags, BigInteger required) { + return false; + } + + @Override + public BigInteger minimum(BigInteger flags) { + return null; + } + + @Override + public BigInteger maximum(BigInteger flags) { + return null; + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BigBitFlagsIterator.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BigBitFlagsIterator.java new file mode 100644 index 0000000..d2e13e2 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BigBitFlagsIterator.java @@ -0,0 +1,36 @@ +package fr.louisdevie.tatsuki.bitflags; + +import java.math.BigInteger; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class BigBitFlagsIterator implements Iterator { + private BigInteger value; + private BigInteger current; + + public BigBitFlagsIterator(BigInteger value) { + this.value = value; + this.current = BigInteger.ONE; + } + + public boolean hasNext() { + return !this.value.equals(BigInteger.ZERO); + } + + public BigInteger next() { + if (this.value.equals(BigInteger.ZERO)) { + throw new NoSuchElementException(); + } + + while (!this.value.testBit(0)) { + this.value = this.value.shiftRight(1); + this.current = this.current.shiftLeft(1); + } + + BigInteger element = this.current; + this.value = this.value.shiftRight(1); + this.current = this.current.shiftLeft(1); + + return element; + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlagGraph.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlagGraph.java new file mode 100644 index 0000000..0209457 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlagGraph.java @@ -0,0 +1,86 @@ +package fr.louisdevie.tatsuki.bitflags; + +import fr.louisdevie.tatsuki.FlagGraph; +import fr.louisdevie.tatsuki.FlagDefinition; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public class BitFlagGraph implements FlagGraph { + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsAlias(String alias) { + return false; + } + + @Override + public boolean containsValue(Integer value) { + return false; + } + + @Override + public boolean containsDefinition(FlagDefinition definition) { + return false; + } + + @Override + public Optional> definitionNamed(String alias) { + return Optional.empty(); + } + + @Override + public Optional> definitionOf(Integer value) { + return Optional.empty(); + } + + @Override + public Set aliasSet() { + return Set.of(); + } + + @Override + public Set valueSet() { + return Set.of(); + } + + @Override + public Collection> definitions() { + return List.of(); + } + + @Override + public Integer named(String... aliases) { + return 0; + } + + @Override + public boolean hasAny(Integer flags, Integer required) { + return false; + } + + @Override + public boolean hasAll(Integer flags, Integer required) { + return false; + } + + @Override + public Integer minimum(Integer flags) { + return 0; + } + + @Override + public Integer maximum(Integer flags) { + return 0; + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlags.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlags.java new file mode 100644 index 0000000..4a90fc0 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlags.java @@ -0,0 +1,141 @@ +package fr.louisdevie.tatsuki.bitflags; + +import java.math.BigInteger; +import java.util.Iterator; + +public final class BitFlags { + /** + * Computes the union of two sets of bitflags. + * Any bits that are set in either of the inputs will be set in the result. + */ + public static int union(int first, int second) { + return first | second; + } + + /** + * Computes the union of two sets of bitflags. + * Any bits that are set in either of the inputs will be set in the result. + */ + public static long union(long first, long second) { + return first | second; + } + + /** + * Computes the union of two sets of bitflags. + * Any bits that are set in either of the inputs will be set in the result. + */ + public static BigInteger union(BigInteger first, BigInteger second) { + return first.or(second); + } + + /** + * Computes the intersection of two sets of bitflags. + * Only bits that are set in both of the inputs will be set in the result. + */ + public static int intersection(int first, int second) { + return first & second; + } + + /** + * Computes the intersection of two sets of bitflags. + * Only bits that are set in both of the inputs will be set in the result. + */ + public static long intersection(long first, long second) { + return first & second; + } + + /** + * Computes the intersection of two sets of bitflags. + * Only bits that are set in both of the inputs will be set in the result. + */ + public static BigInteger intersection(BigInteger first, BigInteger second) { + return first.and(second); + } + + /** + * Computes the difference between two sets of bitflags. + * Only bits that are set in the first input and not set in the second will be set in the result. + */ + public static int difference(int first, int second) { + return first & ~second; + } + + /** + * Computes the difference between two sets of bitflags. + * Only bits that are set in the first input and not set in the second will be set in the result. + */ + public static long difference(long first, long second) { + return first & ~second; + } + + /** + * Computes the difference between two sets of bitflags. + * Only bits that are set in the first input and not set in the second will be set in the result. + */ + public static BigInteger difference(BigInteger first, BigInteger second) { + return first.andNot(second); + } + + /** + * Tests if a set of bitflags is a superset of the other. + * Return `true` if every bit that is set in the second input is also set in the first. + */ + public static boolean isSuperset(int first, int second) { + return (first & second) == second; + } + + /** + * Tests if a set of bitflags is a superset of the other. + * Return `true` if every bit that is set in the second input is also set in the first. + */ + public static boolean isSuperset(long first, long second) { + return (first & second) == second; + } + + /** + * Tests if a set of bitflags is a superset of the other. + * Return `true` if every bit that is set in the second input is also set in the first. + */ + public static boolean isSuperset(BigInteger first, BigInteger second) { + return first.and(second).equals(second); + } + + /** + * Returns an iterable over the individual bits that are set. + */ + public static Iterable enumerate(int flags) { + return new IterableInteger(flags); + } + + private record IterableInteger(int value) implements Iterable { + public Iterator iterator() { + return new BitFlagsIterator(this.value); + } + } + + /** + * Returns an iterable over the individual bits that are set. + */ + public static Iterable enumerate(long flags) { + return new IterableLong(flags); + } + + private record IterableLong(long value) implements Iterable { + public Iterator iterator() { + return new LongBitFlagsIterator(this.value); + } + } + + /** + * Returns an iterable over the individual bits that are set. + */ + public static Iterable enumerate(BigInteger flags) { + return new IterableBigInteger(flags); + } + + private record IterableBigInteger(BigInteger value) implements Iterable { + public Iterator iterator() { + return new BigBitFlagsIterator(this.value); + } + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlagsIterator.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlagsIterator.java new file mode 100644 index 0000000..f2c59a4 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/BitFlagsIterator.java @@ -0,0 +1,35 @@ +package fr.louisdevie.tatsuki.bitflags; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class BitFlagsIterator implements Iterator { + private int value; + private int current; + + public BitFlagsIterator(int value) { + this.value = value; + this.current = 1; + } + + public boolean hasNext() { + return this.value != 0; + } + + public Integer next() { + if (this.value == 0) { + throw new NoSuchElementException(); + } + + while ((this.value & 1) == 0) { + this.value >>= 1; + this.current <<= 1; + } + + int element = this.current; + this.value >>= 1; + this.current <<= 1; + + return element; + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/LongBitFlagGraph.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/LongBitFlagGraph.java new file mode 100644 index 0000000..3d3c99c --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/LongBitFlagGraph.java @@ -0,0 +1,87 @@ +package fr.louisdevie.tatsuki.bitflags; + +import fr.louisdevie.tatsuki.FlagGraph; +import fr.louisdevie.tatsuki.FlagDefinition; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public class LongBitFlagGraph implements FlagGraph { + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsAlias(String alias) { + return false; + } + + @Override + public boolean containsValue(Long value) { + return false; + } + + @Override + public boolean containsDefinition(FlagDefinition definition) { + return false; + } + + @Override + public Optional> definitionNamed(String alias) { + return Optional.empty(); + } + + @Override + public Optional> definitionOf(Long value) { + return Optional.empty(); + } + + @Override + public Set aliasSet() { + return Set.of(); + } + + @Override + public Set valueSet() { + return Set.of(); + } + + @Override + public Collection> definitions() { + return List.of(); + } + + @Override + public Long named(String... aliases) { + return 0L; + } + + @Override + public boolean hasAny(Long flags, Long required) { + return false; + } + + @Override + public boolean hasAll(Long flags, Long required) { + return false; + } + + @Override + public Long minimum(Long flags) { + return 0L; + } + + @Override + public Long maximum(Long flags) { + return 0L; + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/LongBitFlagsIterator.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/LongBitFlagsIterator.java new file mode 100644 index 0000000..93e4272 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/bitflags/LongBitFlagsIterator.java @@ -0,0 +1,36 @@ +package fr.louisdevie.tatsuki.bitflags; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LongBitFlagsIterator implements Iterator { + private long value; + private long current; + + public LongBitFlagsIterator(long value) { + this.value = value; + this.current = 1L; + } + + public boolean hasNext() { + return this.value != 0L; + } + + public Long next() { + if (this.value == 0L) { + throw new NoSuchElementException(); + } + + while ((this.value & 1L) == 0L) { + this.value >>= 1; + this.current <<= 1; + } + + long element = this.current; + this.value >>= 1; + this.current <<= 1; + + return element; + } +} + diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/BitFlagSetBuilder.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/BitFlagSetBuilder.java deleted file mode 100644 index e59dfeb..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/BitFlagSetBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.louisdevie.tatsuki.builders; - -import fr.louisdevie.tatsuki.BitFlagSet; -import fr.louisdevie.tatsuki.builders.syntax.DefineFlag; -import fr.louisdevie.tatsuki.builders.syntax.SetValueOrCompose; - -public class BitFlagSetBuilder implements DefineFlag { - public SetValueOrCompose define(String name) { - return null; - } - - public BitFlagSet build() { - return new BitFlagSet(); - } -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/AsOrComposeValues.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/AsOrComposeValues.java new file mode 100644 index 0000000..ea50041 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/AsOrComposeValues.java @@ -0,0 +1,29 @@ +package fr.louisdevie.tatsuki.builders.syntax; + + +public interface AsOrComposeValues { + /** + * Give the flag an alias to reference it elsewhere. + * + * @param alias An alias for the flag. + * + * @throws NullPointerException when {@code alias} is {@code null}. + * @throws IllegalArgumentException when two flags are given the same alias. + */ + DefineOrComposeValues as(String alias); + + /** + * Combine multiple flags together. + * + * @param values The values of the flags to combine. + */ + @SuppressWarnings("unchecked") + AsOrComposeValues composeValues(V... values); + + /** + * Combine multiple flags together. + * + * @param aliases The aliases of the flags to combine. + */ + AsOrComposeValues compose(String... aliases); +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/AsOrRequiresOrDefineOrComposeValues.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/AsOrRequiresOrDefineOrComposeValues.java new file mode 100644 index 0000000..f075df4 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/AsOrRequiresOrDefineOrComposeValues.java @@ -0,0 +1,13 @@ +package fr.louisdevie.tatsuki.builders.syntax; + +public interface AsOrRequiresOrDefineOrComposeValues extends RequiresOrDefineOrComposeValues { + /** + * Give the flag an alias to reference it elsewhere. + * + * @param alias An alias for the flag. + * + * @throws NullPointerException when {@code alias} is {@code null}. + * @throws IllegalArgumentException when two flags are given the same alias. + */ + RequiresOrDefineOrComposeValues as(String alias); +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/DefineFlag.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/DefineFlag.java deleted file mode 100644 index 09eb8b0..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/DefineFlag.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.louisdevie.tatsuki.builders.syntax; - -import fr.louisdevie.tatsuki.BitFlagSet; - -public interface DefineFlag { - SetValueOrCompose define(String name); - - X build(); -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/DefineOrComposeValues.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/DefineOrComposeValues.java new file mode 100644 index 0000000..4ebf916 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/DefineOrComposeValues.java @@ -0,0 +1,29 @@ +package fr.louisdevie.tatsuki.builders.syntax; + + +public interface DefineOrComposeValues extends Root { + /** + * Define a flag with the given value. + * + * @param value The value of the flag. + * @throws NullPointerException when {@code value} is {@code null}. + * @throws IllegalArgumentException when two flags are defined with the same value, or when {@code value} is not an + * appropriate value for the type of flag set you are building. + */ + AsOrRequiresOrDefineOrComposeValues defineValue(V value); + + /** + * Combine multiple flags together. + * + * @param aliases The aliases of the flags to combine. + */ + AsOrComposeValues compose(String... aliases); + + /** + * Combine multiple flags together. + * + * @param values The values of the flags to combine. + */ + @SuppressWarnings("unchecked") + AsOrComposeValues composeValues(V... values); +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/RequireParentsOrDefineFlag.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/RequireParentsOrDefineFlag.java deleted file mode 100644 index 085bb40..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/RequireParentsOrDefineFlag.java +++ /dev/null @@ -1,5 +0,0 @@ -package fr.louisdevie.tatsuki.builders.syntax; - -public interface RequireParentsOrDefineFlag extends DefineFlag { - DefineFlag requires(String ...flags); -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/RequiresOrDefineOrComposeValues.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/RequiresOrDefineOrComposeValues.java new file mode 100644 index 0000000..eb87f68 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/RequiresOrDefineOrComposeValues.java @@ -0,0 +1,16 @@ +package fr.louisdevie.tatsuki.builders.syntax; + +public interface RequiresOrDefineOrComposeValues extends DefineOrComposeValues { + /** + * Define the "parents" of this flag. A flag is not considered enabled unless all its parents are also enabled. + * @param aliases The names of the required flags. + */ + RequiresOrDefineOrComposeValues requires(String... aliases); + + /** + * Define the "parents" of this flag. A flag is not considered enabled unless all its parents are also enabled. + * @param values The values of the required flags. + */ + @SuppressWarnings("unchecked") + RequiresOrDefineOrComposeValues requiresValues(V... values); +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/Root.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/Root.java new file mode 100644 index 0000000..badf502 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/Root.java @@ -0,0 +1,12 @@ +package fr.louisdevie.tatsuki.builders.syntax; + +/** + * Builder syntax root. + * @param The result type produced by the builder. + */ +public interface Root { + /** + * Build a flag set with the flags previously defined. + */ + R build(); +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/SelectFlagSetType.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/SelectFlagSetType.java deleted file mode 100644 index d304705..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/SelectFlagSetType.java +++ /dev/null @@ -1,7 +0,0 @@ -package fr.louisdevie.tatsuki.builders.syntax; - -import fr.louisdevie.tatsuki.BitFlagSet; - -public interface SelectFlagSetType { - DefineFlag useBitFlags(); -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/SetValueOrCompose.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/SetValueOrCompose.java deleted file mode 100644 index e1c4a2d..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/builders/syntax/SetValueOrCompose.java +++ /dev/null @@ -1,7 +0,0 @@ -package fr.louisdevie.tatsuki.builders.syntax; - -public interface SetValueOrCompose { - RequireParentsOrDefineFlag withValue(int value); - - DefineFlag compose(String ...flags); -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/CollectionFlagGraphBuilder.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/CollectionFlagGraphBuilder.java new file mode 100644 index 0000000..c129e06 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/CollectionFlagGraphBuilder.java @@ -0,0 +1,27 @@ +package fr.louisdevie.tatsuki.collections; + +import fr.louisdevie.tatsuki.builders.syntax.AsOrComposeValues; +import fr.louisdevie.tatsuki.builders.syntax.AsOrRequiresOrDefineOrComposeValues; +import fr.louisdevie.tatsuki.builders.syntax.DefineOrComposeValues; + +class CollectionFlagGraphBuilder implements DefineOrComposeValues> { + @Override + public AsOrRequiresOrDefineOrComposeValues> defineValue(E value) { + return null; + } + + @Override + public AsOrComposeValues> compose(String... aliases) { + return null; + } + + @Override + public AsOrComposeValues> composeValues(E... values) { + return null; + } + + @Override + public SetFlagGraph build() { + return null; + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/SetFlagDefinition.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/SetFlagDefinition.java new file mode 100644 index 0000000..4295098 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/SetFlagDefinition.java @@ -0,0 +1,33 @@ +package fr.louisdevie.tatsuki.collections; + +import fr.louisdevie.tatsuki.FlagDefinition; + +import java.util.Optional; +import java.util.Set; + +class SetFlagDefinition implements FlagDefinition> { + @Override + public Optional getAlias() { + return Optional.empty(); + } + + @Override + public Set values() { + return Set.of(); + } + + @Override + public boolean isIn(Set set) { + return false; + } + + @Override + public Set addTo(Set set) { + return Set.of(); + } + + @Override + public Set removeFrom(Set set) { + return Set.of(); + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/SetFlagGraph.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/SetFlagGraph.java new file mode 100644 index 0000000..a520971 --- /dev/null +++ b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/collections/SetFlagGraph.java @@ -0,0 +1,95 @@ +package fr.louisdevie.tatsuki.collections; + +import fr.louisdevie.tatsuki.FlagGraph; +import fr.louisdevie.tatsuki.builders.syntax.DefineOrComposeValues; +import fr.louisdevie.tatsuki.FlagDefinition; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +public class SetFlagGraph implements FlagGraph> { + public static DefineOrComposeValues> builder() { + return new CollectionFlagGraphBuilder<>(); + } + + SetFlagGraph(Collection> c) { + + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean containsAlias(String alias) { + return false; + } + + @Override + public boolean containsValue(E value) { + return false; + } + + @Override + public boolean containsDefinition(FlagDefinition> definition) { + return false; + } + + @Override + public Optional>> definitionNamed(String alias) { + return Optional.empty(); + } + + @Override + public Optional>> definitionOf(E value) { + return Optional.empty(); + } + + @Override + public Set aliasSet() { + return Set.of(); + } + + @Override + public Set valueSet() { + return Set.of(); + } + + @Override + public Collection>> definitions() { + return List.of(); + } + + @Override + public Set named(String... aliases) { + return Set.of(); + } + + @Override + public boolean hasAny(Set flags, Set required) { + return false; + } + + @Override + public boolean hasAll(Set flags, Set required) { + return false; + } + + @Override + public Set minimum(Set flags) { + return Set.of(); + } + + @Override + public Set maximum(Set flags) { + return Set.of(); + } +} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/definition/FlagDefinition.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/definition/FlagDefinition.java deleted file mode 100644 index 2dc9aed..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/definition/FlagDefinition.java +++ /dev/null @@ -1,4 +0,0 @@ -package fr.louisdevie.tatsuki.definition; - -interface FlagDefinition { -} diff --git a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/definition/FlagDefinitionMap.java b/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/definition/FlagDefinitionMap.java deleted file mode 100644 index 11f2402..0000000 --- a/java/tatsuki/src/main/java/fr/louisdevie/tatsuki/definition/FlagDefinitionMap.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.louisdevie.tatsuki.definition; - -import java.util.List; -import java.util.Map; - -public class FlagDefinitionMap { - private Map> _container; - -} diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BigBitFlagSetTests.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BigBitFlagGraphTests.java similarity index 85% rename from java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BigBitFlagSetTests.java rename to java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BigBitFlagGraphTests.java index ee5f0b0..df0e75c 100644 --- a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BigBitFlagSetTests.java +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BigBitFlagGraphTests.java @@ -1,5 +1,6 @@ package fr.louisdevie.tatsuki; +import fr.louisdevie.tatsuki.bitflags.BigBitFlagGraph; import org.junit.jupiter.api.Test; import java.math.BigInteger; @@ -8,21 +9,21 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.*; -public class BigBitFlagSetTests { - private static BigInteger big(int value) { +public class BigBitFlagGraphTests { + /*private static BigInteger big(int value) { return BigInteger.valueOf(value); } @Test public void empty() { - var flags = new BigBitFlagSet(); + var flags = new BigBitFlagGraph(); assertEquals(big(0), flags.empty()); } @Test public void union() { - final var flags = new BigBitFlagSet(); + final var flags = new BigBitFlagGraph(); assertEquals(big(0), flags.union(big(0), big(0))); assertEquals(big(1), flags.union(big(1), big(0))); @@ -33,7 +34,7 @@ public class BigBitFlagSetTests { @Test public void difference() { - var flags = new BigBitFlagSet(); + var flags = new BigBitFlagGraph(); assertEquals(big(0), flags.difference(big(0), big(0))); assertEquals(big(1), flags.difference(big(1), big(0))); @@ -44,7 +45,7 @@ public class BigBitFlagSetTests { @Test public void intersection() { - var flags = new BigBitFlagSet(); + var flags = new BigBitFlagGraph(); assertEquals(big(0), flags.intersection(big(0), big(0))); assertEquals(big(0), flags.intersection(big(1), big(0))); @@ -56,7 +57,7 @@ public class BigBitFlagSetTests { @Test public void isSuperset() { - var flags = new BigBitFlagSet(); + var flags = new BigBitFlagGraph(); assertTrue(flags.isSuperset(big(0), big(0))); assertTrue(flags.isSuperset(big(3), big(0))); @@ -68,7 +69,7 @@ public class BigBitFlagSetTests { @Test public void enumerate() { - var flags = new BigBitFlagSet(); + var flags = new BigBitFlagGraph(); assertIterableEquals(List.of(), flags.enumerate(big(0))); assertIterableEquals(List.of(big(1)), flags.enumerate(big(1))); @@ -76,5 +77,5 @@ public class BigBitFlagSetTests { assertIterableEquals(List.of(big(1), big(2)), flags.enumerate(big(3))); assertIterableEquals(List.of(big(1), big(2), big(8)), flags.enumerate(big(11))); assertIterableEquals(List.of(big(4), big(32), big(64)), flags.enumerate(big(100))); - } + }*/ } diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BitFlagSetTests.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BitFlagGraphTests.java similarity index 84% rename from java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BitFlagSetTests.java rename to java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BitFlagGraphTests.java index 053978b..e9bbf97 100644 --- a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BitFlagSetTests.java +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/BitFlagGraphTests.java @@ -1,5 +1,6 @@ package fr.louisdevie.tatsuki; +import fr.louisdevie.tatsuki.bitflags.BitFlagGraph; import org.junit.jupiter.api.Test; import java.util.List; @@ -7,17 +8,17 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.*; -public class BitFlagSetTests { - @Test +public class BitFlagGraphTests { + /*@Test public void empty() { - var flags = new BitFlagSet(); + var flags = new BitFlagGraph(); assertEquals(0, flags.empty()); } @Test public void union() { - final var flags = new BitFlagSet(); + final var flags = new BitFlagGraph(); assertEquals(0, flags.union(0, 0)); assertEquals(1, flags.union(1, 0)); @@ -28,7 +29,7 @@ public class BitFlagSetTests { @Test public void difference() { - var flags = new BitFlagSet(); + var flags = new BitFlagGraph(); assertEquals(0, flags.difference(0, 0)); assertEquals(1, flags.difference(1, 0)); @@ -39,7 +40,7 @@ public class BitFlagSetTests { @Test public void intersection() { - var flags = new BitFlagSet(); + var flags = new BitFlagGraph(); assertEquals(0, flags.intersection(0, 0)); assertEquals(0, flags.intersection(1, 0)); @@ -51,7 +52,7 @@ public class BitFlagSetTests { @Test public void isSuperset() { - var flags = new BitFlagSet(); + var flags = new BitFlagGraph(); assertTrue(flags.isSuperset(0, 0)); assertTrue(flags.isSuperset(3, 0)); @@ -63,7 +64,7 @@ public class BitFlagSetTests { @Test public void enumerate() { - var flags = new BitFlagSet(); + var flags = new BitFlagGraph(); assertIterableEquals(List.of(), flags.enumerate(0)); assertIterableEquals(List.of(1), flags.enumerate(1)); @@ -71,5 +72,5 @@ public class BitFlagSetTests { assertIterableEquals(List.of(1, 2), flags.enumerate(3)); assertIterableEquals(List.of(1, 2, 8), flags.enumerate(11)); assertIterableEquals(List.of(4, 32, 64), flags.enumerate(100)); - } + }*/ } diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/LongBitFlagSetTests.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/LongBitFlagGraphTests.java similarity index 83% rename from java/tatsuki/src/test/java/fr/louisdevie/tatsuki/LongBitFlagSetTests.java rename to java/tatsuki/src/test/java/fr/louisdevie/tatsuki/LongBitFlagGraphTests.java index 27c92ea..6edab57 100644 --- a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/LongBitFlagSetTests.java +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/LongBitFlagGraphTests.java @@ -1,5 +1,6 @@ package fr.louisdevie.tatsuki; +import fr.louisdevie.tatsuki.bitflags.LongBitFlagGraph; import org.junit.jupiter.api.Test; import java.util.List; @@ -7,17 +8,17 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.*; -public class LongBitFlagSetTests { - @Test +public class LongBitFlagGraphTests { + /*@Test public void empty() { - var flags = new LongBitFlagSet(); + var flags = new LongBitFlagGraph(); assertEquals(0L, flags.empty()); } @Test public void union() { - final var flags = new LongBitFlagSet(); + final var flags = new LongBitFlagGraph(); assertEquals(0L, flags.union(0L, 0L)); assertEquals(1L, flags.union(1L, 0L)); @@ -28,7 +29,7 @@ public class LongBitFlagSetTests { @Test public void difference() { - var flags = new LongBitFlagSet(); + var flags = new LongBitFlagGraph(); assertEquals(0L, flags.difference(0L, 0L)); assertEquals(1L, flags.difference(1L, 0L)); @@ -39,7 +40,7 @@ public class LongBitFlagSetTests { @Test public void intersection() { - var flags = new LongBitFlagSet(); + var flags = new LongBitFlagGraph(); assertEquals(0L, flags.intersection(0L, 0L)); assertEquals(0L, flags.intersection(1L, 0L)); @@ -51,7 +52,7 @@ public class LongBitFlagSetTests { @Test public void isSuperset() { - var flags = new LongBitFlagSet(); + var flags = new LongBitFlagGraph(); assertTrue(flags.isSuperset(0L, 0L)); assertTrue(flags.isSuperset(3L, 0L)); @@ -63,7 +64,7 @@ public class LongBitFlagSetTests { @Test public void enumerate() { - var flags = new LongBitFlagSet(); + var flags = new LongBitFlagGraph(); assertIterableEquals(List.of(), flags.enumerate(0L)); assertIterableEquals(List.of(1L), flags.enumerate(1L)); @@ -71,5 +72,5 @@ public class LongBitFlagSetTests { assertIterableEquals(List.of(1L, 2L), flags.enumerate(3L)); assertIterableEquals(List.of(1L, 2L, 8L), flags.enumerate(11L)); assertIterableEquals(List.of(4L, 32L, 64L), flags.enumerate(100L)); - } + }*/ } diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/bitflags/BitFlagsTests.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/bitflags/BitFlagsTests.java new file mode 100644 index 0000000..db21f1d --- /dev/null +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/bitflags/BitFlagsTests.java @@ -0,0 +1,122 @@ +package fr.louisdevie.tatsuki.bitflags; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static fr.louisdevie.tatsuki.testing.Assertions.assertYields; +import static fr.louisdevie.tatsuki.testing.Factory.big; +import static org.junit.jupiter.api.Assertions.*; + +public class BitFlagsTests { + @Test + public void union() { + assertEquals(0, BitFlags.union(0, 0)); + assertEquals(1, BitFlags.union(1, 0)); + assertEquals(2, BitFlags.union(0, 2)); + assertEquals(3, BitFlags.union(1, 2)); + assertEquals(7, BitFlags.union(3, 6)); + + assertEquals(0L, BitFlags.union(0L, 0L)); + assertEquals(1L, BitFlags.union(1L, 0L)); + assertEquals(2L, BitFlags.union(0L, 2L)); + assertEquals(3L, BitFlags.union(1L, 2L)); + assertEquals(7L, BitFlags.union(3L, 6L)); + + assertEquals(big(0), BitFlags.union(big(0), big(0))); + assertEquals(big(1), BitFlags.union(big(1), big(0))); + assertEquals(big(2), BitFlags.union(big(0), big(2))); + assertEquals(big(3), BitFlags.union(big(1), big(2))); + assertEquals(big(7), BitFlags.union(big(3), big(6))); + } + + @Test + public void difference() { + assertEquals(0, BitFlags.difference(0, 0)); + assertEquals(1, BitFlags.difference(1, 0)); + assertEquals(1, BitFlags.difference(3, 6)); + assertEquals(4, BitFlags.difference(6, 3)); + assertEquals(8, BitFlags.difference(8, 17)); + + assertEquals(0L, BitFlags.difference(0L, 0L)); + assertEquals(1L, BitFlags.difference(1L, 0L)); + assertEquals(1L, BitFlags.difference(3L, 6L)); + assertEquals(4L, BitFlags.difference(6L, 3L)); + assertEquals(8L, BitFlags.difference(8L, 17L)); + + assertEquals(big(0), BitFlags.difference(big(0), big(0))); + assertEquals(big(1), BitFlags.difference(big(1), big(0))); + assertEquals(big(1), BitFlags.difference(big(3), big(6))); + assertEquals(big(4), BitFlags.difference(big(6), big(3))); + assertEquals(big(8), BitFlags.difference(big(8), big(17))); + } + + @Test + public void intersection() { + assertEquals(0, BitFlags.intersection(0, 0)); + assertEquals(0, BitFlags.intersection(1, 0)); + assertEquals(0, BitFlags.intersection(1, 2)); + assertEquals(1, BitFlags.intersection(1, 3)); + assertEquals(1, BitFlags.intersection(11, 5)); + assertEquals(3, BitFlags.intersection(11, 7)); + + assertEquals(0L, BitFlags.intersection(0L, 0L)); + assertEquals(0L, BitFlags.intersection(1L, 0L)); + assertEquals(0L, BitFlags.intersection(1L, 2L)); + assertEquals(1L, BitFlags.intersection(1L, 3L)); + assertEquals(1L, BitFlags.intersection(11L, 5L)); + assertEquals(3L, BitFlags.intersection(11L, 7L)); + + assertEquals(big(0), BitFlags.intersection(big(0), big(0))); + assertEquals(big(0), BitFlags.intersection(big(1), big(0))); + assertEquals(big(0), BitFlags.intersection(big(1), big(2))); + assertEquals(big(1), BitFlags.intersection(big(1), big(3))); + assertEquals(big(1), BitFlags.intersection(big(11), big(5))); + assertEquals(big(3), BitFlags.intersection(big(11), big(7))); + } + + @Test + public void isSuperset() { + assertTrue(BitFlags.isSuperset(0, 0)); + assertTrue(BitFlags.isSuperset(3, 0)); + assertTrue(BitFlags.isSuperset(3, 1)); + assertTrue(BitFlags.isSuperset(3, 3)); + assertFalse(BitFlags.isSuperset(0, 3)); + assertFalse(BitFlags.isSuperset(8, 4)); + + assertTrue(BitFlags.isSuperset(0L, 0L)); + assertTrue(BitFlags.isSuperset(3L, 0L)); + assertTrue(BitFlags.isSuperset(3L, 1L)); + assertTrue(BitFlags.isSuperset(3L, 3L)); + assertFalse(BitFlags.isSuperset(0L, 3L)); + assertFalse(BitFlags.isSuperset(8L, 4L)); + + assertTrue(BitFlags.isSuperset(big(0), big(0))); + assertTrue(BitFlags.isSuperset(big(3), big(0))); + assertTrue(BitFlags.isSuperset(big(3), big(1))); + assertTrue(BitFlags.isSuperset(big(3), big(3))); + assertFalse(BitFlags.isSuperset(big(0), big(3))); + assertFalse(BitFlags.isSuperset(big(8), big(4))); + } + + @Test + public void enumerate() { + assertYields(List.of(), BitFlags.enumerate(0)); + assertYields(List.of(1), BitFlags.enumerate(1)); + assertYields(List.of(2), BitFlags.enumerate(2)); + assertYields(List.of(1, 2), BitFlags.enumerate(3)); + assertYields(List.of(4, 32, 64), BitFlags.enumerate(100)); + + assertYields(List.of(), BitFlags.enumerate(0L)); + assertYields(List.of(1L), BitFlags.enumerate(1L)); + assertYields(List.of(2L), BitFlags.enumerate(2L)); + assertYields(List.of(1L, 2L), BitFlags.enumerate(3L)); + assertYields(List.of(4L, 32L, 64L), BitFlags.enumerate(100L)); + + assertYields(List.of(), BitFlags.enumerate(big(0))); + assertYields(List.of(big(1)), BitFlags.enumerate(big(1))); + assertYields(List.of(big(2)), BitFlags.enumerate(big(2))); + assertYields(List.of(big(1), big(2)), BitFlags.enumerate(big(3))); + assertYields(List.of(big(4), big(32), big(64)), BitFlags.enumerate(big(100))); + } +} diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/collections/CollectionFlagGraphTests.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/collections/CollectionFlagGraphTests.java new file mode 100644 index 0000000..2a55d5e --- /dev/null +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/collections/CollectionFlagGraphTests.java @@ -0,0 +1,85 @@ +package fr.louisdevie.tatsuki.collections; + +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +public class CollectionFlagGraphTests { + @Test + public void named() { + final var flags = SetFlagGraph.builder() + .defineValue(12).as("a") + .defineValue(45).as("b") + .defineValue(78).as("c") + .compose("a", "b").as("ab") + .build(); + + assertEquals(Set.of(), flags.named()) ; + assertEquals(Set.of(12), flags.named("a")) ; + assertEquals(Set.of(12, 45, 78), flags.named("ab", "c")) ; + } + + @Test + public void hasAny() { + final var flags = SetFlagGraph.builder() + .defineValue(12) + .defineValue(45).requiresValues(12) + .defineValue(78) + .build(); + + assertFalse(flags.hasAny(Set.of(), Set.of())); + assertFalse(flags.hasAny(Set.of(12, 45, 78), Set.of())); + assertTrue(flags.hasAny(Set.of(12, 45, 78), Set.of(12))); + assertTrue(flags.hasAny(Set.of(12), Set.of(12, 78))); + assertFalse(flags.hasAny(Set.of(45, 78), Set.of(45))); + } + + @Test + public void hasAll() { + final var flags = SetFlagGraph.builder() + .defineValue(12) + .defineValue(45).requiresValues(12) + .defineValue(78) + .build(); + + assertTrue(flags.hasAll(Set.of(), Set.of())); + assertTrue(flags.hasAll(Set.of(12, 45, 78), Set.of())); + assertTrue(flags.hasAll(Set.of(12, 45, 78), Set.of(12))); + assertFalse(flags.hasAll(Set.of(12), Set.of(12, 78))); + assertFalse(flags.hasAll(Set.of(45, 78), Set.of(45))); + } + + @Test + public void maximum() { + final var flags = SetFlagGraph.builder() + .defineValue(12) + .defineValue(45).requiresValues(12) + .defineValue(78).requiresValues(45) + .build(); + + assertEquals(Set.of(), flags.maximum(Set.of())) ; + assertEquals(Set.of(12), flags.maximum(Set.of(12))) ; + assertEquals(Set.of(12, 45), flags.maximum(Set.of(45))) ; + assertEquals(Set.of(12, 45, 78), flags.maximum(Set.of(78))) ; + assertEquals(Set.of(), flags.maximum(Set.of(99))) ; + } + + @Test + public void minimum() { + final var flags = SetFlagGraph.builder() + .defineValue(12) + .defineValue(45).requiresValues(12) + .defineValue(78).requiresValues(45) + .build(); + + assertEquals(Set.of(), flags.minimum(Set.of())) ; + assertEquals(Set.of(12), flags.minimum(Set.of(12))) ; + assertEquals(Set.of(), flags.minimum(Set.of(45))) ; + assertEquals(Set.of(12, 45), flags.minimum(Set.of(12, 45))) ; + assertEquals(Set.of(12), flags.minimum(Set.of(12, 78))) ; + assertEquals(Set.of(12, 45, 78), flags.minimum(Set.of(12, 45, 78))) ; + assertEquals(Set.of(), flags.minimum(Set.of(99))) ; + } +} diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/testing/Assertions.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/testing/Assertions.java new file mode 100644 index 0000000..7060615 --- /dev/null +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/testing/Assertions.java @@ -0,0 +1,61 @@ +package fr.louisdevie.tatsuki.testing; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.fail; + +public class Assertions { + public static void assertYields(List expected, Iterable actual) { + Queue remaining = new ArrayDeque<>(expected); + for (Object actualElement : actual) { + if (remaining.isEmpty()) { + fail(String.format("Iterable yielded <%s> (no more elements were expected)", actualElement.toString())); + } + Object expectedElement = remaining.poll(); + if (!expectedElement.equals(actualElement)) { + fail(String.format("Iterable yielded <%s> (expected <%s>)", actualElement.toString(), expectedElement.toString())); + } + } + if (!remaining.isEmpty()) { + fail( + "Iterable did not yield " + + remaining.stream() + .map(obj -> String.format("<%s>", obj.toString())) + .collect(Collectors.joining(", ")) + ); + } + } + + public static void assertYieldsUnordered(List expected, Iterable actual) { + List remaining = new ArrayList<>(expected); + for (Object actualElement : actual) { + int i = remaining.indexOf(actualElement); + if (i == -1) { + String expectation; + if (remaining.isEmpty()) { + expectation = "no more elements were expected"; + } else { + expectation = "expected one of " + + remaining.stream() + .map(obj -> String.format("<%s>", obj.toString())) + .collect(Collectors.joining(", ")); + } + fail(String.format("Iterable yielded <%s> (%s)", actualElement.toString(), expectation)); + } else { + remaining.remove(i); + } + } + if (!remaining.isEmpty()) { + fail( + "Iterable did not yield " + + remaining.stream() + .map(obj -> String.format("<%s>", obj.toString())) + .collect(Collectors.joining(", ")) + ); + } + } +} diff --git a/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/testing/Factory.java b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/testing/Factory.java new file mode 100644 index 0000000..8c6ec86 --- /dev/null +++ b/java/tatsuki/src/test/java/fr/louisdevie/tatsuki/testing/Factory.java @@ -0,0 +1,9 @@ +package fr.louisdevie.tatsuki.testing; + +import java.math.BigInteger; + +public class Factory { + public static BigInteger big(int value) { + return BigInteger.valueOf(value); + } +}