Пример #1
0
        /// <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);
        }
Пример #2
0
 internal CarriedTrieNodeRef(TotalOrderPartitioner <K, V> _enclosing)
 {
     this._enclosing = _enclosing;
     this.content    = null;
 }