internal bool ResolveStringsTo(StringStore store) { // If we've already resolved to this store, don't re-resolve if (store == this.LastResolvedStore) { return(this.LastResolveResult); } // Record we last resolved against this store and failed this.LastResolvedStore = store; this.LastResolveResult = false; // Look up symbol name *prefix* parts (all exact) for (int i = 0; i < this.SplitSymbolName8.Count - 1; ++i) { if (!store.TryFindString(this.SplitSymbolName8[i], this.IgnoreCase, out this.SymbolNamePrefixIdentifiers[i])) { return(false); } } // Look up symbol name suffix (exact only if IsFullSuffix) if (this.IsFullSuffix) { if (!store.TryFindString(this.SymbolNameSuffix, this.IgnoreCase, out this.SymbolNameSuffixIdentifiers)) { return(false); } } else { if (this.SymbolNameSuffix.IsEmpty()) { this.SymbolNameSuffixIdentifiers = Range.Max; } else { if (!store.TryGetRangeStartingWith(this.SymbolNameSuffix, out this.SymbolNameSuffixIdentifiers)) { return(false); } // NOTE: Can't make a prefix Range case sensitive, so have to validate casing later // Case-insensitive sort means you can have [..., array, Array, arrayList, ArrayList, ...], so no way to return case sensitive range starting with 'Array' } } // Look up parameters [and get the copy from the StringStore for fast comparison on signature] if (!store.TryFindString(this.Parameters8, this.IgnoreCase, out this.ParametersIdentifiers)) { return(false); } this.Parameters8 = store[this.ParametersIdentifiers.Start]; // If we found everything, record we succeeded this.LastResolveResult = true; return(true); }
private string MatchesForWordToString(MemberIndex index, StringStore strings, String8 word) { Range matches; if (!strings.TryFindString(word, out matches)) { return(String.Empty); } return(MatchesToString(index, matches)); }
private bool TryFindByPath(int parentNodeIndex, int currentPathPartIndex, String8Set path, StringStore strings, ref int matchingIndex) { // Try to find the string identifier for the next path part name Range currentPartIdentifier; if (!strings.TryFindString(path[currentPathPartIndex], out currentPartIdentifier)) { return(false); } // Try to find nodes matching this name part and search within each of them int child = this.GetFirstChild(parentNodeIndex); while (child > 0) { if (currentPartIdentifier.Contains(this.GetNameIdentifier(child))) { // If we've matched all parts, return success. if (currentPathPartIndex == path.Count - 1) { matchingIndex = child; return(true); } else { // Record that we matched up to this point matchingIndex = child; // If not, search under here for the remaining parts (for each match at this level) if (TryFindByPath(child, currentPathPartIndex + 1, path, strings, ref matchingIndex)) { return(true); } } } child = this.GetNextSibling(child); } return(false); }
public void StringStore_CaseSensitivity() { // Sample Strings: Not all in order, including casing differences, including duplicates StringStore store = new StringStore(); string[] strings = { "bool", "bool", "boolean", "Boolean", "BOOLEAN", "array", "Array", "aRRay", "ARRAY", "Array", "Collections", "ARR", "BIT" }; int[] addedIDs = new int[strings.Length]; // Add each value for (int i = 0; i < strings.Length; ++i) { addedIDs[i] = store.FindOrAddString(strings[i]); } // Verify each value comes back cased correctly (case sensitive add) for (int i = 0; i < strings.Length; ++i) { Assert.AreEqual(strings[i], store[addedIDs[i]].ToString()); } // Convert to Immutable store.ConvertToImmutable(); // Remap IDs for (int i = 0; i < strings.Length; ++i) { addedIDs[i] = store.GetSerializationIdentifier(addedIDs[i]); } // Verify each value comes back cased correctly (case sensitive values preserved on convert) for (int i = 0; i < strings.Length; ++i) { Assert.AreEqual(strings[i], store[addedIDs[i]].ToString()); } // Verify values have ascending IDs and are in case insensitive *stable* order string last = store[0].ToString(); for (int i = 1; i < store.Count; ++i) { string current = store[i].ToString(); // Verify all strings are in case insensitive order int cmp = string.Compare(last, current, StringComparison.OrdinalIgnoreCase); Assert.IsTrue(cmp <= 0); // Verify case-insensitive ties are in case sensitive order relative to each other if (cmp == 0) { Assert.IsTrue(string.Compare(last, current, StringComparison.Ordinal) < 0); } last = current; } // Verify searches return the range of capitalizations for the value byte[] buffer = new byte[20]; for (int i = 0; i < strings.Length; ++i) { String8 value8 = String8.Convert(strings[i], buffer); // Verify the string is found Range range; Assert.IsTrue(store.TryFindString(value8, out range)); // Verify the ID for the exact casing is reported within the range Assert.IsTrue(range.Contains(addedIDs[i])); // Verify every value in the range matches the value (case-insensitive) for (int j = range.Start; j <= range.End; ++j) { String8 otherMatch = store[j]; Assert.AreEqual(0, value8.CompareTo(otherMatch, true), String.Format("'{0}' in match range wasn't reported equal to '{1}' being matched", otherMatch, value8)); } // Verify the values just before and after the range don't match if (range.Start > 0) { String8 valueBefore = store[range.Start - 1]; Assert.IsTrue(value8.CompareTo(valueBefore, true) > 0, String.Format("'{0}' before match range wasn't reported before '{1}' being matched", valueBefore, value8)); } if (range.End < store.Count - 1) { String8 valueAfter = store[range.End + 1]; Assert.IsTrue(value8.CompareTo(valueAfter, true) < 0, String.Format("'{0}' after match range wasn't reported after '{1}' being matched", valueAfter, value8)); } // Ask for the case-sensitive range Range caseSensitive; Assert.IsTrue(store.TryFindString(value8, false, out caseSensitive)); // Verify every value in the range matches the value (case-sensitive) for (int j = caseSensitive.Start; j <= caseSensitive.End; ++j) { String8 otherMatch = store[j]; Assert.AreEqual(0, value8.CompareTo(otherMatch, false), String.Format("'{0}' in case sensitive range wasn't reported equal to '{1}' being matched", otherMatch, value8)); } // Verify the values just before and after the range don't match if (caseSensitive.Start > 0) { String8 valueBefore = store[caseSensitive.Start - 1]; Assert.IsTrue(value8.CompareTo(valueBefore, false) != 0, String.Format("'{0}' before case sensitive range still matches '{1}'", valueBefore, value8)); } if (caseSensitive.End < store.Count - 1) { String8 valueAfter = store[caseSensitive.End + 1]; Assert.IsTrue(value8.CompareTo(valueAfter, false) != 0, String.Format("'{0}' after case sensitive range still matches '{1}'", valueAfter, value8)); } } // Verify MakeCaseSensitive goes to empty if the provided casing isn't any of the values String8 BOOLean = String8.Convert("BOOLean", buffer); Range booleanRange; Assert.IsFalse(store.TryFindString(BOOLean, false, out booleanRange)); }