public override void Write(StringTrieBuilder builder) { next.Write(builder); #pragma warning disable 612, 618 offset = builder.WriteValueAndFinal(value, false); #pragma warning restore 612, 618 }
public override Node Register(StringTrieBuilder builder) { next = next.Register(builder); // Break the linear-match sequence into chunks of at most kMaxLinearMatchLength. #pragma warning disable 612, 618 int maxLinearMatchLength = builder.MaxLinearMatchLength; #pragma warning restore 612, 618 while (length > maxLinearMatchLength) { int nextOffset = stringOffset + length - maxLinearMatchLength; length -= maxLinearMatchLength; LinearMatchNode suffixNode = new LinearMatchNode(strings, nextOffset, maxLinearMatchLength, next); suffixNode.SetHashCode(); next = builder.RegisterNode(suffixNode); } Node result; #pragma warning disable 612, 618 if (hasValue && !builder.MatchNodesCanHaveValues) #pragma warning restore 612, 618 { int intermediateValue = value; value = 0; hasValue = false; SetHashCode(); result = new IntermediateValueNode(intermediateValue, builder.RegisterNode(this)); } else { SetHashCode(); result = this; } return(builder.RegisterNode(result)); }
private Node Register(StringTrieBuilder builder, int start, int limit) { int length = limit - start; #pragma warning disable 612, 618 if (length > builder.MaxBranchLinearSubNodeLength) #pragma warning restore 612, 618 { // Branch on the middle unit. int middle = start + length / 2; return(builder.RegisterNode( new SplitBranchNode( chars[middle], Register(builder, start, middle), Register(builder, middle, limit)))); } ListBranchNode listNode = new ListBranchNode(length); do { char c = chars[start]; Node node = equal[start]; if (node.GetType() == typeof(ValueNode)) { // Final value. listNode.Add(c, ((ValueNode)node).Value); } else { listNode.Add(c, node.Register(builder)); } } while (++start < limit); return(builder.RegisterNode(listNode)); }
public override Node Add(StringTrieBuilder builder, ICharSequence s, int start, int sValue) { if (start == s.Length) { if (hasValue) { throw new ArgumentException("Duplicate string."); } else { SetValue(sValue); return(this); } } char c = s[start++]; int i = Find(c); if (i < chars.Length && c == chars[i]) { equal[i] = equal[i].Add(builder, s, start, sValue); } else { chars.Insert(i, c); equal.Insert(i, builder.CreateSuffixNode(s, start, sValue)); } return(this); }
public override void Write(StringTrieBuilder builder) { next.Write(builder); #pragma warning disable 612, 618 builder.Write(stringOffset, length); offset = builder.WriteValueAndType(hasValue, value, builder.MinLinearMatch + length - 1); #pragma warning restore 612, 618 }
public override void Write(StringTrieBuilder builder) { // Write the sub-nodes in reverse order: The jump lengths are deltas from // after their own positions, so if we wrote the minUnit sub-node first, // then its jump delta would be larger. // Instead we write the minUnit sub-node last, for a shorter delta. int unitNumber = length - 1; Node rightEdge = equal[unitNumber]; int rightEdgeNumber = rightEdge == null ? firstEdgeNumber : rightEdge.Offset; do { --unitNumber; if (equal[unitNumber] != null) { equal[unitNumber].WriteUnlessInsideRightEdge(firstEdgeNumber, rightEdgeNumber, builder); } } while (unitNumber > 0); // The maxUnit sub-node is written as the very last one because we do // not jump for it at all. unitNumber = length - 1; if (rightEdge == null) { #pragma warning disable 612, 618 builder.WriteValueAndFinal(values[unitNumber], true); #pragma warning restore 612, 618 } else { rightEdge.Write(builder); } #pragma warning disable 612, 618 offset = builder.Write(units[unitNumber]); #pragma warning restore 612, 618 // Write the rest of this node's unit-value pairs. while (--unitNumber >= 0) { int value; bool isFinal; if (equal[unitNumber] == null) { // Write the final value for the one string ending with this unit. value = values[unitNumber]; isFinal = true; } else { // Write the delta to the start position of the sub-node. Debug.Assert(equal[unitNumber].Offset > 0); value = offset - equal[unitNumber].Offset; isFinal = false; } #pragma warning disable 612, 618 builder.WriteValueAndFinal(value, isFinal); offset = builder.Write(units[unitNumber]); #pragma warning restore 612, 618 } }
public override void Write(StringTrieBuilder builder) { // Encode the less-than branch first. lessThan.WriteUnlessInsideRightEdge(firstEdgeNumber, greaterOrEqual.Offset, builder); // Encode the greater-or-equal branch last because we do not jump for it at all. greaterOrEqual.Write(builder); // Write this node. Debug.Assert(lessThan.Offset > 0); builder.WriteDeltaTo(lessThan.Offset); // less-than offset = builder.Write(unit); }
public override Node Add(StringTrieBuilder builder, ICharSequence s, int start, int sValue) { if (start == s.Length) { throw new ArgumentException("Duplicate string."); } // Replace self with a node for the remaining string suffix and value. ValueNode node = builder.CreateSuffixNode(s, start, sValue); node.SetValue(value); return(node); }
// See MarkRightEdgesFirst. public void WriteUnlessInsideRightEdge(int firstRight, int lastRight, StringTrieBuilder builder) { // Note: Edge numbers are negative, lastRight<=firstRight. // If offset>0 then this node and its sub-nodes have been written already // and we need not write them again. // If this node is part of the unwritten right branch edge, // then we wait until that is written. if (offset < 0 && (offset < lastRight || firstRight < offset)) { Write(builder); } }
public override void Write(StringTrieBuilder builder) { next.Write(builder); if (length <= builder.MinLinearMatch) { offset = builder.WriteValueAndType(hasValue, value, length - 1); } else { builder.Write(length - 1); offset = builder.WriteValueAndType(hasValue, value, 0); } }
public override void Write(StringTrieBuilder builder) { next.Write(builder); #pragma warning disable 612, 618 if (length <= builder.MinLinearMatch) { offset = builder.WriteValueAndType(hasValue, value, length - 1); } else { builder.Write(length - 1); offset = builder.WriteValueAndType(hasValue, value, 0); #pragma warning restore 612, 618 } }
public override Node Register(StringTrieBuilder builder) { Node subNode = Register(builder, 0, chars.Length); BranchHeadNode head = new BranchHeadNode(chars.Length, subNode); Node result = head; if (hasValue) { if (builder.MatchNodesCanHaveValues) { head.SetValue(value); } else { result = new IntermediateValueNode(value, builder.RegisterNode(head)); } } return(builder.RegisterNode(result)); }
/// <summary> /// Recursive method for registering unique nodes, /// after all (string, value) pairs have been added. /// Final-value nodes are pre-registered while /// <see cref="Add(StringTrieBuilder, ICharSequence, int, int)"/>ing /// (string, value) pairs. Other nodes created while /// <see cref="Add(StringTrieBuilder, ICharSequence, int, int)"/>ing /// <see cref="RegisterNode(Node)"/> themselves later and might replace /// themselves with new types of nodes for <see cref="Write(StringTrieBuilder)"/>ing. /// </summary> /// <returns>The registered version of this node which implements <see cref="Write(StringTrieBuilder)"/>.</returns> public virtual Node Register(StringTrieBuilder builder) { return(this); }
public override void Write(StringTrieBuilder builder) { next.Write(builder); builder.Write(stringOffset, length); offset = builder.WriteValueAndType(hasValue, value, builder.MinLinearMatch + length - 1); }
public override Node Add(StringTrieBuilder builder, ICharSequence s, int start, int sValue) { if (start == s.Length) { if (hasValue) { throw new ArgumentException("Duplicate string."); } else { SetValue(sValue); return(this); } } int limit = stringOffset + length; for (int i = stringOffset; i < limit; ++i, ++start) { if (start == s.Length) { // s is a prefix with a new value. Split self into two linear-match nodes. int prefixLength = i - stringOffset; LinearMatchNode suffixNode = new LinearMatchNode(strings, i, length - prefixLength, next); suffixNode.SetValue(sValue); length = prefixLength; next = suffixNode; return(this); } char thisChar = strings[i]; char newChar = s[start]; if (thisChar != newChar) { // Mismatch, insert a branch node. DynamicBranchNode branchNode = new DynamicBranchNode(); // Reuse this node for one of the remaining substrings, if any. Node result, thisSuffixNode; if (i == stringOffset) { // Mismatch on first character, turn this node into a suffix. if (hasValue) { // Move the value for prefix length "start" to the new node. branchNode.SetValue(value); value = 0; hasValue = false; } ++stringOffset; --length; thisSuffixNode = length > 0 ? this : next; // C++: if(length==0) { delete this; } result = branchNode; } else if (i == limit - 1) { // Mismatch on last character, keep this node for the prefix. --length; thisSuffixNode = next; next = branchNode; result = this; } else { // Mismatch on intermediate character, keep this node for the prefix. int prefixLength = i - stringOffset; ++i; // Suffix start offset (after thisChar). thisSuffixNode = new LinearMatchNode( strings, i, length - (prefixLength + 1), next); length = prefixLength; next = branchNode; result = this; } ValueNode newSuffixNode = builder.CreateSuffixNode(s, start + 1, sValue); branchNode.Add(thisChar, thisSuffixNode); branchNode.Add(newChar, newSuffixNode); return(result); } } // s matches all of this node's characters. next = next.Add(builder, s, start, sValue); return(this); }
public override void Write(StringTrieBuilder builder) { next.Write(builder); offset = builder.WriteValueAndFinal(value, false); }
/// <summary> /// Recursive method for adding a new (string, value) pair. /// Matches the remaining part of <paramref name="s"/> from <paramref name="start"/>, /// and adds a new node where there is a mismatch. /// </summary> /// <returns>This or a replacement <see cref="Node"/>.</returns> public virtual Node Add(StringTrieBuilder builder, ICharSequence s, int start, int sValue) { return(this); }
// Write() must set the offset to a positive value. public abstract void Write(StringTrieBuilder builder);
public override void Write(StringTrieBuilder builder) { offset = builder.WriteValueAndFinal(value, true); }