/// <summary>This is the core of buildTrie.</summary> /// <remarks> /// This is the core of buildTrie. The interface, and stub, above, just adds /// an empty CarriedTrieNodeRef. /// We build trie nodes in depth first order, which is also in key space /// order. Every leaf node is referenced as a slot in a parent internal /// node. If two adjacent slots [in the DFO] hold leaf nodes that have /// no split point, then they are not separated by a split point either, /// because there's no place in key space for that split point to exist. /// When that happens, the leaf nodes would be semantically identical, and /// we reuse the object. A single CarriedTrieNodeRef "ref" lives for the /// duration of the tree-walk. ref carries a potentially reusable, unsplit /// leaf node for such reuse until a leaf node with a split arises, which /// breaks the chain until we need to make a new unsplit leaf node. /// Note that this use of CarriedTrieNodeRef means that for internal nodes, /// for internal nodes if this code is modified in any way we still need /// to make or fill in the subnodes in key space order. /// </remarks> private TotalOrderPartitioner.TrieNode BuildTrieRec(BinaryComparable[] splits, int lower, int upper, byte[] prefix, int maxDepth, TotalOrderPartitioner.CarriedTrieNodeRef @ref) { int depth = prefix.Length; // We generate leaves for a single split point as well as for // no split points. if (depth >= maxDepth || lower >= upper - 1) { // If we have two consecutive requests for an unsplit trie node, we // can deliver the same one the second time. if (lower == upper && @ref.content != null) { return(@ref.content); } TotalOrderPartitioner.TrieNode result = LeafTrieNodeFactory(depth, splits, lower, upper); @ref.content = lower == upper ? result : null; return(result); } TotalOrderPartitioner.InnerTrieNode result_1 = new TotalOrderPartitioner.InnerTrieNode (this, depth); byte[] trial = Arrays.CopyOf(prefix, prefix.Length + 1); // append an extra byte on to the prefix int currentBound = lower; for (int ch = 0; ch < unchecked ((int)(0xFF)); ++ch) { trial[depth] = unchecked ((byte)(ch + 1)); lower = currentBound; while (currentBound < upper) { if (splits[currentBound].CompareTo(trial, 0, trial.Length) >= 0) { break; } currentBound += 1; } trial[depth] = unchecked ((byte)ch); result_1.child[unchecked ((int)(0xFF)) & ch] = BuildTrieRec(splits, lower, currentBound , trial, maxDepth, @ref); } // pick up the rest trial[depth] = unchecked ((byte)unchecked ((int)(0xFF))); result_1.child[unchecked ((int)(0xFF))] = BuildTrieRec(splits, lower, currentBound , trial, maxDepth, @ref); return(result_1); }
internal CarriedTrieNodeRef(TotalOrderPartitioner <K, V> _enclosing) { this._enclosing = _enclosing; this.content = null; }