Ejemplo n.º 1
0
        /// <summary>
        ///     Gets/Sets a single character.
        ///     Runs in O(lg N) for random access. Sequential read-only access benefits from a special optimization and runs in
        ///     amortized O(1).
        /// </summary>
        /// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to Length-1).</exception>
        /// <remarks>
        ///     The getter counts as a read access and may be called concurrently to other read accesses.
        /// </remarks>
        public T this[int index]
        {
            get
            {
                // use unsigned integers - this way negative values for index overflow and can be tested for with the same check
                if (unchecked ((uint)index >= (uint)Length))
                {
                    throw new ArgumentOutOfRangeException("index", index,
                                                          "0 <= index < " + Length.ToString(CultureInfo.InvariantCulture));
                }
                var entry = FindNodeUsingCache(index).PeekOrDefault();
                return(entry.node.contents[index - entry.nodeStartIndex]);
            }
            set
            {
                if (index < 0 || index >= Length)
                {
                    throw new ArgumentOutOfRangeException("index", index,
                                                          "0 <= index < " + Length.ToString(CultureInfo.InvariantCulture));
                }
                root = root.SetElement(index, value);
                OnChanged();

                /* Here's a try at implementing the setter using the cached node stack (UNTESTED code!).
                 * However I don't use the code because it's complicated and doesn't integrate correctly with change notifications.
                 * Instead, I'll use the much easier to understand recursive solution.
                 * Oh, and it also doesn't work correctly with function nodes.
                 * ImmutableStack<RopeCacheEntry> nodeStack = FindNodeUsingCache(offset);
                 * RopeCacheEntry entry = nodeStack.Peek();
                 * if (!entry.node.isShared) {
                 *      entry.node.contents[offset - entry.nodeStartOffset] = value;
                 *      // missing: clear the caches except for the node stack cache (e.g. ToString() cache?)
                 * } else {
                 *      RopeNode oldNode = entry.node;
                 *      RopeNode newNode = oldNode.Clone();
                 *      newNode.contents[offset - entry.nodeStartOffset] = value;
                 *      for (nodeStack = nodeStack.Pop(); !nodeStack.IsEmpty; nodeStack = nodeStack.Pop()) {
                 *              RopeNode parentNode = nodeStack.Peek().node;
                 *              RopeNode newParentNode = parentNode.CloneIfShared();
                 *              if (newParentNode.left == oldNode) {
                 *                      newParentNode.left = newNode;
                 *              } else {
                 *                      Debug.Assert(newParentNode.right == oldNode);
                 *                      newParentNode.right = newNode;
                 *              }
                 *              if (parentNode == newParentNode) {
                 *                      // we were able to change the existing node (it was not shared);
                 *                      // there's no reason to go further upwards
                 *                      ClearCacheOnModification();
                 *                      return;
                 *              } else {
                 *                      oldNode = parentNode;
                 *                      newNode = newParentNode;
                 *              }
                 *      }
                 *      // we reached the root of the rope.
                 *      Debug.Assert(root == oldNode);
                 *      root = newNode;
                 *      ClearCacheOnModification();
                 * }*/
            }
        }