diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-10-16 06:11:39 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2018-10-16 06:11:39 -0300 |
| commit | d2be5b73d7a5653ad5c8273c17284346baa6f1c7 (patch) | |
| tree | 9d3c6adb193f53588bd5d004fdf80c0381685351 /base/src/main | |
| parent | 0308029629a12711b849ea7765639b9b1f9e03d2 (diff) | |
| parent | d1d01769e7c55f7f62dc01cadf420d5f63424584 (diff) | |
Merge branch 'master' of github.com:bculkin2442/bjc-utils2
Diffstat (limited to 'base/src/main')
26 files changed, 1193 insertions, 532 deletions
diff --git a/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java b/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java index 3a03d18..108f90b 100644 --- a/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java +++ b/base/src/main/java/bjc/utils/cli/objects/DefineCLI.java @@ -2,7 +2,6 @@ package bjc.utils.cli.objects; import bjc.utils.funcutils.StringUtils; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; diff --git a/base/src/main/java/bjc/utils/cli/objects/DelimSplitterCLI.java b/base/src/main/java/bjc/utils/cli/objects/DelimSplitterCLI.java index 8b27ab7..9bf6ee6 100644 --- a/base/src/main/java/bjc/utils/cli/objects/DelimSplitterCLI.java +++ b/base/src/main/java/bjc/utils/cli/objects/DelimSplitterCLI.java @@ -3,7 +3,6 @@ package bjc.utils.cli.objects; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; diff --git a/base/src/main/java/bjc/utils/components/MemoryComponentRepository.java b/base/src/main/java/bjc/utils/components/MemoryComponentRepository.java index 658aaa1..a4b8dda 100644 --- a/base/src/main/java/bjc/utils/components/MemoryComponentRepository.java +++ b/base/src/main/java/bjc/utils/components/MemoryComponentRepository.java @@ -2,21 +2,44 @@ package bjc.utils.components; import bjc.utils.funcdata.IMap; -public class MemoryComponentRepository<ComponentType extends IDescribedComponent> implements IComponentRepository<ComponentType> { +/** + * A repository of components stored in memory. + * + * @author bjculkin + * + * @param <ComponentType> + */ +public class MemoryComponentRepository<ComponentType extends IDescribedComponent> + implements IComponentRepository<ComponentType> { private final IMap<String, ComponentType> repo; private final String source; + /** + * Create a new memory component repository. + * + * @param repo + * The set of components to use. + */ public MemoryComponentRepository(IMap<String, ComponentType> repo) { this(repo, "memory"); } + /** + * Create a new memory component repository. + * + * @param repo + * The set of components to use. + * @param source + * Where the components came from. + */ public MemoryComponentRepository(IMap<String, ComponentType> repo, String source) { this.repo = repo; this.source = source; } + @Override public IMap<String, ComponentType> getAll() { return repo; } diff --git a/base/src/main/java/bjc/utils/data/CircularIterator.java b/base/src/main/java/bjc/utils/data/CircularIterator.java index 4558b63..9af4d87 100644 --- a/base/src/main/java/bjc/utils/data/CircularIterator.java +++ b/base/src/main/java/bjc/utils/data/CircularIterator.java @@ -8,7 +8,7 @@ import java.util.Iterator; * @author EVE * * @param <E> - * The type of the iterable. + * The type of the iterable. */ public class CircularIterator<E> implements Iterator<E> { /* The iterable, and our current iterator into it. */ @@ -28,11 +28,11 @@ public class CircularIterator<E> implements Iterator<E> { * Create a new circular iterator. * * @param src - * The iterable to iterate from. + * The iterable to iterate from. * * @param circ - * Should we actually do circular iteration, or just repeat the - * terminal element? + * Should we actually do circular iteration, or just + * repeat the terminal element? */ public CircularIterator(final Iterable<E> src, final boolean circ) { source = src; @@ -45,7 +45,7 @@ public class CircularIterator<E> implements Iterator<E> { * Create a new circular iterator that does actual circular iteration. * * @param src - * The iterable to iterate from. + * The iterable to iterate from. */ public CircularIterator(final Iterable<E> src) { this(src, true); @@ -59,11 +59,12 @@ public class CircularIterator<E> implements Iterator<E> { @Override public E next() { - if(!curr.hasNext()) { - if(doCircle) { - curr = source.iterator(); - } else + if (!curr.hasNext()) { + if (!doCircle) { return curElm; + } + + curr = source.iterator(); } curElm = curr.next(); diff --git a/base/src/main/java/bjc/utils/data/IPair.java b/base/src/main/java/bjc/utils/data/IPair.java index 907cf3d..886bf7c 100644 --- a/base/src/main/java/bjc/utils/data/IPair.java +++ b/base/src/main/java/bjc/utils/data/IPair.java @@ -12,10 +12,10 @@ import bjc.utils.funcdata.theory.Bifunctor; * @author ben * * @param <LeftType> - * The type of the left side of the pair. + * The type of the left side of the pair. * * @param <RightType> - * The type of the right side of the pair. + * The type of the right side of the pair. * */ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightType> { @@ -23,13 +23,13 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Bind a function across the values in this pair. * * @param <BoundLeft> - * The type of the bound left. + * The type of the bound left. * * @param <BoundRight> - * The type of the bound right. + * The type of the bound right. * * @param binder - * The function to bind with. + * The function to bind with. * * @return The bound pair. */ @@ -40,10 +40,10 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Bind a function to the left value in this pair. * * @param <BoundLeft> - * The type of the bound value. + * The type of the bound value. * * @param leftBinder - * The function to use to bind. + * The function to use to bind. * * @return A pair with the left type bound. */ @@ -54,10 +54,10 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Bind a function to the right value in this pair. * * @param <BoundRight> - * The type of the bound value. + * The type of the bound value. * * @param rightBinder - * The function to use to bind. + * The function to use to bind. * * @return A pair with the right type bound. */ @@ -68,13 +68,13 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Pairwise combine two pairs together. * * @param <OtherLeft> - * The left type of the other pair. + * The left type of the other pair. * * @param <OtherRight> - * The right type of the other pair. + * The right type of the other pair. * * @param otherPair - * The pair to combine with. + * The pair to combine with. * * @return The pairs, pairwise combined together. */ @@ -87,25 +87,25 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Combine the contents of two pairs together. * * @param <OtherLeft> - * The type of the left value of the other pair. + * The type of the left value of the other pair. * * @param <OtherRight> - * The type of the right value of the other pair. + * The type of the right value of the other pair. * * @param <CombinedLeft> - * The type of the left value of the combined pair. + * The type of the left value of the combined pair. * * @param <CombinedRight> - * The type of the right value of the combined pair. + * The type of the right value of the combined pair. * * @param otherPair - * The other pair to combine with. + * The other pair to combine with. * * @param leftCombiner - * The function to combine the left values with. + * The function to combine the left values with. * * @param rightCombiner - * The function to combine the right values with. + * The function to combine the right values with. * * @return A pair with its values combined. */ @@ -119,7 +119,7 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * pair. * * @param consumer - * The action to perform on the pair. + * The action to perform on the pair. */ public default void doWith(final BiConsumer<LeftType, RightType> consumer) { merge((leftValue, rightValue) -> { @@ -133,7 +133,7 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp default <OldLeft, OldRight, NewLeft> LeftBifunctorMap<OldLeft, OldRight, NewLeft> fmapLeft( final Function<OldLeft, NewLeft> func) { return argumentPair -> { - if(!(argumentPair instanceof IPair<?, ?>)) { + if (!(argumentPair instanceof IPair<?, ?>)) { final String msg = "This function can only be applied to instances of IPair"; throw new IllegalArgumentException(msg); @@ -149,7 +149,7 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp default <OldLeft, OldRight, NewRight> RightBifunctorMap<OldLeft, OldRight, NewRight> fmapRight( final Function<OldRight, NewRight> func) { return argumentPair -> { - if(!(argumentPair instanceof IPair<?, ?>)) { + if (!(argumentPair instanceof IPair<?, ?>)) { final String msg = "This function can only be applied to instances of IPair"; throw new IllegalArgumentException(msg); @@ -187,10 +187,11 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Doesn't modify the pair. * * @param <NewLeft> - * The new type of the left part of the pair. + * The new type of the left part of the pair. * * @param mapper - * The function to use to transform the left part of the pair. + * The function to use to transform the left part of the + * pair. * * @return The pair, with its left part transformed. */ @@ -202,10 +203,11 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Doesn't modify the pair. * * @param <NewRight> - * The new type of the right part of the pair. + * The new type of the right part of the pair. * * @param mapper - * The function to use to transform the right part of the pair. + * The function to use to transform the right part of the + * pair. * * @return The pair, with its right part transformed. */ @@ -215,15 +217,24 @@ public interface IPair<LeftType, RightType> extends Bifunctor<LeftType, RightTyp * Merge the two values in this pair into a single value. * * @param <MergedType> - * The type of the single value. + * The type of the single value. * * @param merger - * The function to use for merging. + * The function to use for merging. * * @return The pair, merged into a single value. */ public <MergedType> MergedType merge(BiFunction<LeftType, RightType, MergedType> merger); + /** + * Static pair constructor. + * + * @param left + * The left side of the pair. + * @param right + * The right side of the pair. + * @return A pair, with the specified left/right side. + */ public static <T1, T2> IPair<T1, T2> pair(T1 left, T2 right) { return new Pair<>(left, right); } diff --git a/base/src/main/java/bjc/utils/esodata/DefaultList.java b/base/src/main/java/bjc/utils/esodata/DefaultList.java index 235a1a8..4d3d1dc 100644 --- a/base/src/main/java/bjc/utils/esodata/DefaultList.java +++ b/base/src/main/java/bjc/utils/esodata/DefaultList.java @@ -8,6 +8,8 @@ import java.util.List; * A list that has a default value that out-of-bounds accesses return. * * @author Ben Culkin + * @param <ValueType> + * The type of the values contained in the list. */ public class DefaultList<ValueType> extends AbstractList<ValueType> { /* @@ -20,33 +22,67 @@ public class DefaultList<ValueType> extends AbstractList<ValueType> { * bounds, but what are you going to do? */ - private ValueType defVal; private List<ValueType> backing; + /** + * Create a new DefaultList. + */ public DefaultList() { this(new ArrayList<>(), null); } + /** + * Create a new DefaultList, with a set default value. + * + * @param defVal + * The default value for the list. + */ public DefaultList(ValueType defVal) { this(new ArrayList<>(), defVal); } + /** + * Create a new DefaultList, with a specific backing list. + * + * @param backer + * The backing list to use. + * + */ public DefaultList(List<ValueType> backer) { this(backer, null); } + /** + * Create a new DefaultList, with a set default value. + * + * @param backer + * The backing list to use. + * + * @param defVal + * The default value for the list. + */ public DefaultList(List<ValueType> backer, ValueType defVal) { this.defVal = defVal; this.backing = backer; } + /** + * Get the default value. + * + * @return The default value. + */ public ValueType getDefault() { return defVal; } + /** + * Set the default value. + * + * @param defVal The default value. + */ public void setDefault(ValueType defVal) { this.defVal = defVal; } diff --git a/base/src/main/java/bjc/utils/esodata/DoubleSided.java b/base/src/main/java/bjc/utils/esodata/DoubleSided.java index 83b7c77..2c57332 100644 --- a/base/src/main/java/bjc/utils/esodata/DoubleSided.java +++ b/base/src/main/java/bjc/utils/esodata/DoubleSided.java @@ -1,5 +1,11 @@ package bjc.utils.esodata; +/** + * Interface for a double-sided object. + * + * @author bjculkin + * + */ public interface DoubleSided { /** * Flips the object. diff --git a/base/src/main/java/bjc/utils/esodata/MapSet.java b/base/src/main/java/bjc/utils/esodata/MapSet.java index 94d7700..16def9e 100644 --- a/base/src/main/java/bjc/utils/esodata/MapSet.java +++ b/base/src/main/java/bjc/utils/esodata/MapSet.java @@ -6,49 +6,115 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +/** + * A string-keyed set of maps. + * + * @author bjculkin + * + * @param <KeyType> + * The key type of the maps. + * @param <ValueType> + * The value type of the maps. + */ public class MapSet<KeyType, ValueType> extends AbstractMap<KeyType, ValueType> { private Map<String, Map<KeyType, ValueType>> backing; private Map<KeyType, ValueType> currentMap = null; + /** + * Create a new set of maps. + */ public MapSet() { backing = new HashMap<>(); } + /** + * Create a new set of maps, with the specified set of maps. + * + * @param back + * The set of maps to use. + */ public MapSet(Map<String, Map<KeyType, ValueType>> back) { backing = back; } + /** + * Add a keyed map. + * + * @param key + * The key for the map. + * @param map + * The map itself. + */ public void addMap(String key, Map<KeyType, ValueType> map) { backing.put(key, map); } + /** + * Clear out the contents of the set + */ public void clearMap() { currentMap = null; backing.clear(); } + /** + * Check if there is a map attached to the specified key. + * + * @param key + * The key to look for. + * @return Whether or not there is anything attached to the key. + */ public boolean containsMap(String key) { return backing.containsKey(key); } + /** + * Get the map attached to a specified key. + * + * @param key + * The key to look for. + * @return The map attached to the key. + */ public Map<KeyType, ValueType> getMap(String key) { return backing.get(key); } + /** + * Get all of the backing entries. + * + * @return The backing entries. + */ public Set<Map.Entry<String, Map<KeyType, ValueType>>> getMapEntries() { return backing.entrySet(); } + /** + * Get all of the keys. + * + * @return The keys currently in use. + */ public Set<String> getMapKeys() { return backing.keySet(); } + /** + * Get all of the keyed maps. + * + * @return The keyed maps. + */ public Collection<Map<KeyType, ValueType>> getMapValues() { return backing.values(); } + /** + * Set the current map. + * + * @param key + * The key to use as the current map. + * @return False if there is no map attached to the key, true otherwise. + */ public boolean setMap(String key) { if (!backing.containsKey(key)) return false; @@ -57,6 +123,13 @@ public class MapSet<KeyType, ValueType> extends AbstractMap<KeyType, ValueType> return true; } + /** + * Sets the current map, or creates a new one if there isn't one + * attached to that key. + * + * @param key + * The key to use as the current map. + */ public void setCreateMap(String key) { if (!backing.containsKey(key)) { currentMap = new HashMap<>(); @@ -69,6 +142,14 @@ public class MapSet<KeyType, ValueType> extends AbstractMap<KeyType, ValueType> currentMap = backing.get(key); } + /** + * Set the current map, or bind a map to it. + * + * @param key + * The key to set or bind. + * @param map + * The map to bind to the key if it isn't present. + */ public void setPutMap(String key, Map<KeyType, ValueType> map) { if (!backing.containsKey(key)) { currentMap = map; diff --git a/base/src/main/java/bjc/utils/esodata/Tape.java b/base/src/main/java/bjc/utils/esodata/Tape.java index 41b0ce7..0835f7e 100644 --- a/base/src/main/java/bjc/utils/esodata/Tape.java +++ b/base/src/main/java/bjc/utils/esodata/Tape.java @@ -8,7 +8,7 @@ package bjc.utils.esodata; * unbounded to the right, but in practice bounded by available memory. * * @param <T> - * The element type of the tape. + * The element type of the tape. * * @author bjculkin */ @@ -24,7 +24,7 @@ public interface Tape<T> { * Set the item the tape is currently on. * * @param itm - * The new value for the tape item. + * The new value for the tape item. */ void item(T itm); @@ -46,7 +46,7 @@ public interface Tape<T> { * Insert an element before the current item. * * @param itm - * The item to add. + * The item to add. */ void insertBefore(T itm); @@ -54,7 +54,7 @@ public interface Tape<T> { * Insert an element after the current item. * * @param itm - * The item to insert. + * The item to insert. */ void insertAfter(T itm); @@ -90,7 +90,7 @@ public interface Tape<T> { * that would exceed zero don't move the cursor at all. * * @param amt - * The amount to attempt to move the cursor left. + * The amount to attempt to move the cursor left. * * @return True if the cursor was moved left. */ @@ -107,14 +107,28 @@ public interface Tape<T> { * Move the cursor the specified amount right. * * @param amt - * The amount to move the cursor right by. + * The amount to move the cursor right by. * * @return Whether the cursor was moved right. */ boolean right(int amt); + /** + * Seek to an absolute position on the tape. + * + * @param pos + * The position to seek to. + * @return Whether or not the tape successfully seeked to that position. + */ boolean seekTo(int pos); + /** + * Check if this tape is at its end. + * + * Equivalent to checking if position() == size(). + * + * @return Whether or not the tape is at its end. + */ default boolean atEnd() { return position() == size(); } diff --git a/base/src/main/java/bjc/utils/funcdata/FunctionalList.java b/base/src/main/java/bjc/utils/funcdata/FunctionalList.java index 6953bd0..b988588 100644 --- a/base/src/main/java/bjc/utils/funcdata/FunctionalList.java +++ b/base/src/main/java/bjc/utils/funcdata/FunctionalList.java @@ -54,7 +54,20 @@ public class FunctionalList<E> implements Cloneable, IList<E> { wrapped.add(item); } } - + + /** + * Create a new functional list containing the specified items. + * + * Takes O(n) time, where n is the number of items specified + * + * @param items + * The items to put into this functional list. + * @return The returned list. + */ + @SafeVarargs + public static <T> IList<T> listOf(final T... items) { + return new FunctionalList<>(items); + } /** * Create a new functional list with the specified size. * diff --git a/base/src/main/java/bjc/utils/funcdata/IList.java b/base/src/main/java/bjc/utils/funcdata/IList.java index 12eaf2f..c2f247b 100644 --- a/base/src/main/java/bjc/utils/funcdata/IList.java +++ b/base/src/main/java/bjc/utils/funcdata/IList.java @@ -18,14 +18,14 @@ import bjc.utils.functypes.ID; * @author ben * * @param <ContainedType> - * The type in this list + * The type in this list */ public interface IList<ContainedType> extends Iterable<ContainedType> { /** * Add an item to this list. * * @param item - * The item to add to this list. + * The item to add to this list. * * @return Whether the item was added to the list successfully.. */ @@ -35,7 +35,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Add all of the elements in the provided list to this list. * * @param items - * The list of items to add. + * The list of items to add. * * @return True if every item was successfully added to the list, false * otherwise. @@ -48,7 +48,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Add all of the elements in the provided array to this list. * * @param items - * The array of items to add. + * The array of items to add. * * @return True if every item was successfully added to the list, false * otherwise. @@ -57,7 +57,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { default boolean addAll(final ContainedType... items) { boolean succ = true; - for(final ContainedType item : items) { + for (final ContainedType item : items) { final boolean addSucc = add(item); succ = succ ? addSucc : false; @@ -71,7 +71,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * predicate. * * @param matcher - * The predicate to use for checking. + * The predicate to use for checking. * * @return Whether all of the elements of the list match the specified * predicate. @@ -82,7 +82,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Check if any of the elements in this list match the specified list. * * @param matcher - * The predicate to use for checking. + * The predicate to use for checking. * * @return Whether any element in the list matches the provided * predicate. @@ -93,13 +93,13 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Reduce the contents of this list using a collector. * * @param <StateType> - * The intermediate accumulation type. + * The intermediate accumulation type. * * @param <ReducedType> - * The final, reduced type. + * The final, reduced type. * * @param collector - * The collector to use for reduction. + * The collector to use for reduction. * * @return The reduced list. */ @@ -126,16 +126,16 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * list and the combined one. * * @param <OtherType> - * The type of the second list. + * The type of the second list. * * @param <CombinedType> - * The type of the combined list. + * The type of the combined list. * * @param list - * The list to combine with. + * The list to combine with. * * @param combiner - * The function to use for combining element pairs. + * The function to use for combining element pairs. * * @return A new list containing the merged pairs of lists. */ @@ -146,7 +146,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Check if the list contains the specified item. * * @param item - * The item to see if it is contained. + * The item to see if it is contained. * * @return Whether or not the specified item is in the list. */ @@ -166,7 +166,18 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { */ ContainedType last(); + /** + * Remove and return the first element from the list. + * + * @return The first element from the list. + */ ContainedType popFirst(); + + /** + * Remove and return the last element from the list. + * + * @return The last element from the list. + */ ContainedType popLast(); /** @@ -176,10 +187,10 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Does not change the underlying list. * * @param <MappedType> - * The type of the flattened list. + * The type of the flattened list. * * @param expander - * The function to apply to each member of the list. + * The function to apply to each member of the list. * * @return A new list containing the flattened results of applying the * provided function. @@ -190,7 +201,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Apply a given action for each member of the list. * * @param action - * The action to apply to each member of the list. + * The action to apply to each member of the list. */ @Override void forEach(Consumer<? super ContainedType> action); @@ -199,8 +210,8 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Apply a given function to each element in the list and its index. * * @param action - * The function to apply to each element in the list and its - * index. + * The function to apply to each element in the list and + * its index. */ void forEachIndexed(BiConsumer<Integer, ContainedType> action); @@ -208,7 +219,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Retrieve a value in the list by its index. * * @param index - * The index to retrieve a value from. + * The index to retrieve a value from. * * @return The value at the specified index in the list. */ @@ -218,7 +229,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Retrieve a list containing all elements matching a predicate. * * @param predicate - * The predicate to match by. + * The predicate to match by. * * @return A list containing all elements that match the predicate. */ @@ -245,10 +256,10 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Does not change the underlying list. * * @param <MappedType> - * The type of the transformed list. + * The type of the transformed list. * * @param transformer - * The function to apply to each element in the list. + * The function to apply to each element in the list. * * @return A new list containing the mapped elements of this list. */ @@ -258,10 +269,10 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Zip two lists into a list of pairs. * * @param <OtherType> - * The type of the second list. + * The type of the second list. * * @param list - * The list to use as the left side of the pair. + * The list to use as the left side of the pair. * * @return A list containing pairs of this element and the specified * list. @@ -272,7 +283,8 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Partition this list into a list of sublists. * * @param partitionSize - * The size of elements to put into each one of the sublists. + * The size of elements to put into each one of the + * sublists. * * @return A list partitioned into partitions of size partitionSize. The * last partition may not be completely full if the size of the @@ -284,7 +296,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Prepend an item to the list. * * @param item - * The item to prepend to the list. + * The item to prepend to the list. */ void prepend(ContainedType item); @@ -292,11 +304,11 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Prepend an array of items to the list. * * @param items - * The items to prepend to the list. + * The items to prepend to the list. */ @SuppressWarnings("unchecked") default void prependAll(final ContainedType... items) { - for(final ContainedType item : items) { + for (final ContainedType item : items) { prepend(item); } } @@ -316,7 +328,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * generator. * * @param rnd - * The random number generator to use. + * The random number generator to use. * * @return A random element from this list. */ @@ -326,21 +338,21 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Reduce this list to a single value, using a accumulative approach. * * @param <StateType> - * The in-between type of the values + * The in-between type of the values * * @param <ReducedType> - * The final value type + * The final value type * * @param initial - * The initial value of the accumulative state. + * The initial value of the accumulative state. * * @param accumulator - * The function to use to combine a list element with the - * accumulative state. + * The function to use to combine a list element with the + * accumulative state. * * @param transformer - * The function to use to convert the accumulative state into a - * final result. + * The function to use to convert the accumulative state + * into a final result. * * @return A single value condensed from this list and transformed into * its final state. @@ -353,14 +365,14 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Reduce this list to a single value, using a accumulative approach. * * @param <StateType> - * The in-between type of the values. + * The in-between type of the values. * * @param initial - * The initial value of the accumulative state. + * The initial value of the accumulative state. * * @param accumulator - * The function to use to combine a list element with the - * accumulative state. + * The function to use to combine a list element with the + * accumulative state. * * @return A single value condensed from this list. */ @@ -373,7 +385,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Remove all elements that match a given predicate. * * @param predicate - * The predicate to use to determine elements to delete. + * The predicate to use to determine elements to delete. * * @return Whether there was anything that satisfied the predicate. */ @@ -383,7 +395,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Remove all parameters that match a given parameter. * * @param element - * The object to remove all matching copies of. + * The object to remove all matching copies of. */ void removeMatching(ContainedType element); @@ -398,11 +410,11 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * hand. * * @param key - * The key to search for. + * The key to search for. * * @param comparator - * The way to compare elements for searching. Pass null to use - * the natural ordering for E. + * The way to compare elements for searching. Pass null + * to use the natural ordering for E. * * @return The element if it is in this list, or null if it is not. */ @@ -415,8 +427,8 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Does change the underlying list. * * @param comparator - * The way to compare elements for sorting. Pass null to use E's - * natural ordering + * The way to compare elements for sorting. Pass null to + * use E's natural ordering */ void sort(Comparator<ContainedType> comparator); @@ -431,7 +443,7 @@ public interface IList<ContainedType> extends Iterable<ContainedType> { * Convert this list into an array. * * @param type - * The type of array to return. + * The type of array to return. * * @return The list, as an array. */ diff --git a/base/src/main/java/bjc/utils/funcutils/FileUtils.java b/base/src/main/java/bjc/utils/funcutils/FileUtils.java index 0fd3db0..04ac6b0 100644 --- a/base/src/main/java/bjc/utils/funcutils/FileUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/FileUtils.java @@ -13,26 +13,28 @@ import java.util.function.BiPredicate; */ public class FileUtils { /* - * @NOTE If it becomes necessary, write another overload for this with - * all the buttons and knobs from walkFileTree. + * @NOTE + * + * If it becomes necessary, write another overload for this with all the + * buttons and knobs from walkFileTree. */ /** * Traverse a directory recursively. This is a depth-first traversal. * * @param root - * The directory to start the traversal at. + * The directory to start the traversal at. * * @param predicate - * The predicate to determine whether or not to traverse a - * directory. + * The predicate to determine whether or not to traverse + * a directory. * * @param action - * The action to invoke upon each file in the directory. - * Returning true means to continue the traversal, returning - * false stops it. + * The action to invoke upon each file in the directory. + * Returning true means to continue the traversal, + * returning false stops it. * * @throws IOException - * If the walk throws an exception. + * If the walk throws an exception. * */ public static void traverseDirectory(final Path root, final BiPredicate<Path, BasicFileAttributes> predicate, diff --git a/base/src/main/java/bjc/utils/funcutils/FuncUtils.java b/base/src/main/java/bjc/utils/funcutils/FuncUtils.java index 2e55a3d..ff9fefb 100644 --- a/base/src/main/java/bjc/utils/funcutils/FuncUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/FuncUtils.java @@ -1,6 +1,7 @@ package bjc.utils.funcutils; import java.util.function.BiFunction; +import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.UnaryOperator; @@ -16,16 +17,16 @@ public class FuncUtils { * function. * * @param <A> - * The initial type of the function. + * The initial type of the function. * * @param <B> - * The intermediate type of the function. + * The intermediate type of the function. * * @param <C> - * The terminal type of the function. + * The terminal type of the function. * * @param func - * The function to transform. + * The function to transform. * * @return The function transformed into a unary function returning a * function. @@ -40,13 +41,13 @@ public class FuncUtils { * Do the specified action the specified number of times. * * @param nTimes - * The number of times to do the action. + * The number of times to do the action. * * @param cons - * The action to perform. + * The action to perform. */ public static void doTimes(final int nTimes, final Consumer<Integer> cons) { - for(int i = 0; i < nTimes; i++) { + for (int i = 0; i < nTimes; i++) { cons.accept(i); } } @@ -55,15 +56,35 @@ public class FuncUtils { * Return an operator that executes until it converges. * * @param op - * The operator to execute. + * The operator to execute. * * @param maxTries - * The maximum amount of times to apply the function in an - * attempt to cause it to converge. + * The maximum amount of times to apply the function in + * an attempt to cause it to converge. * * @return The requested operator. */ public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op, final int maxTries) { + return converge(op, (nw, old) -> nw.equals(old), maxTries); + } + + /** + * Return an operator that executes until it converges. + * + * @param op + * The operator to execute. + * @param converged + * The predicate to execute to check if the function has + * converged. + * + * @param maxTries + * The maximum amount of times to apply the function in + * an attempt to cause it to converge. + * + * @return The requested operator. + */ + public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op, final BiPredicate<T, T> converged, + final int maxTries) { return (val) -> { T newVal = op.apply(val); T oldVal; @@ -75,7 +96,7 @@ public class FuncUtils { newVal = op.apply(newVal); tries += 1; - } while(!newVal.equals(oldVal) && tries < maxTries); + } while (!converged.test(newVal, oldVal) && tries < maxTries); return newVal; }; diff --git a/base/src/main/java/bjc/utils/funcutils/ListUtils.java b/base/src/main/java/bjc/utils/funcutils/ListUtils.java index 55e0afa..b99c8a0 100644 --- a/base/src/main/java/bjc/utils/funcutils/ListUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/ListUtils.java @@ -25,12 +25,12 @@ public class ListUtils { * spaces. * * @param input - * The list of tokens to collapse. + * The list of tokens to collapse. * * @return The collapsed string of tokens. */ public static String collapseTokens(final IList<String> input) { - if(input == null) throw new NullPointerException("Input must not be null"); + if (input == null) throw new NullPointerException("Input must not be null"); return collapseTokens(input, ""); } @@ -40,32 +40,32 @@ public class ListUtils { * separator after each token. * * @param input - * The list of tokens to collapse. + * The list of tokens to collapse. * * @param seperator - * The separator to use for separating tokens. + * The separator to use for separating tokens. * * @return The collapsed string of tokens. */ public static String collapseTokens(final IList<String> input, final String seperator) { - if(input == null) { + if (input == null) { throw new NullPointerException("Input must not be null"); - } else if(seperator == null) { + } else if (seperator == null) { throw new NullPointerException("Seperator must not be null"); } - if(input.getSize() < 1) { + if (input.getSize() < 1) { return ""; - } else if(input.getSize() == 1) { + } else if (input.getSize() == 1) { return input.first(); } else { final StringBuilder state = new StringBuilder(); int i = 1; - for(final String itm : input.toIterable()) { + for (final String itm : input.toIterable()) { state.append(itm); - if(i != input.getSize()) { + if (i != input.getSize()) { state.append(seperator); } @@ -80,17 +80,17 @@ public class ListUtils { * Select a number of random items from the list without replacement. * * @param <E> - * The type of items to select. + * The type of items to select. * * @param list - * The list to select from. + * The list to select from. * * @param number - * The number of items to selet. + * The number of items to selet. * * @param rng - * A function that creates a random number from 0 to the desired - * number. + * A function that creates a random number from 0 to the + * desired number. * * @return A new list containing the desired number of items randomly * selected from the specified list without replacement. @@ -104,7 +104,7 @@ public class ListUtils { final Iterator<E> itr = list.toIterable().iterator(); E element = null; - for(final int index = 0; itr.hasNext(); element = itr.next()) { + for (final int index = 0; itr.hasNext(); element = itr.next()) { /* n - m */ final int winningChance = number - selected.getSize(); @@ -112,7 +112,7 @@ public class ListUtils { final int totalChance = total - (index - 1); /* Probability of selecting the t+1'th element */ - if(NumberUtils.isProbable(winningChance, totalChance, rng)) { + if (NumberUtils.isProbable(winningChance, totalChance, rng)) { selected.add(element); } } @@ -124,17 +124,17 @@ public class ListUtils { * Select a number of random items from the list, with replacement. * * @param <E> - * The type of items to select. + * The type of items to select. * * @param list - * The list to select from. + * The list to select from. * * @param number - * The number of items to select. + * The number of items to select. * * @param rng - * A function that creates a random number from 0 to the desired - * number. + * A function that creates a random number from 0 to the + * desired number. * * @return A new list containing the desired number of items randomly * selected from the specified list. @@ -143,7 +143,7 @@ public class ListUtils { final Function<Integer, Integer> rng) { final IList<E> selected = new FunctionalList<>(new ArrayList<>(number)); - for(int i = 0; i < number; i++) { + for (int i = 0; i < number; i++) { selected.add(list.randItem(rng)); } @@ -155,26 +155,27 @@ public class ListUtils { * for more than one element in a partition. * * @param <E> - * The type of elements in the list to partition. + * The type of elements in the list to partition. * * @param input - * The list to partition. + * The list to partition. * * @param counter - * The function to determine the count for each element for. + * The function to determine the count for each element + * for. * * @param partitionSize - * The number of elements to put in each partition. + * The number of elements to put in each partition. * * @return A list partitioned according to the above rules. */ public static <E> IList<IList<E>> groupPartition(final IList<E> input, final Function<E, Integer> counter, final int partitionSize) { - if(input == null) { + if (input == null) { throw new NullPointerException("Input list must not be null"); - } else if(counter == null) { + } else if (counter == null) { throw new NullPointerException("Counter must not be null"); - } else if(partitionSize < 1 || partitionSize > input.getSize()) { + } else if (partitionSize < 1 || partitionSize > input.getSize()) { final String fmt = "%d is not a valid partition size. Must be between 1 and %d"; final String msg = String.format(fmt, partitionSize, input.getSize()); @@ -190,11 +191,11 @@ public class ListUtils { final GroupPartIteration<E> it = new GroupPartIteration<>(returned, rejected, partitionSize, counter); /* Run up to a certain number of passes. */ - for(int numberOfIterations = 0; numberOfIterations < MAX_NTRIESPART + for (int numberOfIterations = 0; numberOfIterations < MAX_NTRIESPART && !rejected.isEmpty(); numberOfIterations++) { input.forEach(it); - if(rejected.isEmpty()) { + if (rejected.isEmpty()) { /* Nothing was rejected, so we're done. */ return returned; } @@ -212,10 +213,10 @@ public class ListUtils { * Merge the contents of a bunch of lists together into a single list. * * @param <E> - * The type of value in this lists. + * The type of value in this lists. * * @param lists - * The values in the lists to merge. + * The values in the lists to merge. * * @return A list containing all the elements of the lists. */ @@ -223,8 +224,8 @@ public class ListUtils { public static <E> IList<E> mergeLists(final IList<E>... lists) { final IList<E> returned = new FunctionalList<>(); - for(final IList<E> list : lists) { - for(final E itm : list.toIterable()) { + for (final IList<E> list : lists) { + for (final E itm : list.toIterable()) { returned.add(itm); } } @@ -236,24 +237,24 @@ public class ListUtils { * Pad the provided list out to the desired size. * * @param <E> - * The type of elements in the list. + * The type of elements in the list. * * @param list - * The list to pad out. + * The list to pad out. * * @param counter - * The function to count elements with. + * The function to count elements with. * * @param size - * The desired size of the list. + * The desired size of the list. * * @param padder - * The function to get elements to pad with. + * The function to get elements to pad with. * * @return The list, padded to the desired size. * * @throws IllegalArgumentException - * If the list couldn't be padded to the desired size. + * If the list couldn't be padded to the desired size. */ public static <E> IList<E> padList(final IList<E> list, final Function<E, Integer> counter, final int size, final Supplier<E> padder) { @@ -261,22 +262,22 @@ public class ListUtils { final IList<E> returned = new FunctionalList<>(); - for(final E itm : list.toIterable()) { + for (final E itm : list.toIterable()) { count += counter.apply(itm); returned.add(itm); } - if(count % size != 0) { + if (count % size != 0) { /* We need to pad */ int needed = count % size; int threshold = 0; - while(needed > 0 && threshold <= MAX_NTRIESPART) { + while (needed > 0 && threshold <= MAX_NTRIESPART) { final E val = padder.get(); final int newCount = counter.apply(val); - if(newCount <= needed) { + if (newCount <= needed) { returned.add(val); threshold = 0; @@ -287,7 +288,7 @@ public class ListUtils { } } - if(threshold > MAX_NTRIESPART) { + if (threshold > MAX_NTRIESPART) { final String fmt = "Heuristic (more than %d iterations of attempting to pad) detected an unpaddable list. (%s)\nPartially padded list: %S"; final String msg = String.format(fmt, MAX_NTRIESPART, list.toString(), @@ -300,11 +301,18 @@ public class ListUtils { return returned; } + /** + * Convert a list of longs into an array of longs. + * + * @param list + * The list to convert. + * @return The list as an array. + */ public static long[] toPrimitive(List<Long> list) { long[] res = new long[list.size()]; int idx = 0; - for(long val : list) { + for (long val : list) { res[idx] = val; idx += 1; @@ -320,7 +328,7 @@ public class ListUtils { * pg 322) * * @param list - * The list to generate permutations from. + * The list to generate permutations from. * @return The list of permutations of the list. */ public static <T> List<List<T>> permuteList(List<T> list) { @@ -329,17 +337,17 @@ public class ListUtils { /* * Special-case small usages. */ - if(list.size() == 0) { + if (list.size() == 0) { return permutes; } - if(list.size() == 1) { + if (list.size() == 1) { permutes.add(list); return permutes; } - if(list.size() == 2) { + if (list.size() == 2) { T elm1 = list.get(0); T elm2 = list.get(1); @@ -363,13 +371,13 @@ public class ListUtils { int[] auxC = new int[list.size()]; int[] auxO = new int[list.size()]; - for(int i = 0; i < list.size(); i++) { + for (int i = 0; i < list.size(); i++) { auxC[i] = 0; auxO[i] = 1; } List<T> currentPermute = new ArrayList<>(list.size()); - for(T elm : list) { + for (T elm : list) { currentPermute.add(elm); } permutes.add(currentPermute); @@ -377,18 +385,18 @@ public class ListUtils { int j = list.size() - 1; int s = 0; - while(true) { + while (true) { int q = auxC[j] + auxO[j]; - if(q < 0) { + if (q < 0) { auxO[j] = -auxO[j]; j -= 1; continue; } - if(q == j) { - if(j == 0) break; + if (q == j) { + if (j == 0) break; s += 1; @@ -406,7 +414,7 @@ public class ListUtils { auxC[j] = q; currentPermute = new ArrayList<>(list.size()); - for(T elm : list) { + for (T elm : list) { currentPermute.add(elm); } permutes.add(currentPermute); @@ -418,12 +426,6 @@ public class ListUtils { return permutes; } - private static <T> List<List<T>> powerList(List<T> list) { - List<List<T>> results = new LinkedList<>(); - - return results; - } - private static <T> void swapList(List<T> list, int a, int b) { T tmp = list.get(a); diff --git a/base/src/main/java/bjc/utils/funcutils/SetUtils.java b/base/src/main/java/bjc/utils/funcutils/SetUtils.java index eac417c..d57ac00 100644 --- a/base/src/main/java/bjc/utils/funcutils/SetUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/SetUtils.java @@ -5,10 +5,21 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +/** + * Various utility functions dealing with sets. + * @author bjculkin + * + */ public class SetUtils { + /** + * Create a power-set (set of all subsets) of a given set. + * @param originalSet The set to create a power-set of. + * @return The power-set of the set. + */ public static <T> Set<Set<T>> powerSet(Set<T> originalSet) { Set<Set<T>> sets = new HashSet<Set<T>>(); + // Special-case empty input if (originalSet.isEmpty()) { sets.add(new HashSet<T>()); return sets; @@ -16,13 +27,18 @@ public class SetUtils { List<T> list = new ArrayList<T>(originalSet); + // Add original set to list. T head = list.get(0); + // Trim leading element from set. Set<T> rest = new HashSet<T>(list.subList(1, list.size())); - for (Set<T> set : powerSet(rest)) { + Set<Set<T>> remSets = powerSet(rest); + + for (Set<T> set : remSets) { Set<T> newSet = new HashSet<T>(); + // Create a new set with the removed element. newSet.add(head); newSet.addAll(set); @@ -33,6 +49,12 @@ public class SetUtils { return sets; } + /** + * Utility method for set construction. + * @param elms The elements to stick in the set. + * @return A set containing the specified elements. + */ + @SafeVarargs public static <T> Set<T> toSet(T... elms) { Set<T> set = new HashSet<>(); diff --git a/base/src/main/java/bjc/utils/funcutils/StringUtils.java b/base/src/main/java/bjc/utils/funcutils/StringUtils.java index 8e75f79..7a4ee20 100644 --- a/base/src/main/java/bjc/utils/funcutils/StringUtils.java +++ b/base/src/main/java/bjc/utils/funcutils/StringUtils.java @@ -254,220 +254,4 @@ public class StringUtils { } return strings; } - - public static boolean levelContains(String haystack, String... needles) { - int nestLevel = 0; - int i = 0; - - boolean prevCharWasSlash = false; - boolean inString = false; - - char stringEnder = ' '; - - while(i < haystack.length()) { - if(inString == false && nestLevel == 0) { - for(String needle : needles) { - if(haystack.regionMatches(i, needle, 0, needle.length())) { - return true; - } - } - } - - if(inString) { - if(prevCharWasSlash == true) { - prevCharWasSlash = false; - } else if (haystack.charAt(i) == stringEnder) { - inString = false; - } - } else { - switch(haystack.charAt(i)) { - case '\'': - inString = true; - stringEnder = '\''; - break; - case '\"': - inString = true; - stringEnder = '\"'; - break; - case '(': - case '[': - case '{': - case '<': - nestLevel += 1; - break; - case ')': - case ']': - case '}': - case '>': - nestLevel = Math.max(0, nestLevel - 1); - break; - } - } - - i += 1; - } - - return false; - } - - public static List<String> levelSplit(String phrase, String... splits) { - return levelSplit(phrase, false, splits); - } - - public static List<String> levelSplit(String phrase, boolean keepDelims, String... splits) { - String work = phrase; - - List<String> strangs = new ArrayList<>(); - - int nestLevel = 0; - int i = 0; - - boolean prevCharWasSlash = false; - boolean inString = false; - - char stringEnder = ' '; - - // Shortcut empty strings - if(phrase.equals("")) { - strangs.add(""); - - return strangs; - } - - while(i < work.length()) { - if(inString == false && nestLevel == 0) { - for(String split : splits) { - if(work.regionMatches(i, split, 0, split.length())) { - strangs.add(work.substring(0, i)); - - if(keepDelims) strangs.add(split); - - work = work.substring(i + split.length()); - i = 0; - - continue; - } - } - } - - if(inString) { - if(prevCharWasSlash == true) { - prevCharWasSlash = false; - } else if (work.charAt(i) == stringEnder) { - inString = false; - } - } else { - /* - * @TODO Ben Culkin 9/4/18 - * - * This currently crashes if the string ends - * with one of the delimiters in question. - */ - switch(work.charAt(i)) { - case '\'': - inString = true; - stringEnder = '\''; - break; - case '\"': - inString = true; - stringEnder = '\"'; - break; - case '(': - case '[': - case '{': - case '<': - nestLevel += 1; - break; - case ')': - case ']': - case '}': - case '>': - nestLevel = Math.max(0, nestLevel - 1); - break; - } - } - - i += 1; - } - - strangs.add(work); - - return strangs; - } - - public static List<String> levelSplitRX(String phrase, String patt) { - return levelSplit(phrase, false, patt); - } - - // @TODO @FIXME - // - // This doesn't seem like its working - public static List<String> levelSplitRX(String phrase, boolean keepDelims, String patt) { - Pattern pat = Pattern.compile(patt); - - String work = phrase; - Matcher mat = pat.matcher(work); - - List<String> strangs = new ArrayList<>(); - - int nestLevel = 0; - int i = 0; - - boolean prevCharWasSlash = false; - boolean inString = false; - - char stringEnder = ' '; - - while(i < work.length()) { - if(inString == false && nestLevel == 0) { - if(mat.find(i)) { - strangs.add(work.substring(0, i)); - if(keepDelims) strangs.add(mat.group()); - work = work.substring(mat.end()); - i = 0; - - mat = pat.matcher(work); - - continue; - } - } - - if(inString) { - if(prevCharWasSlash == true) { - prevCharWasSlash = false; - } else if (work.charAt(i) == stringEnder) { - inString = false; - } - } else { - switch(work.charAt(i)) { - case '\'': - inString = true; - stringEnder = '\''; - break; - case '\"': - inString = true; - stringEnder = '\"'; - break; - case '(': - case '[': - case '{': - case '<': - nestLevel += 1; - break; - case ')': - case ']': - case '}': - case '>': - nestLevel = Math.max(0, nestLevel - 1); - break; - } - } - - i += 1; - } - - strangs.add(work); - - return strangs; - } } diff --git a/base/src/main/java/bjc/utils/funcutils/TestUtils.java b/base/src/main/java/bjc/utils/funcutils/TestUtils.java new file mode 100644 index 0000000..df44e7a --- /dev/null +++ b/base/src/main/java/bjc/utils/funcutils/TestUtils.java @@ -0,0 +1,44 @@ +package bjc.utils.funcutils; + +import static org.junit.Assert.assertEquals; + +import java.util.Collection; +import java.util.Iterator; + +/** + * Utilities for testing. + * + * @author bjculkin + * + */ +public class TestUtils { + /** + * Assert an iterator provides a particular sequence of values. + * + * @param src + * The iterator to pull values from. + * @param vals + * The values to expect from the iterator. + */ + public static <T> void assertIteratorEquals(Iterator<T> src, T... vals) { + for (T val : vals) { + assertEquals(val, src.next()); + } + } + + /** + * Assert an iterator provides a particular sequence of values. + * + * @param src + * The iterator to pull values from. + * @param hasMore + * The expected value of hasNext for the iterator. + * @param vals + * The values to expect from the iterator. + */ + public static <T> void assertIteratorEquals(Iterator<T> src, boolean hasMore, T... vals) { + assertIteratorEquals(src, vals); + + assertEquals(hasMore, src.hasNext()); + } +} diff --git a/base/src/main/java/bjc/utils/gen/WeightedRandom.java b/base/src/main/java/bjc/utils/gen/WeightedRandom.java index 405d685..71de333 100644 --- a/base/src/main/java/bjc/utils/gen/WeightedRandom.java +++ b/base/src/main/java/bjc/utils/gen/WeightedRandom.java @@ -2,9 +2,7 @@ package bjc.utils.gen; import java.util.Random; -import bjc.utils.data.IHolder; import bjc.utils.data.IPair; -import bjc.utils.data.Identity; import bjc.utils.data.Pair; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.IList; @@ -16,7 +14,7 @@ import bjc.utils.funcdata.IList; * @author ben * * @param <E> - * The type of values that are randomly selected. + * The type of values that are randomly selected. */ public class WeightedRandom<E> { private final IList<IPair<Integer, E>> values; @@ -29,17 +27,18 @@ public class WeightedRandom<E> { private final static Random BASE = new Random(); private boolean exhaust; + /** * Create a new weighted random generator with the specified source of * randomness. * * @param src - * The source of randomness to use. + * The source of randomness to use. */ public WeightedRandom(Random src) { values = new FunctionalList<>(); - if(src == null) throw new NullPointerException("Source of randomness must not be null"); + if (src == null) throw new NullPointerException("Source of randomness must not be null"); source = src; } @@ -63,10 +62,10 @@ public class WeightedRandom<E> { * Add a probability for a specific result to be given. * * @param chance - * The chance to get this result. + * The chance to get this result. * * @param result - * The result to get when the chance comes up. + * The result to get when the chance comes up. */ public void addProbability(final int chance, final E result) { values.add(new Pair<>(chance, result)); @@ -83,15 +82,20 @@ public class WeightedRandom<E> { return generateValue(source); } + /** + * Generate a random value, using the specified Random. + * + * @param rn + * The Random instance to use. + * @return A random value. + */ public E generateValue(Random rn) { int target = rn.nextInt(totalChance); - int i = 0; - - for(IPair<Integer, E> val : values) { + for (IPair<Integer, E> val : values) { int prob = val.getLeft(); - if(target < prob) { - if(exhaust) { + if (target < prob) { + if (exhaust) { totalChance -= val.getLeft(); values.removeMatching(val); } @@ -100,11 +104,11 @@ public class WeightedRandom<E> { } target -= prob; - i += 1; } return null; } + /** * Return a list of values that can be generated by this generator * @@ -124,17 +128,41 @@ public class WeightedRandom<E> { return values; } + /** + * Get a descending value. + * + * Descending values are quite simple. You have a 1 in factor chance to + * advance to the next value, otherwise, the current value is the one + * returned. + * + * @param factor + * The descent factor to use. + * @return A random value. + */ public E getDescent(int factor) { return getDescent(factor, source); } + /** + * Get a descending value. + * + * Descending values are quite simple. You have a 1 in factor chance to + * advance to the next value, otherwise, the current value is the one + * returned. + * + * @param factor + * The descent factor to use. + * @param rn + * The Random instance to use. + * @return A random value. + */ public E getDescent(int factor, Random rn) { - if(values.getSize() == 0) return null; + if (values.getSize() == 0) return null; - for(IPair<Integer, E> val : values) { - if(rn.nextInt(factor) == 0) continue; + for (IPair<Integer, E> val : values) { + if (rn.nextInt(factor) == 0) continue; - if(exhaust) { + if (exhaust) { totalChance -= val.getLeft(); values.removeMatching(val); @@ -144,29 +172,61 @@ public class WeightedRandom<E> { } IPair<Integer, E> val = values.getByIndex(values.getSize() - 1); - if(exhaust) values.removeMatching(val); + if (exhaust) values.removeMatching(val); return val.getRight(); } + /** + * Get a value, treating this as a set of binomial trials. + * + * Essentially, the system rolls a bound-sided dice trials times, and + * marks a success for every roll less than or equal to target. + * + * @param target + * The number to roll at or under. + * @param bound + * The maximum roll value. + * @param trials + * The number of times to roll. + * @return The value at the index corresponding to the number of + * successes. + */ public E getBinomial(int target, int bound, int trials) { return getBinomial(target, bound, trials, source); } + /** + * Get a value, treating this as a set of binomial trials. + * + * Essentially, the system rolls a bound-sided dice trials times, and + * marks a success for every roll less than or equal to target. + * + * @param target + * The number to roll at or under. + * @param bound + * The maximum roll value. + * @param trials + * The number of times to roll. + * @param rn + * The Random instance to use. + * @return The value at the index corresponding to the number of + * successes. + */ public E getBinomial(int target, int bound, int trials, Random rn) { - if(values.getSize() == 0) return null; + if (values.getSize() == 0) return null; int numSuc = 0; - for(int i = 0; i < trials; i++) { - /* + for (int i = 0; i < trials; i++) { + /* * Adjust for zero, because it's easy to think of this * as rolling a bound-sided dice and marking a success * for every roll less than or equal to target. */ int num = rn.nextInt(bound) + 1; - if(num <= target) { + if (num <= target) { //System.err.printf("\t\tTRACE: mark binomial success (%d <= 1d%d, %d)\n", target, bound, num); numSuc += 1; } @@ -174,7 +234,7 @@ public class WeightedRandom<E> { //System.err.printf("\tTRACE: got %d success for binomial trials (%d <= 1d%d, %d times)\n", numSuc, target, bound, trials); IPair<Integer, E> val = values.getByIndex(Math.min(numSuc, values.getSize() - 1)); - if(exhaust) { + if (exhaust) { totalChance -= val.getLeft(); values.removeMatching(val); @@ -183,9 +243,14 @@ public class WeightedRandom<E> { return val.getRight(); } + /** + * Return a new WeightedRandom that is exhaustible (only returns one value once). + * + * @return A new WeightedRandom that is exhaustible. + */ public WeightedRandom<E> exhaustible() { IList<IPair<Integer, E>> lst = new FunctionalList<>(); - for(IPair<Integer, E> val : values) { + for (IPair<Integer, E> val : values) { lst.add(val); } diff --git a/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java b/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java new file mode 100644 index 0000000..83b391b --- /dev/null +++ b/base/src/main/java/bjc/utils/ioutils/LevelSplitter.java @@ -0,0 +1,274 @@ +package bjc.utils.ioutils; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Splits a string on a delimiter, respecting grouping delimiters. + * + * By default, grouping delimiters are (), [], {}, and <>, as well as single and + * double quoted strings. + * + * @author bjculkin + * + */ +public class LevelSplitter { + /** + * Defaultly configured level splitter. + */ + public final static LevelSplitter def = new LevelSplitter(); + + /** + * Check if a string contains any one of a specified number of things, + * respecting groups. + * + * @param haystack + * The string to look in. + * @param needles + * The strings to look for. + * @return Whether or not any of the strings were contained outside of + * groups. + */ + public boolean levelContains(String haystack, String... needles) { + int nestLevel = 0; + int i = 0; + + boolean prevCharWasSlash = false; + boolean inString = false; + + char stringEnder = ' '; + + while (i < haystack.length()) { + if (inString == false && nestLevel == 0) { + for (String needle : needles) { + if (haystack.regionMatches(i, needle, 0, needle.length())) { + return true; + } + } + } + + if (inString) { + if (prevCharWasSlash == true) { + prevCharWasSlash = false; + } else if (haystack.charAt(i) == stringEnder) { + inString = false; + } + } else { + switch (haystack.charAt(i)) { + case '\'': + inString = true; + stringEnder = '\''; + break; + case '\"': + inString = true; + stringEnder = '\"'; + break; + case '(': + case '[': + case '{': + case '<': + nestLevel += 1; + break; + case ')': + case ']': + case '}': + case '>': + nestLevel = Math.max(0, nestLevel - 1); + break; + } + } + + i += 1; + } + + return false; + } + + /** + * Split a string, respecting groups. + * + * @param phrase + * The string to split. + * @param splits + * The strings to split on. + * @return A list of split strings. If keepDelims is true, it also + * includes the delimiters in between the split strings. + */ + public List<String> levelSplit(String phrase, String... splits) { + return levelSplit(phrase, false, splits); + } + + /** + * Split a string, respecting groups. + * + * @param phrase + * The string to split. + * @param keepDelims + * Whether or not to include the delimiters in the + * results. + * @param splits + * The strings to split on. + * @return A list of split strings. If keepDelims is true, it also + * includes the delimiters in between the split strings. + */ + public List<String> levelSplit(String phrase, boolean keepDelims, String... splits) { + String work = phrase; + + List<String> strangs = new ArrayList<>(); + + int nestLevel = 0; + int i = 0; + + boolean prevCharWasSlash = false; + boolean inString = false; + + char stringEnder = ' '; + + // Shortcut empty strings + if (phrase.equals("")) { + strangs.add(""); + + return strangs; + } + + while (i < work.length()) { + if (inString == false && nestLevel == 0) { + for (String split : splits) { + if (work.regionMatches(i, split, 0, split.length())) { + strangs.add(work.substring(0, i)); + + if (keepDelims) strangs.add(split); + + work = work.substring(i + split.length()); + i = 0; + + continue; + } + } + } + + if (inString) { + if (prevCharWasSlash == true) { + prevCharWasSlash = false; + } else if (work.charAt(i) == stringEnder) { + inString = false; + } + } else { + /* + * @TODO Ben Culkin 9/4/18 + * + * This currently crashes if the string ends + * with one of the delimiters in question. + */ + switch (work.charAt(i)) { + case '\'': + inString = true; + stringEnder = '\''; + break; + case '\"': + inString = true; + stringEnder = '\"'; + break; + case '(': + case '[': + case '{': + case '<': + nestLevel += 1; + break; + case ')': + case ']': + case '}': + case '>': + nestLevel = Math.max(0, nestLevel - 1); + break; + } + } + + i += 1; + } + + strangs.add(work); + + return strangs; + } + + // @TODO @FIXME + // + // This doesn't seem like its working + @SuppressWarnings("javadoc") + public List<String> levelSplitRX(String phrase, String patt) { + return levelSplit(phrase, false, patt); + } + + @SuppressWarnings("javadoc") + public List<String> levelSplitRX(String phrase, boolean keepDelims, String patt) { + Pattern pat = Pattern.compile(patt); + + String work = phrase; + Matcher mat = pat.matcher(work); + + List<String> strangs = new ArrayList<>(); + + int nestLevel = 0; + int i = 0; + + boolean prevCharWasSlash = false; + boolean inString = false; + + char stringEnder = ' '; + + while (i < work.length()) { + if (inString == false && nestLevel == 0) { + if (mat.find(i)) { + strangs.add(work.substring(0, i)); + if (keepDelims) strangs.add(mat.group()); + work = work.substring(mat.end()); + i = 0; + + mat = pat.matcher(work); + + continue; + } + } + + if (inString) { + if (prevCharWasSlash == true) { + prevCharWasSlash = false; + } else if (work.charAt(i) == stringEnder) { + inString = false; + } + } else { + switch (work.charAt(i)) { + case '\'': + inString = true; + stringEnder = '\''; + break; + case '\"': + inString = true; + stringEnder = '\"'; + break; + case '(': + case '[': + case '{': + case '<': + nestLevel += 1; + break; + case ')': + case ']': + case '}': + case '>': + nestLevel = Math.max(0, nestLevel - 1); + break; + } + } + + i += 1; + } + + strangs.add(work); + + return strangs; + } +} diff --git a/base/src/main/java/bjc/utils/ioutils/MirrorDB.java b/base/src/main/java/bjc/utils/ioutils/MirrorDB.java index 1f60059..1010fd6 100644 --- a/base/src/main/java/bjc/utils/ioutils/MirrorDB.java +++ b/base/src/main/java/bjc/utils/ioutils/MirrorDB.java @@ -1,8 +1,6 @@ package bjc.utils.ioutils; import java.io.InputStream; -import java.io.IOException; - import java.util.HashMap; import java.util.Map; import java.util.Scanner; @@ -12,9 +10,19 @@ import java.util.Scanner; // What to do about one-to-many mirrored mappings? // // Currently, we pick the one with the latest codepoint + +/** + * A database for describing mirrored characters. + * + * @author bjculkin + * + */ public class MirrorDB { private Map<String, String> mirrored; + /** + * Create a new database of mirrored characters. + */ public MirrorDB() { mirrored = new HashMap<>(); @@ -47,10 +55,24 @@ public class MirrorDB { } } + /** + * Check if a string can be mirrored. + * + * @param mir + * The string to check for mirroring. + * @return Whether or not the given string can be mirrored. + */ public boolean canMirror(String mir) { return mirrored.containsKey(mir); } + /** + * Mirror a string. + * + * @param mir + * The string to mirror. + * @return The mirrored version of the string. + */ public String mirror(String mir) { return mirrored.get(mir); } diff --git a/base/src/main/java/bjc/utils/ioutils/ReportWriter.java b/base/src/main/java/bjc/utils/ioutils/ReportWriter.java index 647d4fe..4eb5aef 100644 --- a/base/src/main/java/bjc/utils/ioutils/ReportWriter.java +++ b/base/src/main/java/bjc/utils/ioutils/ReportWriter.java @@ -5,29 +5,46 @@ import java.io.Writer; import bjc.utils.esodata.DefaultList; +/** + * A writer with support for some formatting operations, such as autoindentation + * and pagination. + * + * @author bjculkin + * + */ public class ReportWriter extends Writer { + /* + * Storage of indentation values. + */ private static class IndentVal { + // # of character positions indentStr occupies public int indentStrPos; + // String that is printed for the indent. public String indentStr; + // Indent string w/ tabs replaced with spaces public String indentStrSpacedTabs; public IndentVal() { } } + // Writer to print to private Writer contained; - // # of character positions indentStr occupies + // Current indentation level private int indentLevel; + // Current # of columns the indentation occupies private int indentPos = 0; + // The indentation values to use private DefaultList<IndentVal> iVals; - private IndentVal defIVal; + // The default indentation value. + private IndentVal defIVal; // # of char. positions to the tab - private int tabEqv = 8; - // @NOTE 9/17/19 + private int tabEqv = 8; + // @NOTE 9/17/18 // // Consider adding support for both the vertical tab, and variable tab // stops. @@ -35,86 +52,192 @@ public class ReportWriter extends Writer { // For variable tab stops, decide between a set of numbers saying 'This // level tab is counted as X spaces' and a set of numbers saying 'A tab // advances to the next tab stop that has not been passed' + + // The total count of lines printed private int linesWritten = 0; - private int linePos = 0; + // The current position in the line + private int linePos = 0; + // The number of newlines to print for every newline encountered. private int lineSpacing = 1; - private int pageLine = 0; - private int pageNum = 0; + // The current line on the page + private int pageLine = 0; + // The current page number + private int pageNum = 0; + // The number of lines per page private int linesPerPage = 20; + // Whether or not to print tabs as spaces. private boolean printTabsAsSpaces; + // Whether or not the last character was a newline private boolean lastCharWasNL; - private char lastChar; + // The last character encountered + private char lastChar; // Really wish java had public `readonly` properties. I wouldn't even // care if that was a restriction that was only enforced by the compiler + + /** + * Get the current indent level. + * + * @return The current indent level. + */ public int getLevel() { return indentLevel; } + /** + * Get the current line-spacing. + * + * This is the number of blank lines to print out every time a blank + * line is encountered in the input, and is set to 1 by default. + * + * @return The current line spacing. + */ public int getLineSpacing() { return lineSpacing; } + /** + * Get the current line on the page. + * + * @return The current line on the page. + */ public int getPageLine() { return pageLine; } + /** + * Get the current page number. + * + * @return The current page number. + */ public int getPageNum() { return pageNum; } + /** + * Get the number of lines per page. + * + * @return The number of lines per page. + */ public int getLinesPerPage() { return linesPerPage; } + /** + * Get the current indent position. + * + * This is the count of columns the indentation occupies. + * + * @return The current indent position. + */ public int getIndentPos() { return indentPos; } + /** + * Get the string of the default indentation value. + * + * @return The string for the default indentation value. + */ public String getString() { return defIVal.indentStr; } + /** + * Get the string of a specific indentation value. + * + * @param lvl + * The level to get the value for. + * @return The string for the specified indentation value. + */ public String getString(int lvl) { return iVals.get(lvl).indentStr; } + /** + * Get the number of spaces to a tab. + * + * @return The number of spaces to a tab. + */ public int getTabEqv() { return tabEqv; } + /** + * Get the total number of lines written. + * + * @return The total number of lines written. + */ public int getLinesWritter() { return linesWritten; } + /** + * Get the current position in the line. + * + * @return The current position in the line. + */ public int getLinePos() { return linePos; } + /** + * Get the last character printed. + * + * @return The last character printed. + */ public char getLastChar() { return lastChar; } + /** + * Get the contained writer. + * + * @return The contained writer. + */ public Writer getWriter() { return contained; } + /** + * Check if the last character was a newline. + * + * @return Was the last character a new line? + */ public boolean isLastCharNL() { return lastCharWasNL; } + /** + * Check if tabs are being printed as spaces. + * + * @return Are tabs being printed as spaces? + */ public boolean isPrintingTabsAsSpaces() { return printTabsAsSpaces; } + /** + * Set the line spacing. + * + * @param spacing + * The number of lines to print for every blank line + * encountered. + */ public void setLineSpacing(int spacing) { lineSpacing = spacing; } + /** + * Set whether tabs are being printed as spaces. + * + * @param tabsAsSpaces + * Whether to print tabs as spaces. + */ public void setPrintTabsAsSpaces(boolean tabsAsSpaces) { printTabsAsSpaces = tabsAsSpaces; @@ -122,6 +245,12 @@ public class ReportWriter extends Writer { refreshIndents(-1); } + /** + * Set the number of lines per page. + * + * @param lines + * The number of lines per page. + */ public void setLinesPerPage(int lines) { linesPerPage = lines; @@ -141,10 +270,22 @@ public class ReportWriter extends Writer { } } + /** + * Set the current indentation level. + * + * @param level + * The indentation level. + */ public void setLevel(int level) { indentLevel = level; } + /** + * Set the current amount of spaces per tab. + * + * @param eqv + * The amount of spaces per tab. + */ public void setTabEqv(int eqv) { tabEqv = eqv; @@ -157,12 +298,30 @@ public class ReportWriter extends Writer { // Weirdness may occur if the indent string has a // newline in it, since that newline won't be considered // to exist by the IndentWriter + + /** + * Set the default indentation string to use. + * + * NOTE: Using a string that contains a newline may cause weirdness of + * various sorts to happen. + * + * @param str + * The string to use for default indentation. + */ public void setString(String str) { defIVal.indentStr = str; refreshIndents(-2); } + /** + * Set the indentation string for a specific indentation level. + * + * @param lvl + * The level to set the indentation string for. + * @param str + * The indentation string to use. + */ public void setString(int lvl, String str) { iVals.get(lvl).indentStr = str; @@ -174,6 +333,14 @@ public class ReportWriter extends Writer { // Pass a index to refresh that level // Pass -1 to refresh all indexes // Pass -2 to refresh the default index + /** + * Refresh the indentation settings. + * + * @param lvl + * The level of indents to refresh. Passing a number >= 0 + * refreshes that level, -1 refreshes every level, and -2 + * refreshes just the default indentation. + */ private void refreshIndents(int lvl) { if (lvl == -2) { refreshIndent(defIVal); @@ -181,21 +348,24 @@ public class ReportWriter extends Writer { for (IndentVal ival : iVals) { refreshIndent(ival); } + + refreshIndent(defIVal); } else { refreshIndent(iVals.get(lvl)); } } + // Refresh an indent val to respect current settings private void refreshIndent(IndentVal vl) { vl.indentStrPos = 0; int indentLength = vl.indentStr.length(); StringBuilder conv = new StringBuilder(); - for(int i = 0; i < indentLength; i++) { + for (int i = 0; i < indentLength; i++) { char c = vl.indentStr.charAt(i); - if(c == '\t') { - for(int j = 0; j < tabEqv; j++) { + if (c == '\t') { + for (int j = 0; j < tabEqv; j++) { conv.append(' '); } @@ -209,25 +379,30 @@ public class ReportWriter extends Writer { vl.indentStrSpacedTabs = conv.toString(); } + /** + * Duplicate this writers settings. + * @param contents The internal writer to use. + * @return A new writer, sharing this ones settings, but writing to the provided Writer instead. + */ public ReportWriter duplicate(Writer contents) { ReportWriter rw = new ReportWriter(contents); - rw.iVals = iVals; - rw.defIVal = defIVal; + rw.iVals = iVals; + rw.defIVal = defIVal; rw.indentLevel = indentLevel; - rw.indentPos = indentPos; + rw.indentPos = indentPos; rw.tabEqv = tabEqv; rw.linesWritten = linesWritten; - rw.linePos = linePos; - rw.lineSpacing = lineSpacing; + rw.linePos = linePos; + rw.lineSpacing = lineSpacing; rw.printTabsAsSpaces = printTabsAsSpaces; - rw.pageLine = pageLine; - rw.pageNum = pageNum; + rw.pageLine = pageLine; + rw.pageNum = pageNum; rw.linesPerPage = linesPerPage; // @NOTE 9/5/18 @@ -238,10 +413,20 @@ public class ReportWriter extends Writer { return rw; } + /** + * Create a new ReportWriter. + * @param write The place to write to. + */ public ReportWriter(Writer write) { this(write, 0, "\t"); } + /** + * Create a new ReportWriter with the specified default indentation values. + * @param write The place to write to. + * @param level The current indentation level. + * @param indentStr The indentation string. + */ public ReportWriter(Writer write, int level, String indentStr) { super(); @@ -250,19 +435,30 @@ public class ReportWriter extends Writer { indentLevel = level; defIVal = new IndentVal(); - iVals = new DefaultList<>(defIVal); + iVals = new DefaultList<>(defIVal); setString(indentStr); } + /** + * Indent a specific number of levels. + * @param lvl The number of levels to indent. + */ public void indent(int lvl) { indentLevel += lvl; } + /** + * Indent one level. + */ public void indent() { indent(1); } + /** + * Dedent a specific number of levels. + * @param lvl The number of levels to dedent. + */ public void dedent(int lvl) { // @NOTE 9/5/18 // @@ -271,10 +467,18 @@ public class ReportWriter extends Writer { indentLevel = Math.max(0, indentLevel - lvl); } + /** + * Dedent 1 level. + */ public void dedent() { dedent(1); } + /** + * Writes a buffer to the output, then clears it. + * @param sb The buffer to write and clear. + * @throws IOException If something goes wrong writing the buffer. + */ public void writeBuffer(StringBuffer sb) throws IOException { write(sb.toString()); @@ -289,14 +493,14 @@ public class ReportWriter extends Writer { // next page, or just printing the actual form-feed and hoping whatever // reading software handles it properly private void writePage() { - pageNum += 1; + pageNum += 1; pageLine -= linesPerPage; } private void writeNL(char c) throws IOException { // Count lines written linesWritten += lineSpacing; - pageLine += lineSpacing; + pageLine += lineSpacing; lastCharWasNL = true; @@ -317,41 +521,40 @@ public class ReportWriter extends Writer { writePage(); } - - linePos = 0; + linePos = 0; indentPos = 0; } @Override public void write(char[] cbuf, int off, int len) throws IOException { // Skip empty writes - if(len == 0) return; + if (len == 0) return; // Last character was a new line, print the indent string - if(lastCharWasNL) { + if (lastCharWasNL) { lastCharWasNL = false; printIndents(); } - for(int i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { int idx = i + off; char c = cbuf[idx]; - if(c == '\n' || c == '\r' || (c == '\n' && lastChar != '\r') || c == '\f') { + if ((c == '\n' && lastChar != '\r') || c == '\n' || c == '\r' || c == '\f') { writeNL(c); } else { - if(lastCharWasNL) { + if (lastCharWasNL) { lastCharWasNL = false; printIndents(); } - if(c == '\t') { + if (c == '\t') { linePos += tabEqv; - for(int j = 0; j < tabEqv; j++) { + for (int j = 0; j < tabEqv; j++) { contained.write(' '); } } else { @@ -368,10 +571,11 @@ public class ReportWriter extends Writer { for (int j = 0; j < indentLevel; j++) { IndentVal ival = iVals.get(j); - if (printTabsAsSpaces) contained.write(ival.indentStrSpacedTabs); - else contained.write(ival.indentStr); + if (printTabsAsSpaces) + contained.write(ival.indentStrSpacedTabs); + else contained.write(ival.indentStr); - linePos += ival.indentStrPos; + linePos += ival.indentStrPos; indentPos += ival.indentStrPos; } } diff --git a/base/src/main/java/bjc/utils/ioutils/blocks/Block.java b/base/src/main/java/bjc/utils/ioutils/blocks/Block.java index 61d473c..bf0257e 100644 --- a/base/src/main/java/bjc/utils/ioutils/blocks/Block.java +++ b/base/src/main/java/bjc/utils/ioutils/blocks/Block.java @@ -27,19 +27,26 @@ public class Block { */ public final int blockNo; + /** + * The line offset number for this block. + * + * Essentially, this is the absolute number of lines that this block is + * into whatever source it came from, where as startLine and endLine are + * relative to the BlockReader this Block is from. + */ public int lineOffset; /** * Create a new block. * * @param blockNo - * The number of this block. + * The number of this block. * @param contents - * The contents of this block. + * The contents of this block. * @param startLine - * The line this block started on. + * The line this block started on. * @param endLine - * The line this block ended. + * The line this block ended. */ public Block(final int blockNo, final String contents, final int startLine, final int endLine) { this.contents = contents; @@ -49,50 +56,16 @@ public class Block { } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + blockNo; - result = prime * result + (contents == null ? 0 : contents.hashCode()); - result = prime * result + endLine; - result = prime * result + startLine; - - return result; - } - - @Override - public boolean equals(final Object obj) { - if(this == obj) return true; - if(obj == null) return false; - if(!(obj instanceof Block)) return false; - - final Block other = (Block) obj; - - if(blockNo != other.blockNo) return false; - - if(contents == null) { - if(other.contents != null) return false; - } else if(!contents.equals(other.contents)) return false; - - if(endLine != other.endLine) return false; - if(startLine != other.startLine) return false; - - return true; - } - - @Override public String toString() { - if(lineOffset != -1) { + if (lineOffset != -1) { String fmt = "Block #%d (from lines %d (%d) to %d (%d)), length: %d characters"; - return String.format(fmt, blockNo, startLine + lineOffset, - startLine, endLine + lineOffset, + return String.format(fmt, blockNo, startLine + lineOffset, startLine, endLine + lineOffset, endLine + lineOffset, contents.length()); - } else { - String fmt = "Block #%d (from lines %d to %d), length: %d characters"; - - return String.format(fmt, blockNo, startLine, endLine, contents.length()); } + + String fmt = "Block #%d (from lines %d to %d), length: %d characters"; + + return String.format(fmt, blockNo, startLine, endLine, contents.length()); } } diff --git a/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java b/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java index 02483c1..66ebd66 100644 --- a/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java +++ b/base/src/main/java/bjc/utils/ioutils/blocks/SerialBlockReader.java @@ -2,6 +2,7 @@ package bjc.utils.ioutils.blocks; import java.io.IOException; import java.util.Deque; +import java.util.LinkedList; /** * Provides a means of concatenating two block readers. @@ -21,6 +22,8 @@ public class SerialBlockReader implements BlockReader { * The readers to pull from, in the order to pull from them. */ public SerialBlockReader(final BlockReader... readers) { + readerQueue = new LinkedList<>(); + for(final BlockReader reader : readers) { readerQueue.add(reader); } diff --git a/base/src/main/java/bjc/utils/math/NumberUtils.java b/base/src/main/java/bjc/utils/math/NumberUtils.java index 5c8ec7e..7dc2ff3 100644 --- a/base/src/main/java/bjc/utils/math/NumberUtils.java +++ b/base/src/main/java/bjc/utils/math/NumberUtils.java @@ -436,6 +436,7 @@ public class NumberUtils { StringBuilder pad = new StringBuilder(); if(work.length() < mincols) { + @SuppressWarnings("unused") int padCount = 0; for(int i = work.length(); i < mincols; i++) { // @NOTE 9/6/18 :CommaPad diff --git a/base/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java b/base/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java index 2a565f2..1ca0fc1 100644 --- a/base/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java +++ b/base/src/main/java/bjc/utils/parserutils/splitter/ConfigurableTokenSplitter.java @@ -16,15 +16,15 @@ import bjc.utils.funcdata.IList; * */ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { - private final Set<String> simpleDelimiters; - private final Set<String> multipleDelimiters; - private final Set<String> rRawDelimiters; + private final Set<String> simpleDelimiters; + private final Set<String> multipleDelimiters; + private final Set<String> rRawDelimiters; /** * Create a new token splitter with blank configuration. * * @param keepDelims - * Whether or not to keep delimiters. + * Whether or not to keep delimiters. */ public ConfigurableTokenSplitter(final boolean keepDelims) { super(null, keepDelims); @@ -35,16 +35,25 @@ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { rRawDelimiters = new LinkedHashSet<>(); } + private ConfigurableTokenSplitter(boolean keepDelims, Set<String> simpleDelimiters, + Set<String> multipleDelimiters, Set<String> rRawDelimiters) { + super(null, keepDelims); + + this.simpleDelimiters = simpleDelimiters; + this.multipleDelimiters = multipleDelimiters; + this.rRawDelimiters = rRawDelimiters; + } + /** * Add a set of simple delimiters to this splitter. * * Simple delimiters match one occurrence of themselves as literals. * * @param simpleDelims - * The simple delimiters to add. + * The simple delimiters to add. */ public void addSimpleDelimiters(final String... simpleDelims) { - for(final String simpleDelim : simpleDelims) { + for (final String simpleDelim : simpleDelims) { simpleDelimiters.add(simpleDelim); } } @@ -56,10 +65,10 @@ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { * literals. * * @param multiDelims - * The multiple delimiters to add. + * The multiple delimiters to add. */ public void addMultiDelimiters(final String... multiDelims) { - for(final String multiDelim : multiDelims) { + for (final String multiDelim : multiDelims) { multipleDelimiters.add(multiDelim); } } @@ -71,10 +80,10 @@ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { * expressions. * * @param rRawDelims - * The raw delimiters to add. + * The raw delimiters to add. */ public void addRawDelimiters(final String... rRawDelims) { - for(final String rRawDelim : rRawDelims) { + for (final String rRawDelim : rRawDelims) { rRawDelimiters.add(rRawDelim); } } @@ -86,15 +95,15 @@ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { public void compile() { final StringBuilder rPattern = new StringBuilder(); - for(final String rRawDelimiter : rRawDelimiters) { + for (final String rRawDelimiter : rRawDelimiters) { rPattern.append(applyFormat("rawDelim", rRawDelimiter)); } - for(final String multipleDelimiter : multipleDelimiters) { + for (final String multipleDelimiter : multipleDelimiters) { rPattern.append(applyFormat("multipleDelim", multipleDelimiter)); } - for(final String simpleDelimiter : simpleDelimiters) { + for (final String simpleDelimiter : simpleDelimiters) { rPattern.append(applyFormat("simpleDelim", simpleDelimiter)); } @@ -105,7 +114,7 @@ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { @Override public IList<String> split(final String input) { - if(spliter == null) throw new IllegalStateException("Must compile splitter before use"); + if (spliter == null) throw new IllegalStateException("Must compile splitter before use"); return super.split(input); } @@ -117,36 +126,76 @@ public class ConfigurableTokenSplitter extends SimpleTokenSplitter { return String.format(fmt, simpleDelimiters, multipleDelimiters, rRawDelimiters, spliter); } - + + /** + * Builder class for the configurable token splitter. + * + * @author bjculkin + * + */ public static class Builder { private ConfigurableTokenSplitter cts; - + + /** + * Create a new splitter builder. + * + * @param keepDelims + * Whether or not to keep the delimited splitter. + */ public Builder(boolean keepDelims) { cts = new ConfigurableTokenSplitter(keepDelims); } - - public Builder simple(String...strings) { + + /** + * Add a set of simple delimiters. + * + * @param strings + * The simple delimiters to use. + * @return The builder, for chaining. + */ + public Builder simple(String... strings) { cts.addSimpleDelimiters(strings); - + return this; } - - public Builder multiple(String...strings) { + + /** + * Add a set of multiple delimiters. + * + * @param strings + * The multiple delimiters to use. + * @return The builder, for chaining. + */ + public Builder multiple(String... strings) { cts.addMultiDelimiters(strings); - + return this; } - - public Builder raw(String...strings) { + + /** + * Add a set of raw delimiters. + * + * @param strings + * The raw delimiters to use. + * @return The builder, for chaining. + */ + public Builder raw(String... strings) { cts.addRawDelimiters(strings); - + return this; } - + + /** + * Build the splitter. + * + * @return The built splitter. + */ public ConfigurableTokenSplitter build() { - cts.compile(); + ConfigurableTokenSplitter ret = new ConfigurableTokenSplitter(cts.keepDelim, + cts.simpleDelimiters, cts.multipleDelimiters, cts.rRawDelimiters); + ret.compile(); - return cts; + return ret; } } } diff --git a/base/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java b/base/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java index 4e97008..9eb2d48 100644 --- a/base/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java +++ b/base/src/main/java/bjc/utils/parserutils/splitter/SimpleTokenSplitter.java @@ -15,7 +15,7 @@ import bjc.utils.ioutils.RegexStringEditor; public class SimpleTokenSplitter implements TokenSplitter { protected Pattern spliter; - private final boolean keepDelim; + protected final boolean keepDelim; /** * Create a new simple token splitter. |
