/**
  * @return never <c>null</c>, (possibly empty) array of all cells directly used while 
  * evaluating the formula of this frame.
  */
 private CellCacheEntry[] GetSensitiveInputCells()
 {
     int nItems = _sensitiveInputCells.Count;
     if (nItems < 1)
     {
         return CellCacheEntry.EMPTY_ARRAY;
     }
     CellCacheEntry[] result = new CellCacheEntry[nItems];
     result = (CellCacheEntry[])_sensitiveInputCells.ToArray(typeof(CellCacheEntry));
     return result;
 }
 public void Add(CellCacheEntry cce)
 {
     if (_size * 3 >= _arr.Length * 2)
     {
         // re-Hash
         FormulaCellCacheEntry[] prevArr = _arr;
         FormulaCellCacheEntry[] newArr = new FormulaCellCacheEntry[4 + _arr.Length * 3 / 2]; // grow 50%
         for (int i = 0; i < prevArr.Length; i++)
         {
             FormulaCellCacheEntry prevCce = _arr[i];
             if (prevCce != null)
             {
                 AddInternal(newArr, prevCce);
             }
         }
         _arr = newArr;
     }
     if (AddInternal(_arr, cce))
     {
         _size++;
     }
 }
 public void AcceptFormulaDependency(CellCacheEntry cce)
 {
     // Tell the currently evaluating cell frame that it Has a dependency on the specified
     int prevFrameIndex = _evaluationFrames.Count - 1;
     if (prevFrameIndex < 0)
     {
         // Top level frame, there is no 'cell' above this frame that is using the current cell
     }
     else
     {
         CellEvaluationFrame consumingFrame = (CellEvaluationFrame)_evaluationFrames[prevFrameIndex];
         consumingFrame.AddSensitiveInputCell(cce);
     }
 }
        /**
         * Notifies this evaluation tracker that the evaluation of the specified cell is complete. <p/>
         *
         * Every successful call To <c>startEvaluate</c> must be followed by a call To <c>endEvaluate</c> (recommended in a finally block) To enable
         * proper tracking of which cells are being evaluated at any point in time.<p/>
         *
         * Assuming a well behaved client, parameters To this method would not be
         * required. However, they have been included To assert correct behaviour,
         * and form more meaningful error messages.
         */
        public void EndEvaluate(CellCacheEntry cce)
        {

            int nFrames = _evaluationFrames.Count;
            if (nFrames < 1)
            {
                throw new InvalidOperationException("Call To endEvaluate without matching call To startEvaluate");
            }

            nFrames--;
            CellEvaluationFrame frame = (CellEvaluationFrame)_evaluationFrames[nFrames];
            if (cce != frame.GetCCE())
            {
                throw new InvalidOperationException("Wrong cell specified. ");
            }
            // else - no problems so pop current frame
            _evaluationFrames.RemoveAt(nFrames);
            _currentlyEvaluatingCells.Remove(cce);
        }
        private static bool AddInternal(CellCacheEntry[] arr, CellCacheEntry cce)
        {

            int startIx = cce.GetHashCode() % arr.Length;

            for (int i = startIx; i < arr.Length; i++)
            {
                CellCacheEntry item = arr[i];
                if (item == cce)
                {
                    // already present
                    return false;
                }
                if (item == null)
                {
                    arr[i] = cce;
                    return true;
                }
            }
            for (int i = 0; i < startIx; i++)
            {
                CellCacheEntry item = arr[i];
                if (item == cce)
                {
                    // already present
                    return false;
                }
                if (item == null)
                {
                    arr[i] = cce;
                    return true;
                }
            }
            throw new InvalidOperationException("No empty space found");
        }
        public bool Remove(CellCacheEntry cce)
        {
            FormulaCellCacheEntry[] arr = _arr;

            if (_size * 3 < _arr.Length && _arr.Length > 8)
            {
                // re-Hash
                bool found = false;
                FormulaCellCacheEntry[] prevArr = _arr;
                FormulaCellCacheEntry[] newArr = new FormulaCellCacheEntry[_arr.Length / 2]; // shrink 50%
                for (int i = 0; i < prevArr.Length; i++)
                {
                    FormulaCellCacheEntry prevCce = _arr[i];
                    if (prevCce != null)
                    {
                        if (prevCce == cce)
                        {
                            found = true;
                            _size--;
                            // skip it
                            continue;
                        }
                        AddInternal(newArr, prevCce);
                    }
                }
                _arr = newArr;
                return found;
            }
            // else - usual case
            // delete single element (without re-Hashing)

            int startIx = cce.GetHashCode() % arr.Length;

            // note - can't exit loops upon finding null because of potential previous deletes
            for (int i = startIx; i < arr.Length; i++)
            {
                FormulaCellCacheEntry item = arr[i];
                if (item == cce)
                {
                    // found it
                    arr[i] = null;
                    _size--;
                    return true;
                }
            }
            for (int i = 0; i < startIx; i++)
            {
                FormulaCellCacheEntry item = arr[i];
                if (item == cce)
                {
                    // found it
                    arr[i] = null;
                    _size--;
                    return true;
                }
            }
            return false;
        }
 /**
  * @param inputCell a cell directly used by the formula of this evaluation frame
  */
 public void AddSensitiveInputCell(CellCacheEntry inputCell)
 {
     _sensitiveInputCells.Add(inputCell);
 }