Пример #1
0
            private ValueNode <T> GetNode(GetNodeOptions options, int[] rptIdx)
            {
                Debug.Assert(rptIdx != null);

                bool createIfNecessary   = (options == GetNodeOptions.CreateNodesAsNecessary);
                bool valuesBubbleAndFlow = (options != GetNodeOptions.NoBubbleAndFlow);

                if (createIfNecessary && rptIdx.Length > Depth)
                {
                    // make sure our value tree is the appropriate depth
                    _value.Expand(rptIdx.Length - Depth, false);
                    Depth = rptIdx.Length;
                }

                return(GetNodeHelper(_value, 0, createIfNecessary, valuesBubbleAndFlow, rptIdx));
            }
Пример #2
0
            // private recursive helper function
            private ValueNode <T> GetNodeHelper(ValueNode <T> node, int atDepth, bool createIfNecessary, bool valuesBubbleAndFlow, int[] rptIdx)
            {
                // this can be invoked with the following flag combinations:
                //     createIfNecessary == true   &&   valuesBubbleAndFlow == true   // we will be setting an answer
                //     createIfNecessary == false  &&   valuesBubbleAndFlow == true   // we will be getting an answer
                //     createIfNecessary == false  &&   valuesBubbleAndFlow == false  // we are looking up a node to count or manipulate its children

                // if we're recursing deeper than the _depth of this answer, we should not be creating nodes as we go!
                // (In that case, ValueNode<T>.Expand should have been called first to push values down the tree as necessary.)
                Debug.Assert(atDepth <= Depth || !createIfNecessary);

                if (node == null)
                {
                    throw new ArgumentNullException("node");
                }
                if (rptIdx == null)
                {
                    throw new ArgumentNullException("rptIdx");
                }

                // see if we're done recursing through all the repeat levels
                if (rptIdx.Length == 0 && atDepth == Depth)
                {
                    ValueNode <T> result = node;
                    if (valuesBubbleAndFlow)
                    {
                        // if we've found a node but it still has children in the tree,
                        // then the value from a 0-indexed descendant node will "bubble up".
                        while (result.HasChildren)
                        {
                            result = result.Children[0];
                        }
                    }
                    return(result);
                }

                int idx;

                int[] newIdx;
                if (rptIdx.Length > 0)
                {
                    idx = rptIdx[0];
                    // continue recursing down through the repeat levels
                    newIdx = new int[rptIdx.Length - 1];
                    if (rptIdx.Length > 1)
                    {
                        Array.Copy(rptIdx, 1, newIdx, 0, newIdx.Length);
                    }
                }
                else                 // rptIdx.Length == 0 ... we've run out of repeat indices
                {
                    Debug.Assert(atDepth < Depth);
                    if (valuesBubbleAndFlow)                     // create new, zero indices so we can continue recursion
                    {
                        idx    = 0;
                        newIdx = new int[Depth - atDepth - 1];                         // make sure value gets set down at the appropriate repeat level
                    }
                    else
                    {
                        Debug.Assert(!createIfNecessary);                         // we don't want to allow setting values at non-leaf nodes of the tree!
                        return(node);
                    }
                }

                // there are still repeat indices through which to recurse...
                if (createIfNecessary)                 // expand current node as necessary
                {
                    if (!node.HasChildren)
                    {
                        node.Expand(1, true);
                    }
                    if (idx >= node.Children.SetCount)
                    {
                        node.Children.PrepareForIndex(idx);
                    }
                }
                else if (!node.HasChildren)
                {
                    // requested node does not exist -- given indexes exceed depth of repeated values
                    return((valuesBubbleAndFlow && idx == 0 && RepeatIndices.IsFirst(newIdx)) ? node : null);
                }
                else if (idx >= node.Children.SetCount)
                {
                    // requested node does not exist -- given indexes exceed number of repeated values
                    return(null);
                }

                return(GetNodeHelper(node.Children[idx], ++atDepth, createIfNecessary, valuesBubbleAndFlow, newIdx));
            }