diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java index f9370317..5c2677e9 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java @@ -84,10 +84,40 @@ public class PrefixTree, L extends LookupEntry>{ this.resultFactory = resultFactory; } - public LookupEntry lookup(K[] keys, final boolean create){ + /** + * Look up without creating new nodes. + * @param keys + * @return + */ + public L lookup(final K[] keys){ + return lookup( keys, false); + } + + /** + * Look up without creating new nodes. + * @param keys + * @return + */ + public L lookup(final List keys){ + return lookup( keys, false); + } + + /** + * Look up sequence, if desired fill in the given sequence. + * @param keys + * @param create + * @return + */ + public L lookup(K[] keys, final boolean create){ return lookup(Arrays.asList(keys), create); } + /** + * Look up sequence, if desired fill in the given sequence. + * @param keys + * @param create + * @return + */ @SuppressWarnings("unchecked") public L lookup(final List keys, final boolean create){ N insertion = root; @@ -121,6 +151,80 @@ public class PrefixTree, L extends LookupEntry>{ } return resultFactory.newLookupEntry(node, insertion, depth, hasPrefix); } + + /** + * + * @param keys + * @return If already inside (not necessarily as former end point). + */ + public boolean feed(final List keys){ + final L result = lookup(keys, true); + return result.insertion == result.node; + } + + /** + * + * @param chars + * @return If already inside (not necessarily as former end point). + */ + public boolean feed(final K[] keys){ + return feed(Arrays.asList(keys)); + } + + /** + * Check if the tree has a prefix of keys. This does not mean a common prefix, but that the tree contains an end point that is a prefix of the input. + * @param keys + * @return + */ + public boolean hasPrefix(final List keys){ + return lookup(keys, false).hasPrefix; + } + + /** + * Check if the tree has a prefix of keys. This does not mean a common prefix, but that the tree contains an end point that is a prefix of the input. + * @param keys + * @return + */ + public boolean hasPrefix(final K[] keys){ + return hasPrefix(Arrays.asList(keys)); + } + + /** + * Check if the input is prefix of a path inside of the tree, need not be an end point. + * @param keys + * @return + */ + public boolean isPrefix(final List keys){ + return lookup(keys, false).depth == keys.size(); + } + + /** + * Check if the input is prefix of a path inside of the tree, need not be an end point. + * @param keys + * @return + */ + public boolean isPrefix(final K[] keys){ + return isPrefix(Arrays.asList(keys)); + } + + /** + * Check if the input is an inserted sequence (end point), but not necessarily a leaf. + * @param keys + * @return + */ + public boolean matches(final List keys){ + final L result = lookup(keys, false); + return result.node == result.insertion && result.insertion.isEnd; + } + + /** + * Check if the input is an inserted sequence (end point), but not necessarily a leaf. + * @param keys + * @return + */ + public boolean matches(final K[] keys){ + return matches(Arrays.asList(keys)); + } public void clear() { root = nodeFactory.newNode(null); diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimpleCharPrefixTree.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimpleCharPrefixTree.java new file mode 100644 index 00000000..0b4372ee --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimpleCharPrefixTree.java @@ -0,0 +1,97 @@ +package fr.neatmonster.nocheatplus.checks.chat.analysis.ds; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Adding some convenience methods. + * @author mc_dev + * + */ +public class SimpleCharPrefixTree extends SimplePrefixTree{ + + /** + * Auxiliary method to get a List of Character. + * @param chars + * @return + */ + public static final List toCharacterList(final char[] chars){ + final List characters = new ArrayList(chars.length); + for (int i = 0; i < chars.length; i++){ + characters.add(chars[i]); + } + return characters; + } + + /** + * + * @param chars + * @param create + * @return + */ + public SimpleLookupEntry lookup(final char[] chars, boolean create){ + return lookup(toCharacterList(chars), create); + } + + /** + * + * @param chars + * @param create + * @return + */ + public SimpleLookupEntry lookup(final String input, boolean create){ + return lookup(input.toCharArray(), create); + } + + /** + * + * @param chars + * @return If already inside (not necessarily as former end point). + */ + public boolean feed(final String input){ + return feed(input.toCharArray()); + } + + /** + * + * @param chars + * @return If already inside (not necessarily as former end point). + */ + public boolean feed(final char[] chars){ + return feed(toCharacterList(chars)); + } + + public void feedAll(final Collection inputs, boolean trim, boolean lowerCase){ + for (String input : inputs){ + if (trim) input = input.toLowerCase(); + if (lowerCase) input = input.toLowerCase(); + feed(input); + } + } + + public boolean hasPrefix(final char[] chars){ + return hasPrefix(toCharacterList(chars)); + } + + public boolean hasPrefix(final String input){ + return hasPrefix(input.toCharArray()); + } + + public boolean isPrefix(final char[] chars){ + return isPrefix(toCharacterList(chars)); + } + + public boolean isPrefix(final String input){ + return isPrefix(input.toCharArray()); + } + + public boolean matches(final char[] chars){ + return matches(toCharacterList(chars)); + } + + public boolean matches(final String input){ + return matches(input.toCharArray()); + } + +}