public void Test54TruncatingIteratorFromLinearMatchLong() { StringAndValue[] data = { new StringAndValue("abcdef", 10), new StringAndValue("abcdepq", 200), new StringAndValue("abcdeyz", 3000) }; CharsTrie trie = buildTrie(data, data.Length, TrieBuilderOption.Fast); // Go into a linear-match node. trie.Next('a'); trie.Next('b'); trie.Next('c'); // Truncate after the linear-match node. CharsTrieEnumerator iter = trie.GetEnumerator(3); StringAndValue[] expected = { new StringAndValue("def", 10), new StringAndValue("dep", -1), new StringAndValue("dey", -1) }; checkIterator(iter, expected); // Reset, and we should get the same result. Logln("after iter.Reset()"); checkIterator(iter.Reset(), expected); }
public void Test37LargeTrie() { CharsTrie trie = buildLargeTrie(1111); Generator gen = new Generator(); while (gen.countUniqueFirstChars() < 1111) { ICharSequence x = gen.GetString(); int value = gen.GetValue(); int index; if (x.Length == 0) { index = 0; } else { if (trie.First(x[0]) == Result.NoMatch) { Errln(String.Format("first(first char U+{0:x4})=BytesTrie.Result.NO_MATCH for string {1}\n", char.GetNumericValue(x[0]), gen.GetIndex())); break; } index = 1; } Result result = trie.Next(x, index, x.Length); if (!result.HasValue() || result != trie.Current || value != trie.GetValue()) { Errln(String.Format("next(" + Prettify(x) + ")!=hasValue or " + "next()!=current() or getValue() wrong " + "for string " + gen.GetIndex())); break; } gen.Next(); } }
public void Test50IteratorFromBranch() { CharsTrie trie = buildMonthsTrie(TrieBuilderOption.Fast); // Go to a branch node. trie.Next('j'); trie.Next('a'); trie.Next('n'); CharsTrieEnumerator iter = trie.GetEnumerator(); // Expected data: Same as in buildMonthsTrie(), except only the suffixes // following "jan". StringAndValue[] data = { new StringAndValue("", 1), new StringAndValue(".", 1), new StringAndValue("a", 1), new StringAndValue("bb", 1), new StringAndValue("c", 1), new StringAndValue("ddd", 1), new StringAndValue("ee", 1), new StringAndValue("ef", 1), new StringAndValue("f", 1), new StringAndValue("gg", 1), new StringAndValue("h", 1), new StringAndValue("iiii", 1), new StringAndValue("j", 1), new StringAndValue("kk", 1), new StringAndValue("kl", 1), new StringAndValue("kmm", 1), new StringAndValue("l", 1), new StringAndValue("m", 1), new StringAndValue("nnnnnnnnnnnnnnnnnnnnnnnnnnnn", 1), new StringAndValue("o", 1), new StringAndValue("pp", 1), new StringAndValue("qqq", 1), new StringAndValue("r", 1), new StringAndValue("uar", 1), new StringAndValue("uary", 1) }; checkIterator(iter, data); // Reset, and we should get the same result. Logln("after iter.Reset()"); checkIterator(iter.Reset(), data); }
private void checkFirst(CharsTrie trie, StringAndValue[] data, int dataLength) { for (int i = 0; i < dataLength; ++i) { if (data[i].s.Length == 0) { continue; // skip empty string } String expectedString = data[i].s; int c = expectedString[0]; int nextCp = expectedString.Length > 1 ? expectedString[1] : 0; Result firstResult = trie.First(c); int firstValue = firstResult.HasValue() ? trie.GetValue() : -1; Result nextResult = trie.Next(nextCp); if (firstResult != trie.Reset().Next(c) || firstResult != trie.Current || firstValue != (firstResult.HasValue() ? trie.GetValue() : -1) || nextResult != trie.Next(nextCp) ) { Errln(String.Format("trie.first(U+{0:X4})!=trie.Reset().Next(same) for {1}", c, data[i].s)); } c = expectedString.CodePointAt(0); int cLength = Character.CharCount(c); nextCp = expectedString.Length > cLength?expectedString.CodePointAt(cLength) : 0; firstResult = trie.FirstForCodePoint(c); firstValue = firstResult.HasValue() ? trie.GetValue() : -1; nextResult = trie.NextForCodePoint(nextCp); if (firstResult != trie.Reset().NextForCodePoint(c) || firstResult != trie.Current || firstValue != (firstResult.HasValue() ? trie.GetValue() : -1) || nextResult != trie.NextForCodePoint(nextCp) ) { Errln(String.Format("trie.firstForCodePoint(U+{0:X4})!=trie.Reset().NextForCodePoint(same) for {1}", c, data[i].s)); } } trie.Reset(); }
// next(string) is also tested in other functions, // but here we try to go partway through the string, and then beyond it. private void checkNextString(CharsTrie trie, StringAndValue[] data, int dataLength) { for (int i = 0; i < dataLength; ++i) { String expectedString = data[i].s; int stringLength = expectedString.Length; if (!trie.Next(expectedString, 0, stringLength / 2).Matches()) { Errln("trie.Next(up to middle of string)=BytesTrie.Result.NO_MATCH for " + data[i].s); continue; } // Test that we stop properly at the end of the string. trie.Next(expectedString, stringLength / 2, stringLength); if (trie.Next(0).Matches()) { Errln("trie.Next(string+NUL)!=BytesTrie.Result.NO_MATCH for " + data[i].s); } trie.Reset(); } }
public void Test41GetNextChars() { CharsTrie trie = buildMonthsTrie(TrieBuilderOption.Small); StringBuilder buffer = new StringBuilder(); int count = trie.GetNextChars(buffer); if (count != 2 || !"aj".ContentEquals(buffer)) { Errln("months getNextChars()!=[aj] at root"); } trie.Next('j'); trie.Next('a'); trie.Next('n'); // getNextChars() directly after next() buffer.Length = (0); count = trie.GetNextChars(buffer); if (count != 20 || !".abcdefghijklmnopqru".ContentEquals(buffer)) { Errln("months getNextChars()!=[.abcdefghijklmnopqru] after \"jan\""); } // getNextChars() after getValue() trie.GetValue(); // next() had returned BytesTrie.Result.INTERMEDIATE_VALUE. buffer.Length = (0); count = trie.GetNextChars(buffer); if (count != 20 || !".abcdefghijklmnopqru".ContentEquals(buffer)) { Errln("months getNextChars()!=[.abcdefghijklmnopqru] after \"jan\"+getValue()"); } // getNextChars() from a linear-match node trie.Next('u'); buffer.Length = (0); count = trie.GetNextChars(buffer); if (count != 1 || !"a".ContentEquals(buffer)) { Errln("months getNextChars()!=[a] after \"janu\""); } trie.Next('a'); buffer.Length = (0); count = trie.GetNextChars(buffer); if (count != 1 || !"r".ContentEquals(buffer)) { Errln("months getNextChars()!=[r] after \"janua\""); } trie.Next('r'); trie.Next('y'); // getNextChars() after a final match buffer.Length = (0); count = trie.GetNextChars(buffer); if (count != 0 || buffer.Length != 0) { Errln("months getNextChars()!=[] after \"january\""); } }
public void Test51IteratorFromLinearMatch() { CharsTrie trie = buildMonthsTrie(StringTrieBuilder.Option.SMALL); // Go into a linear-match node. trie.Next('j'); trie.Next('a'); trie.Next('n'); trie.Next('u'); trie.Next('a'); CharsTrie.Enumerator iter = trie.GetEnumerator(); // Expected data: Same as in buildMonthsTrie(), except only the suffixes // following "janua". StringAndValue[] data = { new StringAndValue("r", 1), new StringAndValue("ry", 1) }; checkIterator(iter, data); // Reset, and we should get the same result. Logln("after iter.Reset()"); checkIterator(iter.Reset(), data); }
public void Test40GetUniqueValue() { CharsTrie trie = buildMonthsTrie(TrieBuilderOption.Fast); long uniqueValue; if ((uniqueValue = trie.GetUniqueValue()) != 0) { Errln("unique value at root"); } trie.Next('j'); trie.Next('a'); trie.Next('n'); // getUniqueValue() directly after next() if ((uniqueValue = trie.GetUniqueValue()) != ((1 << 1) | 1)) { Errln("not unique value 1 after \"jan\": instead " + uniqueValue); } trie.First('j'); trie.Next('u'); if ((uniqueValue = trie.GetUniqueValue()) != 0) { Errln("unique value after \"ju\""); } if (trie.Next('n') != Result.IntermediateValue || 6 != trie.GetValue()) { Errln("not normal value 6 after \"jun\""); } // getUniqueValue() after getValue() if ((uniqueValue = trie.GetUniqueValue()) != ((6 << 1) | 1)) { Errln("not unique value 6 after \"jun\""); } // getUniqueValue() from within a linear-match node trie.First('a'); trie.Next('u'); if ((uniqueValue = trie.GetUniqueValue()) != ((8 << 1) | 1)) { Errln("not unique value 8 after \"au\""); } }
private void checkNextWithState(CharsTrie trie, StringAndValue[] data, int dataLength) { CharsTrieState noState = new CharsTrieState(), state = new CharsTrieState(); for (int i = 0; i < dataLength; ++i) { if ((i & 1) == 0) { try { trie.ResetToState(noState); Errln("trie.resetToState(noState) should throw an ArgumentException"); } catch (ArgumentException e) { // good } } String expectedString = data[i].s; int stringLength = expectedString.Length; int partialLength = stringLength / 3; for (int j = 0; j < partialLength; ++j) { if (!trie.Next(expectedString[j]).Matches()) { Errln("trie.Next()=BytesTrie.Result.NO_MATCH for a prefix of " + data[i].s); return; } } trie.SaveState(state); Result resultAtState = trie.Current; Result result; int valueAtState = -99; if (resultAtState.HasValue()) { valueAtState = trie.GetValue(); } result = trie.Next(0); // mismatch if (result != Result.NoMatch || result != trie.Current) { Errln("trie.Next(0) matched after part of " + data[i].s); } if (resultAtState != trie.ResetToState(state).Current || (resultAtState.HasValue() && valueAtState != trie.GetValue()) ) { Errln("trie.Next(part of " + data[i].s + ") changes current()/getValue() after " + "saveState/next(0)/resetToState"); } else if (!(result = trie.Next(expectedString, partialLength, stringLength)).HasValue() || result != trie.Current) { Errln("trie.Next(rest of " + data[i].s + ") does not seem to contain " + data[i].s + " after " + "saveState/next(0)/resetToState"); } else if (!(result = trie.ResetToState(state). Next(expectedString, partialLength, stringLength)).HasValue() || result != trie.Current) { Errln("trie does not seem to contain " + data[i].s + " after saveState/next(rest)/resetToState"); } else if (trie.GetValue() != data[i].value) { Errln(String.Format("trie value for {0} is {1}=0x{2:x} instead of expected {3}=0x{4:x}", data[i].s, trie.GetValue(), trie.GetValue(), data[i].value, data[i].value)); } trie.Reset(); } }
private void checkNext(CharsTrie trie, StringAndValue[] data, int dataLength) { CharsTrieState state = new CharsTrieState(); for (int i = 0; i < dataLength; ++i) { String expectedString = data[i].s; int stringLength = expectedString.Length; Result result; if (!(result = trie.Next(expectedString, 0, stringLength)).HasValue() || result != trie.Current ) { Errln("trie does not seem to contain " + data[i].s); } else if (trie.GetValue() != data[i].value) { Errln(String.Format("trie value for {0} is {1}=0x{2:x} instead of expected {3}=0x{4:x}", data[i].s, trie.GetValue(), trie.GetValue(), data[i].value, data[i].value)); } else if (result != trie.Current || trie.GetValue() != data[i].value) { Errln("trie value for " + data[i].s + " changes when repeating current()/getValue()"); } trie.Reset(); result = trie.Current; for (int j = 0; j < stringLength; ++j) { if (!result.HasNext()) { Errln(String.Format("trie.Current!=hasNext before end of {0} (at index {1})", data[i].s, j)); break; } if (result == Result.IntermediateValue) { trie.GetValue(); if (trie.Current != Result.IntermediateValue) { Errln(String.Format("trie.getValue().Current!=Result.INTERMEDIATE_VALUE " + "before end of {0} (at index {1})", data[i].s, j)); break; } } result = trie.Next(expectedString[j]); if (!result.Matches()) { Errln(String.Format("trie.Next()=Result.NO_MATCH " + "before end of {0} (at index {1})", data[i].s, j)); break; } if (result != trie.Current) { Errln(String.Format("trie.Next()!=following current() " + "before end of {0} (at index {1})", data[i].s, j)); break; } } if (!result.HasValue()) { Errln("trie.Next()!=hasValue at the end of " + data[i].s); continue; } trie.GetValue(); if (result != trie.Current) { Errln("trie.Current != current()+getValue()+current() after end of " + data[i].s); } // Compare the final current() with whether next() can actually continue. trie.SaveState(state); bool nextContinues = false; for (int c = 0x20; c < 0xe000; ++c) { if (c == 0x80) { c = 0xd800; // Check for ASCII and surrogates but not all of the BMP. } if (trie.ResetToState(state).Next(c).Matches()) { nextContinues = true; break; } } if ((result == Result.IntermediateValue) != nextContinues) { Errln("(trie.Current==BytesTrie.Result.INTERMEDIATE_VALUE) contradicts " + "(trie.Next(some char)!=BytesTrie.Result.NO_MATCH) after end of " + data[i].s); } trie.Reset(); } }