text:
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//---------------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Diagnostics.CodeAnalysis;
#if SYSTEM_XAML
using System.Xaml;
#else
using MS.Internal.WindowsBase;
#endif

//using MS.Internal.PresentationCore;
//using SR=MS.Internal.WindowsBase.SR;
//using SRID=MS.Internal.WindowsBase.SRID;

    // These classes implement a frugal storage model for lists of type <T>.
    // Performance measurements show that Avalon has many lists that contain
    // a limited number of entries, and frequently zero or a single entry.
    // Therefore these classes are structured to prefer a storage model that
    // starts at zero, and employs a conservative growth strategy to minimize
    // the steady state memory footprint. Also note that the list uses one
    // fewer objects than ArrayList and List<T> and does no allocations at all
    // until an item is inserted into the list.
    //
    // The code is also structured to perform well from a CPU standpoint. Perf
    // analysis shows that the reduced number of processor cache misses makes
    // FrugalList faster than ArrayList or List<T>, especially for lists of 6
    // or fewer items. Timing differ with the size of <T>.
    //
    // FrugalList is appropriate for small lists or lists that grow slowly.
    // Due to the slow growth, if you use it for a list with more than 6 initial
    // entires is best to set the capacity of the list at construction time or
    // soon after. If you must grow the list by a large amount, set the capacity
    // or use Insert() method to force list growth to the final size. Choose
    // your collections wisely and pay particular attention to the growth
    // patterns and search methods.

    // FrugalList has all of the methods of the Ilist interface, but implements
    // them as virtual methods of the class and not as Interface methods. This
    // is to avoid the virtual stub dispatch CPU costs associated with Interfaces.

    // We suppress two FxCop warnings in this module because not all usages
    // of FrugalList will instantiate all the storage classes and not all class instances
    // will use every method.
    // CA1811:AvoidUncalledPrivateCode
    // CA1812:AvoidUninstantiatedInternalClasses
    //

#if SYSTEM_XAML
namespace System.Xaml.MS.Impl
#else
namespace MS.Utility
#endif
{
    // These classes implement a frugal storage model for lists of <T>.
    // Performance measurements show that many lists contain a single item.
    // Therefore this list is structured to prefer a list that contains a single
    // item, and does conservative growth to minimize the memory footprint.

    // This enum controls the growth to successively more complex storage models
    internal enum FrugalListStoreState
    {
        Success,
        SingleItemList,
        ThreeItemList,
        SixItemList,
        Array
    }

    abstract class FrugalListBase<T>
    {
        /// <summary>
        /// Number of entries in this store
        /// </summary>
        // Number of entries in this store
        public int Count
        {
            get
            {
                return _count;
            }
        }

        // for use only by trusted callers - e.g. FrugalObjectList.Compacter
        internal void TrustedSetCount(int newCount)
        {
            _count = newCount;
        }

        /// <summary>
        /// Capacity of this store
        /// </summary>
        public abstract int Capacity
        {
            get;
        }

        // Increase size if needed, insert item into the store
        public abstract FrugalListStoreState Add(T value);

        /// <summary>
        /// Removes all values from the store
        /// </summary>
        public abstract void Clear();

        /// <summary>
        /// Returns true if the store contains the entry.
        /// </summary>
        public abstract bool Contains(T value);

        /// <summary>
        /// Returns the index into the store that contains the item.
        /// -1 is returned if the item is not in the store.
        /// </summary>
        public abstract int IndexOf(T value);

        /// <summary>
        /// Insert item into the store at index, grows if needed
        /// </summary>
        public abstract void Insert(int index, T value);

        // Place item into the store at index
        public abstract void SetAt(int index, T value);

        /// <summary>
        /// Removes the item from the store. If the item was not
        /// in the store false is returned.
        /// </summary>
        public abstract bool Remove(T value);

        /// <summary>
        /// Removes the item from the store
        /// </summary>
        public abstract void RemoveAt(int index);

        /// <summary>
        /// Return the item at index in the store
        /// </summary>
        public abstract T EntryAt(int index);

        /// <summary>
        /// Promotes the values in the current store to the next larger
        /// and more complex storage model.
        /// </summary>
        public abstract void Promote(FrugalListBase<T> newList);

        /// <summary>
        /// Returns the entries as an array
        /// </summary>
        public abstract T[] ToArray();

        /// <summary>
        /// Copies the entries to the given array starting at the
        /// specified index
        /// </summary>
        public abstract void CopyTo(T[] array, int index);

        /// <summary>
        /// Creates a shallow copy of the  list
        /// </summary>
        public abstract object Clone();

        // The number of items in the list.
        protected int _count;

        #region Compacter

        public virtual Compacter NewCompacter(int newCount)
        {
            return new Compacter(this, newCount);
        }

        // basic implementation - compacts in-place
        internal class Compacter
        {
            public Compacter(FrugalListBase<T> store, int newCount)
            {
                _store = store;
                _newCount = newCount;
            }

            public void Include(int start, int end)
            {
                Debug.Assert(start >= _previousEnd, "Arguments out of order during Compact");
                Debug.Assert(_validItemCount + end - start <= _newCount, "Too many items copied during Compact");

                IncludeOverride(start, end);

                _previousEnd = end;
            }

            protected virtual void IncludeOverride(int start, int end)
            {
                // item-by-item move
                for (int i=start; i<end; ++i)
                {
                    _store.SetAt(_validItemCount++, _store.EntryAt(i));
                }
            }

            public virtual FrugalListBase<T> Finish()
            {
                // clear out vacated entries
                T filler = default(T);
                for (int i=_validItemCount, n=_store._count; i<n; ++i)
                {
                    _store.SetAt(i, filler);
                }

                _store._count = _validItemCount;
                return _store;
            }

            protected FrugalListBase<T> _store;
            protected int _validItemCount;
            protected int _previousEnd;
            private int _newCount;
        }

        #endregion Compacter
    }

    /// <summary>
    /// A simple class to handle a single item
    /// </summary>
    internal sealed class SingleItemList<T> : FrugalListBase<T>
    {
        // Capacity of this store
        public override int Capacity
        {
            get
            {
                return SIZE;
            }
        }

        public override FrugalListStoreState Add(T value)
        {
            // If we don't have any entries or the existing entry is being overwritten,
            // then we can use this store. Otherwise we have to promote.
            if (0 == _count)
            {
                _loneEntry = value;
                ++_count;
                return FrugalListStoreState.Success;
            }
            else
            {
                // Entry already used, move to an ThreeItemList
                return FrugalListStoreState.ThreeItemList;
            }
        }

        public override void Clear()
        {
            // Wipe out the info
            _loneEntry = default(T);
            _count = 0;
        }

        public override bool Contains(T value)
        {
            return _loneEntry.Equals(value);
        }

        public override int IndexOf(T value)
        {
            if (_loneEntry.Equals(value))
            {
                return 0;
            }
            return -1;
        }

        public override void Insert(int index, T value)
        {
            // Should only get here if count and index are 0
            if ((_count < SIZE) && (index < SIZE))
            {
                _loneEntry = value;
                ++_count;
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public override void SetAt(int index, T value)
        {
            // Overwrite item at index
            _loneEntry = value;
        }

        public override bool Remove(T value)
        {
            // Wipe out the info in the only entry if it matches the item.
            if (_loneEntry.Equals(value))
            {
                _loneEntry = default(T);
                --_count;
                return true;
            }

            return false;
        }

        public override void RemoveAt(int index)
        {
            // Wipe out the info at index
            if (0 == index)
            {
                _loneEntry = default(T);
                --_count;
            }
            else
            {
                throw new ArgumentOutOfRangeException("index");
            }
        }

        public override T EntryAt(int index)
        {
            return _loneEntry;
        }

        public override void Promote(FrugalListBase<T> oldList)
        {
            if (SIZE == oldList.Count)
            {
                SetCount(SIZE);
                SetAt(0, oldList.EntryAt(0));
            }
            else
            {
                // this list is smaller than oldList
                throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList");
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(SingleItemList<T> oldList)
        {
            SetCount(oldList.Count);
            SetAt(0, oldList.EntryAt(0));
        }

        public override T[] ToArray()
        {
            T[] array = new T[1];
            array[0] = _loneEntry;
            return array;
        }

        public override void CopyTo(T[] array, int index)
        {
            array[index] = _loneEntry;
        }

        public override object Clone()
        {
            SingleItemList<T> newList = new SingleItemList<T>();
            newList.Promote(this);
            return newList;
        }

        private void SetCount(int value)
        {
            if ((value >= 0) && (value <= SIZE))
            {
                _count = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException("value");
            }
        }

        private const int SIZE = 1;

        private T _loneEntry;
    }

    /// <summary>
    /// A simple class to handle a list with 3 items.  Perf analysis showed
    /// that this yielded better memory locality and perf than an object and an array.
    /// </summary>
    internal sealed class ThreeItemList<T> : FrugalListBase<T>
    {
        // Capacity of this store
        public override int Capacity
        {
            get
            {
                return SIZE;
            }
        }

        public override FrugalListStoreState Add(T value)
        {
            switch (_count)
            {
                case 0:
                    _entry0 = value;
                    break;

                case 1:
                    _entry1 = value;
                    break;

                case 2:
                    _entry2 = value;
                    break;

                default:
                    // We have to promote
                    return FrugalListStoreState.SixItemList;
            }
            ++_count;
            return FrugalListStoreState.Success;
        }

        public override void Clear()
        {
            // Wipe out the info.
            _entry0 = default(T);
            _entry1 = default(T);
            _entry2 = default(T);
            _count = 0;
        }

        public override bool Contains(T value)
        {
            return (-1 != IndexOf(value));
        }

        public override int IndexOf(T value)
        {
            if (_entry0.Equals(value))
            {
                return 0;
            }
            if (_count > 1)
            {
                if (_entry1.Equals(value))
                {
                    return 1;
                }
                if ((3 == _count) && (_entry2.Equals(value)))
                {
                    return 2;
                }
            }
            return -1;
        }

        public override void Insert(int index, T value)
        {
            // Should only get here if count < SIZE
            if (_count < SIZE)
            {
                switch (index)
                {
                    case 0:
                        _entry2 = _entry1;
                        _entry1 = _entry0;
                        _entry0 = value;
                        break;

                    case 1:
                        _entry2 = _entry1;
                        _entry1 = value;
                        break;

                    case 2:
                        _entry2 = value;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("index");
                }
                ++_count;
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public override void SetAt(int index, T value)
        {
            // Overwrite item at index
            switch (index)
            {
                case 0:
                    _entry0 = value;
                    break;

                case 1:
                    _entry1 = value;
                    break;

                case 2:
                    _entry2 = value;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("index");
            }
        }

        public override bool Remove(T value)
        {
            // If the item matches an existing entry, wipe out the last
            // entry and move all the other entries up.  Because we only
            // have three entries we can just unravel all the cases.
            if (_entry0.Equals(value))
            {
                RemoveAt(0);
                return true;
            }
            else if ( _count > 1)
            {
                if (_entry1.Equals(value))
                {
                    RemoveAt(1);
                    return true;
                }
                else if ((3 == _count) && (_entry2.Equals(value)))
                {
                    RemoveAt(2);
                    return true;
                }
            }
            return false;
        }

        public override void RemoveAt(int index)
        {
            // Remove entry at index, wipe out the last entry and move
            // all the other entries up.  Because we only have three
            // entries we can just unravel all the cases.
            switch (index)
            {
                case 0:
                    _entry0 = _entry1;
                    _entry1 = _entry2;
                    break;

                case 1:
                    _entry1 = _entry2;
                    break;

                case 2:
                    break;

                default:
                    throw new ArgumentOutOfRangeException("index");
            }
            _entry2 = default(T);
            --_count;
        }

        public override T EntryAt(int index)
        {
            switch (index)
            {
                case 0:
                    return _entry0;

                case 1:
                    return _entry1;

                case 2:
                    return _entry2;

                default:
                    throw new ArgumentOutOfRangeException("index");
            }
        }

        public override void Promote(FrugalListBase<T> oldList)
        {
            int oldCount = oldList.Count;
            if (SIZE >= oldCount)
            {
                SetCount(oldList.Count);

                switch (oldCount)
                {
                    case 3:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        break;

                    case 2:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        break;

                    case 1:
                        SetAt(0, oldList.EntryAt(0));
                        break;

                    case 0:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("oldList");
                }
            }
            else
            {
                // this list is smaller than oldList
                throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList");
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(SingleItemList<T> oldList)
        {
            SetCount(oldList.Count);
            SetAt(0, oldList.EntryAt(0));
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(ThreeItemList<T> oldList)
        {
            int oldCount = oldList.Count;
            SetCount(oldList.Count);

            switch (oldCount)
            {
                case 3:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    break;

                case 2:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    break;

                case 1:
                    SetAt(0, oldList.EntryAt(0));
                    break;

                case 0:
                    break;

                default:
                    throw new ArgumentOutOfRangeException("oldList");
            }
        }

        public override T[] ToArray()
        {
            T[] array = new T[_count];

            array[0] = _entry0;
            if (_count >= 2)
            {
                array[1] = _entry1;
                if (_count == 3)
                {
                    array[2] = _entry2;
                }
            }
            return array;
        }

        public override void CopyTo(T[] array, int index)
        {
            array[index] = _entry0;
            if (_count >= 2)
            {
                array[index+1] = _entry1;
                if (_count == 3)
                {
                    array[index+2] = _entry2;
                }
            }
        }

        public override object Clone()
        {
            ThreeItemList<T> newList = new ThreeItemList<T>();
            newList.Promote(this);
            return newList;
        }

        private void SetCount(int value)
        {
            if ((value >= 0) && (value <= SIZE))
            {
                _count = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException("value");
            }
        }

        private const int SIZE = 3;

        private T _entry0;
        private T _entry1;
        private T _entry2;
    }

    /// <summary>
    /// A simple class to handle a list with 6 items.
    /// </summary>
    internal sealed class SixItemList<T> : FrugalListBase<T>
    {
        // Capacity of this store
        public override int Capacity
        {
            get
            {
                return SIZE;
            }
        }

        public override FrugalListStoreState Add(T value)
        {
            switch (_count)
            {
                case 0:
                    _entry0 = value;
                    break;

                case 1:
                    _entry1 = value;
                    break;

                case 2:
                    _entry2 = value;
                    break;

                case 3:
                    _entry3 = value;
                    break;

                case 4:
                    _entry4 = value;
                    break;

                case 5:
                    _entry5 = value;
                    break;

                default:
                    // We have to promote
                    return FrugalListStoreState.Array;
            }
            ++_count;
            return FrugalListStoreState.Success;
        }

        public override void Clear()
        {
            // Wipe out the info.
            _entry0 = default(T);
            _entry1 = default(T);
            _entry2 = default(T);
            _entry3 = default(T);
            _entry4 = default(T);
            _entry5 = default(T);
            _count = 0;
        }

        public override bool Contains(T value)
        {
            return (-1 != IndexOf(value));
        }

        public override int IndexOf(T value)
        {
            if (_entry0.Equals(value))
            {
                return 0;
            }
            if (_count > 1)
            {
                if (_entry1.Equals(value))
                {
                    return 1;
                }
                if (_count > 2)
                {
                    if (_entry2.Equals(value))
                    {
                        return 2;
                    }
                    if (_count > 3)
                    {
                        if (_entry3.Equals(value))
                        {
                            return 3;
                        }
                        if (_count > 4)
                        {
                            if (_entry4.Equals(value))
                            {
                                return 4;
                            }
                            if ((6 == _count) && (_entry5.Equals(value)))
                            {
                                return 5;
                            }
                        }
                    }
                }
            }
            return -1;
        }

        public override void Insert(int index, T value)
        {
            // Should only get here if count is less than SIZE
            if (_count < SIZE)
            {
                switch (index)
                {
                    case 0:
                        _entry5 = _entry4;
                        _entry4 = _entry3;
                        _entry3 = _entry2;
                        _entry2 = _entry1;
                        _entry1 = _entry0;
                        _entry0 = value;
                        break;

                    case 1:
                        _entry5 = _entry4;
                        _entry4 = _entry3;
                        _entry3 = _entry2;
                        _entry2 = _entry1;
                        _entry1 = value;
                        break;

                    case 2:
                        _entry5 = _entry4;
                        _entry4 = _entry3;
                        _entry3 = _entry2;
                        _entry2 = value;
                        break;

                    case 3:
                        _entry5 = _entry4;
                        _entry4 = _entry3;
                        _entry3 = value;
                        break;

                    case 4:
                        _entry5 = _entry4;
                        _entry4 = value;
                        break;

                    case 5:
                        _entry5 = value;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("index");
                }
                ++_count;
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public override void SetAt(int index, T value)
        {
            // Overwrite item at index
            switch (index)
            {
                case 0:
                    _entry0 = value;
                    break;

                case 1:
                    _entry1 = value;
                    break;

                case 2:
                    _entry2 = value;
                    break;

                case 3:
                    _entry3 = value;
                    break;

                case 4:
                    _entry4 = value;
                    break;

                case 5:
                    _entry5 = value;
                    break;

                default:
                    throw new ArgumentOutOfRangeException("index");
            }
        }

        public override bool Remove(T value)
        {
            // If the item matches an existing entry, wipe out the last
            // entry and move all the other entries up.  Because we only
            // have six entries we can just unravel all the cases.
            if (_entry0.Equals(value))
            {
                RemoveAt(0);
                return true;
            }
            else if (_count > 1)
            {
                if (_entry1.Equals(value))
                {
                    RemoveAt(1);
                    return true;
                }
                else if (_count > 2)
                {
                    if (_entry2.Equals(value))
                    {
                        RemoveAt(2);
                        return true;
                    }
                    else if (_count > 3)
                    {
                        if (_entry3.Equals(value))
                        {
                            RemoveAt(3);
                            return true;
                        }
                        else if (_count > 4)
                        {
                            if (_entry4.Equals(value))
                            {
                                RemoveAt(4);
                                return true;
                            }
                            else if ((6 == _count) && (_entry5.Equals(value)))
                            {
                                RemoveAt(5);
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }

        public override void RemoveAt(int index)
        {
            // Remove entry at index, wipe out the last entry and move
            // all the other entries up. Because we only have six
            // entries we can just unravel all the cases.
            switch (index)
            {
                case 0:
                    _entry0 = _entry1;
                    _entry1 = _entry2;
                    _entry2 = _entry3;
                    _entry3 = _entry4;
                    _entry4 = _entry5;
                    break;

                case 1:
                    _entry1 = _entry2;
                    _entry2 = _entry3;
                    _entry3 = _entry4;
                    _entry4 = _entry5;
                    break;

                case 2:
                    _entry2 = _entry3;
                    _entry3 = _entry4;
                    _entry4 = _entry5;
                    break;

                case 3:
                    _entry3 = _entry4;
                    _entry4 = _entry5;
                    break;

                case 4:
                    _entry4 = _entry5;
                    break;

                case 5:
                    break;

                default:
                    throw new ArgumentOutOfRangeException("index");
            }
            _entry5 = default(T);
            --_count;
        }

        public override T EntryAt(int index)
        {
            switch (index)
            {
                case 0:
                    return _entry0;

                case 1:
                    return _entry1;

                case 2:
                    return _entry2;

                case 3:
                    return _entry3;

                case 4:
                    return _entry4;

                case 5:
                    return _entry5;

                default:
                    throw new ArgumentOutOfRangeException("index");
            }
        }

        public override void Promote(FrugalListBase<T> oldList)
        {
            int oldCount = oldList.Count;
            if (SIZE >= oldCount)
            {
                SetCount(oldList.Count);

                switch (oldCount)
                {
                    case 6:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        SetAt(3, oldList.EntryAt(3));
                        SetAt(4, oldList.EntryAt(4));
                        SetAt(5, oldList.EntryAt(5));
                        break;

                    case 5:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        SetAt(3, oldList.EntryAt(3));
                        SetAt(4, oldList.EntryAt(4));
                        break;

                    case 4:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        SetAt(3, oldList.EntryAt(3));
                        break;

                    case 3:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        break;

                    case 2:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        break;

                    case 1:
                        SetAt(0, oldList.EntryAt(0));
                        break;

                    case 0:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("oldList");
                }
            }
            else
            {
                // this list is smaller than oldList
                throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList");
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(ThreeItemList<T> oldList)
        {
            int oldCount = oldList.Count;
            if (SIZE <= oldCount)
            {
                SetCount(oldList.Count);

                switch (oldCount)
                {
                    case 3:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        break;

                    case 2:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        break;

                    case 1:
                        SetAt(0, oldList.EntryAt(0));
                        break;

                    case 0:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("oldList");
                }
            }
            else
            {
                // this list is smaller than oldList
                throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList");
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(SixItemList<T> oldList)
        {
            int oldCount = oldList.Count;
            SetCount(oldList.Count);

            switch (oldCount)
            {
                case 6:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    SetAt(3, oldList.EntryAt(3));
                    SetAt(4, oldList.EntryAt(4));
                    SetAt(5, oldList.EntryAt(5));
                    break;

                case 5:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    SetAt(3, oldList.EntryAt(3));
                    SetAt(4, oldList.EntryAt(4));
                    break;

                case 4:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    SetAt(3, oldList.EntryAt(3));
                    break;

                case 3:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    break;

                case 2:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    break;

                case 1:
                    SetAt(0, oldList.EntryAt(0));
                    break;

                case 0:
                    break;

                default:
                    throw new ArgumentOutOfRangeException("oldList");
            }
        }

        public override T[] ToArray()
        {
            T[] array = new T[_count];

            if (_count >= 1)
            {
                array[0] = _entry0;
                if (_count >= 2)
                {
                    array[1] = _entry1;
                    if (_count >= 3)
                    {
                        array[2] = _entry2;
                        if (_count >= 4)
                        {
                            array[3] = _entry3;
                            if (_count >= 5)
                            {
                                array[4] = _entry4;
                                if (_count == 6)
                                {
                                    array[5] = _entry5;
                                }
                            }
                        }
                    }
                }
            }
            return array;
        }

        public override void CopyTo(T[] array, int index)
        {
            if (_count >= 1)
            {
                array[index] = _entry0;
                if (_count >= 2)
                {
                    array[index+1] = _entry1;
                    if (_count >= 3)
                    {
                        array[index+2] = _entry2;
                        if (_count >= 4)
                        {
                            array[index+3] = _entry3;
                            if (_count >= 5)
                            {
                                array[index+4] = _entry4;
                                if (_count == 6)
                                {
                                    array[index+5] = _entry5;
                                }
                            }
                        }
                    }
                }
            }
        }

        public override object Clone()
        {
            SixItemList<T> newList = new SixItemList<T>();
            newList.Promote(this);
            return newList;
        }

        private void SetCount(int value)
        {
            if ((value >= 0) && (value <= SIZE))
            {
                _count = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException("value");
            }
        }

        private const int SIZE = 6;

        private T _entry0;
        private T _entry1;
        private T _entry2;
        private T _entry3;
        private T _entry4;
        private T _entry5;
    }

    /// <summary>
    /// A simple class to handle an array of 7 or more items.  It is unsorted and uses
    /// a linear search.
    /// </summary>
    internal sealed class ArrayItemList<T> : FrugalListBase<T>
    {
        public ArrayItemList()
        {
        }

        public ArrayItemList(int size)
        {
            // Make size a multiple of GROWTH
            size += (GROWTH - 1);
            size -= (size % GROWTH);
            _entries = new T[size];
        }

        public ArrayItemList(ICollection collection)
        {
            if (collection != null)
            {
                _count = collection.Count;
                _entries = new T[_count];
                collection.CopyTo(_entries, 0);
            }
        }

        public ArrayItemList(ICollection<T> collection)
        {
            if (collection != null)
            {
                _count = collection.Count;
                _entries = new T[_count];
                collection.CopyTo(_entries, 0);
            }
        }

        // Capacity of this store
        public override int Capacity
        {
            get
            {
                if (_entries != null)
                {
                    return _entries.Length;
                }
                return 0;
            }
        }

        public override FrugalListStoreState Add(T value)
        {
            // If we don't have any entries or the existing entry is being overwritten,
            // then we can use this store. Otherwise we have to promote.
            if ((null != _entries) && (_count < _entries.Length))
            {
                _entries[_count] = value;
                ++_count;
            }
            else
            {
                if (null != _entries)
                {
                    int size = _entries.Length;

                    // Grow the list slowly while it is small but
                    // faster once it reaches the LARGEGROWTH size
                    if (size < LARGEGROWTH)
                    {
                        size += GROWTH;
                    }
                    else
                    {
                        size += size >> 2;
                    }

                    T[] destEntries = new T[size];

                    // Copy old array
                    Array.Copy(_entries, 0, destEntries, 0, _entries.Length);
                    _entries = destEntries;
                }
                else
                {
                    _entries = new T[MINSIZE];
                }

                // Insert into new array
                _entries[_count] = value;
                ++_count;
            }
            return FrugalListStoreState.Success;
        }

        public override void Clear()
        {
            // Wipe out the info.
            for (int i = 0; i < _count; ++i)
            {
                _entries[i] = default(T);
            }
            _count = 0;
        }

        public override bool Contains(T value)
        {
            return (-1 != IndexOf(value));
        }

        public override int IndexOf(T value)
        {
            for (int index = 0; index < _count; ++index)
            {
                if (_entries[index].Equals(value))
                {
                    return index;
                }
            }
            return -1;
        }

        public override void Insert(int index, T value)
        {
            if ((null != _entries) && (_count < _entries.Length))
            {
                // Move down the required number of items
                Array.Copy(_entries, index, _entries, index + 1, _count - index);

                // Put in the new item at the specified index
                _entries[index] = value;
                ++_count;
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public override void SetAt(int index, T value)
        {
            // Overwrite item at index
            _entries[index] = value;
        }

        public override bool Remove(T value)
        {
            for (int index = 0; index < _count; ++index)
            {
                if (_entries[index].Equals(value))
                {
                    RemoveAt(index);
                    return true;
                }
            }

            return false;
        }

        public override void RemoveAt(int index)
        {
            // Shift entries down
            int numToCopy = (_count - index) - 1;
            if (numToCopy > 0)
            {
                Array.Copy(_entries, index + 1, _entries, index, numToCopy);
            }

            // Wipe out the last entry
            _entries[_count - 1] = default(T);
            --_count;
            return;
        }

        public override T EntryAt(int index)
        {
            return _entries[index];
        }

        public override void Promote(FrugalListBase<T> oldList)
        {
            for (int index = 0; index < oldList.Count; ++index)
            {
                if (FrugalListStoreState.Success == Add(oldList.EntryAt(index)))
                {
                    continue;
                }
                // this list is smaller than oldList
                throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList");
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(SixItemList<T> oldList)
        {
            int oldCount = oldList.Count;
            SetCount(oldList.Count);

            switch (oldCount)
            {
                case 6:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    SetAt(3, oldList.EntryAt(3));
                    SetAt(4, oldList.EntryAt(4));
                    SetAt(5, oldList.EntryAt(5));
                    break;

                case 5:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    SetAt(3, oldList.EntryAt(3));
                    SetAt(4, oldList.EntryAt(4));
                    break;

                case 4:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    SetAt(3, oldList.EntryAt(3));
                    break;

                case 3:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    SetAt(2, oldList.EntryAt(2));
                    break;

                case 2:
                    SetAt(0, oldList.EntryAt(0));
                    SetAt(1, oldList.EntryAt(1));
                    break;

                case 1:
                    SetAt(0, oldList.EntryAt(0));
                    break;

                case 0:
                    break;

                default:
                    throw new ArgumentOutOfRangeException("oldList");
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(ArrayItemList<T> oldList)
        {
            int oldCount = oldList.Count;
            if (_entries.Length >= oldCount)
            {
                SetCount(oldList.Count);

                for (int index = 0; index < oldCount; ++index)
                {
                    SetAt(index, oldList.EntryAt(index));
                }
            }
            else
            {
                // this list is smaller than oldList
                throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList");
            }
        }

        public override T[] ToArray()
        {
            T[] array = new T[_count];

            for (int i = 0; i < _count; ++i)
            {
                array[i] = _entries[i];
            }
            return array;
        }

        public override void CopyTo(T[] array, int index)
        {
            for (int i = 0; i < _count; ++i)
            {
                array[index+i] = _entries[i];
            }
        }

        public override object Clone()
        {
            ArrayItemList<T> newList = new ArrayItemList<T>(this.Capacity);
            newList.Promote(this);
            return newList;
        }

        private void SetCount(int value)
        {
            if ((value >= 0) && (value <= _entries.Length))
            {
                _count = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException("value");
            }
        }

        // MINSIZE and GROWTH chosen to minimize memory footprint
        private const int MINSIZE = 9;
        private const int GROWTH = 3;
        private const int LARGEGROWTH = 18;

        private T[] _entries;

        #region Compacter

        public override Compacter NewCompacter(int newCount)
        {
            return new ArrayCompacter(this, newCount);
        }

        // array-based implementation - compacts in-place or into a new array
        internal class ArrayCompacter : FrugalListBase<T>.Compacter
        {
            public ArrayCompacter(ArrayItemList<T> store, int newCount)
                : base(store, newCount)
            {
                _sourceArray = store._entries;

                // compute capacity for target array
                // the first term agrees with AIL.Add, which grows by 5/4
                int newCapacity = Math.Max(newCount + (newCount >> 2), MINSIZE);

                if (newCapacity + (newCapacity >> 2) >= _sourceArray.Length)
                {
                    // if there's not much space to be reclaimed, compact in place
                    _targetStore = store;
                }
                else
                {
                    // otherwise, compact into a smaller array
                    _targetStore = new ArrayItemList<T>(newCapacity);
                }

                _targetArray = _targetStore._entries;
            }

            protected override void IncludeOverride(int start, int end)
            {
                // bulk move
                int size = end - start;
                Array.Copy(_sourceArray, start, _targetArray, _validItemCount, size);
                _validItemCount += size;

                /* The following code is necessary in the general case, to avoid
                 * aliased entries in the old array.  But the only user of Compacter
                 * is DependentList, where aliased entries are not a problem - they'll
                 * just get GC'd along with the old array.

                // when not compacting in place, clear out entries in the source
                if (_targetArray != _sourceArray)
                {
                    T filler = default(T);
                    for (int i=_previousEnd; i<end; ++i)
                    {
                        _sourceArray[i] = filler;
                    }
                }

                */
            }

            public override FrugalListBase<T> Finish()
            {
                // clear out vacated entries in the source
                T filler = default(T);
                if (_sourceArray == _targetArray)
                {
                    // in-place array source
                    for (int i=_validItemCount, n=_store.Count; i<n; ++i)
                    {
                        _sourceArray[i] = filler;
                    }
                }
                else
                {
                    // array source to new array target
                    /* this code is not needed - see remarks in IncludeOverride()
                    for (int i=_previousEnd, n=_store._count; i<n; ++i)
                    {
                        _sourceArray[i] = filler;
                    }
                    */
                }

                // reset Count and return target store
                _targetStore._count = _validItemCount;
                return _targetStore;
            }

            ArrayItemList<T> _targetStore;
            T[] _sourceArray;
            T[] _targetArray;
        }

        #endregion Compacter
    }

    // Use FrugalObjectList when more than one reference to the list is needed.
    // The "object" in FrugalObjectLIst refers to the list itself, not what the list contains.

#if !SYSTEM_XAML
    [FriendAccessAllowed] // Built into Core, also used by Framework.
#endif
    internal class FrugalObjectList<T>
    {
        public FrugalObjectList()
        {
        }

        public FrugalObjectList(int size)
        {
            Capacity = size;
        }

        public int Capacity
        {
            get
            {
                if (null != _listStore)
                {
                    return _listStore.Capacity;
                }
                return 0;
            }
            set
            {
                int capacity = 0;
                if (null != _listStore)
                {
                    capacity = _listStore.Capacity;
                }
                if (capacity < value)
                {
                    // Need to move to a more complex storage
                    FrugalListBase<T> newStore;

                    if (value == 1)
                    {
                        newStore = new SingleItemList<T>();
                    }
                    else if (value <= 3)
                    {
                        newStore = new ThreeItemList<T>();
                    }
                    else if (value <= 6)
                    {
                        newStore = new SixItemList<T>();
                    }
                    else
                    {
                        newStore = new ArrayItemList<T>(value);
                    }

                    if (null != _listStore)
                    {
                        // Move entries in the old store to the new one
                        newStore.Promote(_listStore);
                    }

                    _listStore = newStore;
                }
            }
        }

        public int Count
        {
            get
            {
                if (null != _listStore)
                {
                    return _listStore.Count;
                }
                return 0;
            }
        }

        public T this[int index]
        {
            get
            {
                // If no entry, default(T) is returned
                if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0)))
                {
                    return _listStore.EntryAt(index);
                }
                throw new ArgumentOutOfRangeException("index");
            }

            set
            {
                // Ensure write success
                if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0)))
                {
                    _listStore.SetAt(index, value);
                    return;
                }
                throw new ArgumentOutOfRangeException("index");
            }
        }

        public int Add(T value)
        {
            if (null != _listStore)
            {
                // This is done because forward branches
                // default prediction is not to be taken
                // making this a CPU win because Add is
                // a common operation.
            }
            else
            {
                _listStore = new SingleItemList<T>();
            }

            FrugalListStoreState myState = _listStore.Add(value);
            if (FrugalListStoreState.Success == myState)
            {
            }
            else
            {
                // Need to move to a more complex storage
                // Allocate the store, promote, and add using the derived classes
                // to avoid virtual method calls

                if (FrugalListStoreState.ThreeItemList == myState)
                {
                    ThreeItemList<T> newStore = new ThreeItemList<T>();

                    // Extract the values from the old store and insert them into the new store
                    newStore.Promote(_listStore);

                    // Insert the new item
                    newStore.Add(value);
                    _listStore = newStore;
                }
                else if (FrugalListStoreState.SixItemList == myState)
                {
                    SixItemList<T> newStore = new SixItemList<T>();

                    // Extract the values from the old store and insert them into the new store
                    newStore.Promote(_listStore);
                    _listStore = newStore;

                    // Insert the new item
                    newStore.Add(value);
                    _listStore = newStore;
                }
                else if (FrugalListStoreState.Array == myState)
                {
                    ArrayItemList<T> newStore = new ArrayItemList<T>(_listStore.Count + 1);

                    // Extract the values from the old store and insert them into the new store
                    newStore.Promote(_listStore);
                    _listStore = newStore;

                    // Insert the new item
                    newStore.Add(value);
                    _listStore = newStore;
                }
                else
                {
                    throw new InvalidOperationException(SR.Get(SRID.FrugalList_CannotPromoteBeyondArray));
                }
            }
            return _listStore.Count - 1;
        }

        public void Clear()
        {
            if (null != _listStore)
            {
                _listStore.Clear();
            }
        }

        public bool Contains(T value)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.Contains(value);
            }
            return false;
        }

        public int IndexOf(T value)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.IndexOf(value);
            }
            return -1;
        }

        public void Insert(int index, T value)
        {
            if ((index == 0) || ((null != _listStore) && ((index <= _listStore.Count) && (index >= 0))))
            {
                // Make sure we have a place to put the item
                int minCapacity = 1;

                if ((null != _listStore) && (_listStore.Count == _listStore.Capacity))
                {
                    // Store is full
                    minCapacity = Capacity + 1;
                }

                // Make the Capacity at *least* this big
                Capacity = minCapacity;

                _listStore.Insert(index, value);
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public bool Remove(T value)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.Remove(value);
            }
            return false;
        }

        public void RemoveAt(int index)
        {
            if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0)))
            {
                _listStore.RemoveAt(index);
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public void EnsureIndex(int index)
        {
            if (index >= 0)
            {
                int delta = (index + 1) - Count;
                if (delta > 0)
                {
                    // Grow the store
                    Capacity = index + 1;

                    T filler = default(T);

                    // Insert filler structs or objects
                    for (int i = 0; i < delta; ++i)
                    {
                        _listStore.Add(filler);
                    }
                }
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public T[] ToArray()
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.ToArray();
            }
            return null;
        }

        public void CopyTo(T[] array, int index)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                _listStore.CopyTo(array, index);
            }
        }

        public FrugalObjectList<T> Clone()
        {
            FrugalObjectList<T> myClone = new FrugalObjectList<T>();

            if (null != _listStore)
            {
                myClone._listStore = (FrugalListBase<T>)_listStore.Clone();
            }

            return myClone;
        }

        internal FrugalListBase<T> _listStore;

        #region Compacter
        // helper class - compacts the valid entries, while removing the invalid ones.
        // Usage:
        //      Compacter compacter = new Compacter(this, newCount);
        //      compacter.Include(start, end);      // repeat as necessary
        //      compacter.Finish();
        // newCount is the expected number of valid entries - used to help choose
        //  a target array of appropriate capacity
        // Include(start, end) moves the entries in positions start, ..., end-1 toward
        //  the beginning, appending to the end of the "valid" area.  Successive calls
        //  must be monotonic - i.e. the next 'start' must be >= the previous 'end'.
        //  Also, the sum of the block sizes (end-start) cannot exceed newCount.
        // Finish() puts the provisional target array into permanent use.

        protected class Compacter
        {
            public Compacter(FrugalObjectList<T> list, int newCount)
            {
                _list = list;

                FrugalListBase<T> store = _list._listStore;
                _storeCompacter = (store != null) ? store.NewCompacter(newCount) : null;
            }

            public void Include(int start, int end)
            {
                _storeCompacter.Include(start, end);
            }

            public void Finish()
            {
                if (_storeCompacter != null)
                {
                    _list._listStore = _storeCompacter.Finish();
                }
            }

            FrugalObjectList<T> _list;
            FrugalListBase<T>.Compacter _storeCompacter;
        }
        #endregion Compacter
    }

    // Use FrugalStructList when only one reference to the list is needed.
    // The "struct" in FrugalStructList refers to the list itself, not what the list contains.
#if !SYSTEM_XAML
    [FriendAccessAllowed] // Built into Core, also used by Framework.
#endif
    internal struct FrugalStructList<T>
    {
        public FrugalStructList(int size)
        {
            _listStore = null;
            Capacity = size;
        }

        public FrugalStructList(ICollection collection)
        {
            if (collection.Count > 6)
            {
                _listStore = new ArrayItemList<T>(collection);
            }
            else
            {
                _listStore = null;
                Capacity = collection.Count;
                foreach (T item in collection)
                {
                    Add(item);
                }
            }
        }

        public FrugalStructList(ICollection<T> collection)
        {
            if (collection.Count > 6)
            {
                _listStore = new ArrayItemList<T>(collection);
            }
            else
            {
                _listStore = null;
                Capacity = collection.Count;
                foreach (T item in collection)
                {
                    Add(item);
                }
            }
        }

        public int Capacity
        {
            get
            {
                if (null != _listStore)
                {
                    return _listStore.Capacity;
                }
                return 0;
            }
            set
            {
                int capacity = 0;
                if (null != _listStore)
                {
                    capacity = _listStore.Capacity;
                }
                if (capacity < value)
                {
                    // Need to move to a more complex storage
                    FrugalListBase<T> newStore;

                    if (value == 1)
                    {
                        newStore = new SingleItemList<T>();
                    }
                    else if (value <= 3)
                    {
                        newStore = new ThreeItemList<T>();
                    }
                    else if (value <= 6)
                    {
                        newStore = new SixItemList<T>();
                    }
                    else
                    {
                        newStore = new ArrayItemList<T>(value);
                    }

                    if (null != _listStore)
                    {
                        // Move entries in the old store to the new one
                        newStore.Promote(_listStore);
                    }

                    _listStore = newStore;
                }
            }
        }

        public int Count
        {
            get
            {
                if (null != _listStore)
                {
                    return _listStore.Count;
                }
                return 0;
            }
        }

        public T this[int index]
        {
            get
            {
                // If no entry, default(T) is returned
                if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0)))
                {
                    return _listStore.EntryAt(index);
                }
                throw new ArgumentOutOfRangeException("index");
            }

            set
            {
                // Ensure write success
                if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0)))
                {
                    _listStore.SetAt(index, value);
                    return;
                }
                throw new ArgumentOutOfRangeException("index");
            }
        }

        public int Add(T value)
        {
            if (null != _listStore)
            {
                // This is done because forward branches
                // default prediction is not to be taken
                // making this a CPU win because Add is
                // a common operation.
            }
            else
            {
                _listStore = new SingleItemList<T>();
            }

            FrugalListStoreState myState = _listStore.Add(value);
            if (FrugalListStoreState.Success == myState)
            {
            }
            else
            {
                // Need to move to a more complex storage
                // Allocate the store, promote, and add using the derived classes
                // to avoid virtual method calls

                if (FrugalListStoreState.ThreeItemList == myState)
                {
                    ThreeItemList<T> newStore = new ThreeItemList<T>();

                    // Extract the values from the old store and insert them into the new store
                    newStore.Promote(_listStore);

                    // Insert the new item
                    newStore.Add(value);
                    _listStore = newStore;
                }
                else if (FrugalListStoreState.SixItemList == myState)
                {
                    SixItemList<T> newStore = new SixItemList<T>();

                    // Extract the values from the old store and insert them into the new store
                    newStore.Promote(_listStore);
                    _listStore = newStore;

                    // Insert the new item
                    newStore.Add(value);
                    _listStore = newStore;
                }
                else if (FrugalListStoreState.Array == myState)
                {
                    ArrayItemList<T> newStore = new ArrayItemList<T>(_listStore.Count + 1);

                    // Extract the values from the old store and insert them into the new store
                    newStore.Promote(_listStore);
                    _listStore = newStore;

                    // Insert the new item
                    newStore.Add(value);
                    _listStore = newStore;
                }
                else
                {
                    throw new InvalidOperationException(SR.Get(SRID.FrugalList_CannotPromoteBeyondArray));
                }
            }
            return _listStore.Count - 1;
        }

        public void Clear()
        {
            if (null != _listStore)
            {
                _listStore.Clear();
            }
        }

        public bool Contains(T value)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.Contains(value);
            }
            return false;
        }

        public int IndexOf(T value)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.IndexOf(value);
            }
            return -1;
        }

        public void Insert(int index, T value)
        {
            if ((index == 0) || ((null != _listStore) && ((index <= _listStore.Count) && (index >= 0))))
            {
                // Make sure we have a place to put the item
                int minCapacity = 1;

                if ((null != _listStore) && (_listStore.Count == _listStore.Capacity))
                {
                    // Store is full
                    minCapacity = Capacity + 1;
                }

                // Make the Capacity at *least* this big
                Capacity = minCapacity;

                _listStore.Insert(index, value);
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public bool Remove(T value)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.Remove(value);
            }
            return false;
        }

        public void RemoveAt(int index)
        {
            if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0)))
            {
                _listStore.RemoveAt(index);
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public void EnsureIndex(int index)
        {
            if (index >= 0)
            {
                int delta = (index + 1) - Count;
                if (delta > 0)
                {
                    // Grow the store
                    Capacity = index + 1;

                    T filler = default(T);

                    // Insert filler structs or objects
                    for (int i = 0; i < delta; ++i)
                    {
                        _listStore.Add(filler);
                    }
                }
                return;
            }
            throw new ArgumentOutOfRangeException("index");
        }

        public T[] ToArray()
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                return _listStore.ToArray();
            }
            return null;
        }

        public void CopyTo(T[] array, int index)
        {
            if ((null != _listStore) && (_listStore.Count > 0))
            {
                _listStore.CopyTo(array, index);
            }
        }

        public FrugalStructList<T> Clone()
        {
            FrugalStructList<T> myClone = new FrugalStructList<T>();

            if (null != _listStore)
            {
                myClone._listStore = (FrugalListBase<T>)_listStore.Clone();
            }

            return myClone;
        }

        internal FrugalListBase<T> _listStore;
    }
}


text:
using asssembly_report;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace report
{
    class AssemblyReport
    {
        public static void Usage()
        {
            Console.WriteLine("Usage: specify flename to dissect dependencies");
            Environment.Exit(1);
        }

        static void Main(string[] args)
        {
            var checkReferences = false;
            if (args.Length < 2)
            {
                Usage();
            }

            var exclude = string.Empty;
            if (args.Length == 3)
                exclude = args[2];

            var filename__ = args[0];

            var filenames = new List<string>();
            var excludeFileNames = new List<string>();

            if (File.Exists(filename__))
            {
                filenames.Add(filename__);
            }
            else
            {
                filenames.AddRange(Directory.GetFiles(".", filename__));
                excludeFileNames.AddRange(Directory.GetFiles(".", exclude));

                filenames = filenames.Except(excludeFileNames).ToList();
            }

            var assemblyDetails = new List<AssemblyDetail>();

            foreach (var filename in filenames)
            {
                var file = new FileInfo(filename);
                Console.WriteLine($"Processing ... {filename}");
                try
                {
                    var loadedAssembly = Assembly.LoadFile($@"{file.FullName}");
                    var references = AssemblyReporter.GetReferences(loadedAssembly);

                    var assemblyName = loadedAssembly.GetName();

                    var assemblyDetail = new AssemblyDetail()
                    {
                        Name = file.Name,
                        Version = assemblyName.Version.ToString(),
                        Platform = assemblyName.ProcessorArchitecture.ToString()
                    };

                    assemblyDetails.Add(assemblyDetail);

                    if (checkReferences)
                    {
                        foreach (var reference in references)
                        {
                            Console.Write("  |---");
                            Console.WriteLine($"{reference.Name} {reference.Version}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Fail {filename}: {ex.Message}");
                }
            }

            var json = Newtonsoft.Json.JsonConvert.SerializeObject(assemblyDetails);

            File.WriteAllText(args[1], json);

        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
<?php
namespace Kahlan\Spec\Suite\Filter;

use Kahlan\Plugin\Stub;
use Kahlan\Filter\Chain;

describe("Chain", function () {

    beforeEach(function () {
        $method = 'message';
        $filters = [
            'filter1' => function ($chain, $message) {
                $message = "My {$message}";
                return $chain->next($message);
            },
            'filter2' => function ($chain, $message) {
                return $message;
            }
        ];
        $params = ['World!'];
        $this->chain = new Chain(compact('filters', 'method', 'params'));
    });

    describe("->params()", function () {

        it("gets the params", function () {

            expect($this->chain->params())->toBe(['World!']);

        });

    });

    describe("->method()", function () {

        it("gets the methods", function () {

            expect($this->chain->method())->toBe('message');

        });

    });

    describe("Iterator", function () {

        it("iterate throw the chain", function () {

            expect($this->chain->current())->toBeAnInstanceOf('Closure');
            expect($this->chain->key())->toBe('filter1');
            expect($this->chain->next())->toBe('World!');
            expect($this->chain->next())->toBe(false);
            expect($this->chain->valid())->toBe(false);

        });

        it("procceses a chain", function () {

            $closure = $this->chain->current();
            expect($closure($this->chain, 'Poney!'))->toBe('My Poney!');

        });

        it("counts the number of filters in the chain", function () {

            expect($this->chain)->toHaveLength(2);

        });

    });

});


text:
<?php

namespace App\Application\Controllers\Admin;

use App\Application\Controllers\AbstractController;
use App\Application\DataTables\MenusDataTable;
use App\Application\Model\Item;
use App\Application\Model\Menu;
use App\Application\Repository\InterFaces\MenuInterface;
use App\Application\Requests\Admin\Menu\AddRequestMenu;
use App\Application\Requests\Admin\Menu\UpdateRequestMenu;
use UxWeb\SweetAlert\SweetAlert;
use Yajra\Datatables\Request;
use Alert;

class MenuController extends AbstractController
{
    protected  $menuInterface;
    public function __construct(Menu $model , MenuInterface $menuInterface)
    {
        parent::__construct($model);
        $this->menuInterface = $menuInterface;
    }

    public function index(MenusDataTable $dataTable){
        return $dataTable->render('admin.menu.index');
    }

    public function show($id = null){
        $items = $this->menuInterface->getMenuById($id);
        return $this->createOrEdit('admin.menu.edit' , $id  , ['items' => $items]);
    }

    public function store(AddRequestMenu $request){
         return $this->storeOrUpdate($request , null , 'admin/menu');
    }

    public function update($id , UpdateRequestMenu $request){
        return $this->storeOrUpdate($request , $id , 'admin/menu');
    }

    public function getById($id){
        $fields = $this->model->getConnection()->getSchemaBuilder()->getColumnListing($this->model->getTable());
        return $this->createOrEdit('admin.menu.show' , $id , ['fields' =>  $fields]);
    }

    public function destroy($id){
        return $this->deleteItem($id , 'admin/menu')->with('sucess' , 'Done Delete menu From system');
    }

    public function menuItem(\Illuminate\Http\Request $request){
        return $this->menuInterface->updateMenuItems($request);
    }

    public function addNewItemToMenu(\Illuminate\Http\Request $request){
        return $this->menuInterface->addNewItemToMenu($request);
    }

    public function getItemInfo($id){
        return $this->menuInterface->getItemById($id);
    }

    public function updateOneMenuItem(\Illuminate\Http\Request $request){
        return $this->menuInterface->updateOneMenuItem($request);
    }

    public function pluck(\Illuminate\Http\Request $request){
        return $this->deleteItem($request->id , 'admin/menu')->with('sucess' , 'Done Delete menu From system');
    }

    public function deleteMenuItem($id){
        if(Item::find($id)->delete()){
            Item::where('parent_id' ,$id)->delete();
            SweetAlert::success('Done Delete This Item' ,'Done' );
        }else{
            SweetAlert::error('Done some thing wrong' , 'Error');
        }
        return redirect()->back();
    }
}


text:
#ifndef JAVASCRIPTGRIPPER_H
#define JAVASCRIPTGRIPPER_H

#include <QObject>

class Simulation;
class Gripper;

/**
 * Provides an interface that JavaScript code uses
 * to control the gripper
 */
class JavaScriptGripper : public QObject
{
    Q_OBJECT

    // These properties are available to JavaScript code
    Q_PROPERTY(double x READ getX WRITE setX)
    Q_PROPERTY(double y READ getY WRITE setY)
    Q_PROPERTY(double angle READ getAngle WRITE setAngle)
    Q_PROPERTY(double openDistance READ getOpenDistance WRITE setOpenDistance)
    Q_PROPERTY(bool beamBlocked READ isBeamBlocked)
public:
    explicit JavaScriptGripper(Simulation& simulation, QObject *parent = 0);

    double getX() const;
    void setX(double newX);
    double getY() const;
    void setY(double newY);
    double getAngle() const;
    void setAngle(double angle);
    double getOpenDistance() const;
    void setOpenDistance(double newDistance);

    bool isBeamBlocked() const;

public slots:

    // These methods are available to JavaScript code

    void startOpening();
    void startClosing();

    void startMovingLeft();
    void startMovingRight();
    void startMovingUp();
    void startMovingDown();

    void startMovingPositiveU();
    void startMovingNegativeU();
    void startMovingPositiveV();
    void startMovingNegativeV();

    void startRotatingCounterclockwise();
    void startRotatingClockwise();

	void startRotatingCounterclockwiseAroundOrigin();
	void startRotatingClockwiseAroundOrigin();

    void moveToCenter();

    void stop();

private:

    /**
     * A reference to the Gripper that is being controlled by the script
     */
    Gripper& gripper;
    Simulation& simulation;

signals:

};

#endif // JAVASCRIPTGRIPPER_H


text:
package org.iotivity.test.re.tc.helper;

public class ResourceProperties {
  public static final String URI                       = "/a/TempSensor";
  public static final String TYPE                      = "oic.r.temperature.sensor";
  public static final String INTERFACE                 = "oic.if.";

  public static final String ATTR_KEY_TEMPERATURE      = "Temperature";
  public static final String ATTR_KEY_POWER            = "power";

  public static final String UNFORMATTED_STRING        = "abc";
  public static final String EMPTY_STRING_VALUE        = "";
  public static final String NULL_STRING               = null;

  public static final String OC_RSRVD_WELL_KNOWN_URI   = "/a/TempSensor";
  public static final String RESOURCE_TYPE_TEMPERATURE = "oic.r.temperature.sensor";
}


text:
"""
Virtual gateway for Zigbee Home Automation.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/zha/
"""

import asyncio
import collections
import itertools
import logging
import os
import traceback

from homeassistant.components.system_log import LogEntry, _figure_out_source
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.entity_component import EntityComponent

from ..api import async_get_device_info
from .channels import MAINS_POWERED, ZDOChannel
from .const import (
    ADD_DEVICE_RELAY_LOGGERS, ATTR_MANUFACTURER, BELLOWS, CONF_BAUDRATE,
    CONF_DATABASE, CONF_RADIO_TYPE, CONF_USB_PATH, CONTROLLER, CURRENT,
    DATA_ZHA, DATA_ZHA_BRIDGE_ID, DATA_ZHA_CORE_COMPONENT, DATA_ZHA_GATEWAY,
    DEBUG_LEVELS, DEFAULT_BAUDRATE, DEFAULT_DATABASE_NAME, DEVICE_FULL_INIT,
    DEVICE_INFO, DEVICE_JOINED, DEVICE_REMOVED, DOMAIN, IEEE, LOG_ENTRY,
    LOG_OUTPUT, MODEL, NWK, ORIGINAL, RADIO, RADIO_DESCRIPTION, RAW_INIT,
    SIGNAL_REMOVE, SIGNATURE, TYPE, ZHA, ZHA_GW_MSG, ZIGPY, ZIGPY_DECONZ,
    ZIGPY_XBEE)
from .device import DeviceStatus, ZHADevice
from .discovery import (
    async_create_device_entity, async_dispatch_discovery_info,
    async_process_endpoint)
from .patches import apply_application_controller_patch
from .registries import RADIO_TYPES
from .store import async_get_registry

_LOGGER = logging.getLogger(__name__)

EntityReference = collections.namedtuple(
    'EntityReference', 'reference_id zha_device cluster_channels device_info')

class ZHAGateway:
    """Gateway that handles events that happen on the ZHA Zigbee network."""

    def __init__(self, hass, config):
        """Initialize the gateway."""
        self._hass = hass
        self._config = config
        self._component = EntityComponent(_LOGGER, DOMAIN, hass)
        self._devices = {}
        self._device_registry = collections.defaultdict(list)
        self.zha_storage = None
        self.application_controller = None
        self.radio_description = None
        hass.data[DATA_ZHA][DATA_ZHA_CORE_COMPONENT] = self._component
        hass.data[DATA_ZHA][DATA_ZHA_GATEWAY] = self
        self._log_levels = {
            ORIGINAL: async_capture_log_levels(),
            CURRENT: async_capture_log_levels()
        }
        self.debug_enabled = False
        self._log_relay_handler = LogRelayHandler(hass, self)

    async def async_initialize(self, config_entry):
        """Initialize controller and connect radio."""
        self.zha_storage = await async_get_registry(self._hass)

        usb_path = config_entry.data.get(CONF_USB_PATH)
        baudrate = self._config.get(CONF_BAUDRATE, DEFAULT_BAUDRATE)
        radio_type = config_entry.data.get(CONF_RADIO_TYPE)

        radio_details = RADIO_TYPES[radio_type][RADIO]()
        radio = radio_details[RADIO]
        self.radio_description = RADIO_TYPES[radio_type][RADIO_DESCRIPTION]
        await radio.connect(usb_path, baudrate)

        if CONF_DATABASE in self._config:
            database = self._config[CONF_DATABASE]
        else:
            database = os.path.join(
                self._hass.config.config_dir, DEFAULT_DATABASE_NAME)

        self.application_controller = radio_details[CONTROLLER](
            radio, database)
        apply_application_controller_patch(self)
        self.application_controller.add_listener(self)
        await self.application_controller.startup(auto_form=True)
        self._hass.data[DATA_ZHA][DATA_ZHA_BRIDGE_ID] = str(
            self.application_controller.ieee)

        init_tasks = []
        for device in self.application_controller.devices.values():
            init_tasks.append(self.async_device_initialized(device, False))
        await asyncio.gather(*init_tasks)

    def device_joined(self, device):
        """Handle device joined.

        At this point, no information about the device is known other than its
        address
        """
        async_dispatcher_send(
            self._hass,
            ZHA_GW_MSG,
            {
                TYPE: DEVICE_JOINED,
                NWK: device.nwk,
                IEEE: str(device.ieee)
            }
        )

    def raw_device_initialized(self, device):
        """Handle a device initialization without quirks loaded."""
        endpoint_ids = device.endpoints.keys()
        ept_id = next((ept_id for ept_id in endpoint_ids if ept_id != 0), None)
        manufacturer = 'Unknown'
        model = 'Unknown'
        if ept_id is not None:
            manufacturer = device.endpoints[ept_id].manufacturer
            model = device.endpoints[ept_id].model
        async_dispatcher_send(
            self._hass,
            ZHA_GW_MSG,
            {
                TYPE: RAW_INIT,
                NWK: device.nwk,
                IEEE: str(device.ieee),
                MODEL: model,
                ATTR_MANUFACTURER: manufacturer,
                SIGNATURE: device.get_signature()
            }
        )

    def device_initialized(self, device):
        """Handle device joined and basic information discovered."""
        self._hass.async_create_task(
            self.async_device_initialized(device, True))

    def device_left(self, device):
        """Handle device leaving the network."""
        pass

    def device_removed(self, device):
        """Handle device being removed from the network."""
        zha_device = self._devices.pop(device.ieee, None)
        self._device_registry.pop(device.ieee, None)
        if zha_device is not None:
            device_info = async_get_device_info(self._hass, zha_device)
            self._hass.async_create_task(zha_device.async_unsub_dispatcher())
            async_dispatcher_send(
                self._hass,
                "{}_{}".format(SIGNAL_REMOVE, str(zha_device.ieee))
            )
            if device_info is not None:
                async_dispatcher_send(
                    self._hass,
                    ZHA_GW_MSG,
                    {
                        TYPE: DEVICE_REMOVED,
                        DEVICE_INFO: device_info
                    }
                )

    def get_device(self, ieee):
        """Return ZHADevice for given ieee."""
        return self._devices.get(ieee)

    def get_entity_reference(self, entity_id):
        """Return entity reference for given entity_id if found."""
        for entity_reference in itertools.chain.from_iterable(
                self.device_registry.values()):
            if entity_id == entity_reference.reference_id:
                return entity_reference

    @property
    def devices(self):
        """Return devices."""
        return self._devices

    @property
    def device_registry(self):
        """Return entities by ieee."""
        return self._device_registry

    def register_entity_reference(
            self, ieee, reference_id, zha_device, cluster_channels,
            device_info):
        """Record the creation of a hass entity associated with ieee."""
        self._device_registry[ieee].append(
            EntityReference(
                reference_id=reference_id,
                zha_device=zha_device,
                cluster_channels=cluster_channels,
                device_info=device_info
            )
        )

    @callback
    def async_enable_debug_mode(self):
        """Enable debug mode for ZHA."""
        self._log_levels[ORIGINAL] = async_capture_log_levels()
        async_set_logger_levels(DEBUG_LEVELS)
        self._log_levels[CURRENT] = async_capture_log_levels()

        for logger_name in ADD_DEVICE_RELAY_LOGGERS:
            logging.getLogger(logger_name).addHandler(self._log_relay_handler)

        self.debug_enabled = True

    @callback
    def async_disable_debug_mode(self):
        """Disable debug mode for ZHA."""
        async_set_logger_levels(self._log_levels[ORIGINAL])
        self._log_levels[CURRENT] = async_capture_log_levels()
        for logger_name in ADD_DEVICE_RELAY_LOGGERS:
            logging.getLogger(logger_name).removeHandler(
                self._log_relay_handler)
        self.debug_enabled = False

    @callback
    def _async_get_or_create_device(self, zigpy_device, is_new_join):
        """Get or create a ZHA device."""
        zha_device = self._devices.get(zigpy_device.ieee)
        if zha_device is None:
            zha_device = ZHADevice(self._hass, zigpy_device, self)
            self._devices[zigpy_device.ieee] = zha_device
        if not is_new_join:
            entry = self.zha_storage.async_get_or_create(zha_device)
            zha_device.async_update_last_seen(entry.last_seen)
            zha_device.set_power_source(entry.power_source)
        return zha_device

    @callback
    def async_device_became_available(
            self, sender, is_reply, profile, cluster, src_ep, dst_ep, tsn,
            command_id, args):
        """Handle tasks when a device becomes available."""
        self.async_update_device(sender)

    @callback
    def async_update_device(self, sender):
        """Update device that has just become available."""
        if sender.ieee in self.devices:
            device = self.devices[sender.ieee]
            # avoid a race condition during new joins
            if device.status is DeviceStatus.INITIALIZED:
                device.update_available(True)

    async def async_update_device_storage(self):
        """Update the devices in the store."""
        for device in self.devices.values():
            self.zha_storage.async_update(device)
        await self.zha_storage.async_save()

    async def async_device_initialized(self, device, is_new_join):
        """Handle device joined and basic information discovered (async)."""
        zha_device = self._async_get_or_create_device(device, is_new_join)

        discovery_infos = []
        for endpoint_id, endpoint in device.endpoints.items():
            async_process_endpoint(
                self._hass, self._config, endpoint_id, endpoint,
                discovery_infos, device, zha_device, is_new_join
            )
            if endpoint_id != 0:
                for cluster in endpoint.in_clusters.values():
                    cluster.bind_only = False
                for cluster in endpoint.out_clusters.values():
                    cluster.bind_only = True

        if is_new_join:
            # configure the device
            await zha_device.async_configure()
            zha_device.update_available(True)
        elif zha_device.power_source is not None\
                and zha_device.power_source == MAINS_POWERED:
            # the device isn't a battery powered device so we should be able
            # to update it now
            _LOGGER.debug(
                "attempting to request fresh state for %s %s",
                zha_device.name,
                "with power source: {}".format(
                    ZDOChannel.POWER_SOURCES.get(zha_device.power_source)
                )
            )
            await zha_device.async_initialize(from_cache=False)
        else:
            await zha_device.async_initialize(from_cache=True)

        for discovery_info in discovery_infos:
            async_dispatch_discovery_info(
                self._hass,
                is_new_join,
                discovery_info
            )

        device_entity = async_create_device_entity(zha_device)
        await self._component.async_add_entities([device_entity])

        if is_new_join:
            device_info = async_get_device_info(self._hass, zha_device)
            async_dispatcher_send(
                self._hass,
                ZHA_GW_MSG,
                {
                    TYPE: DEVICE_FULL_INIT,
                    DEVICE_INFO: device_info
                }
            )

    async def shutdown(self):
        """Stop ZHA Controller Application."""
        _LOGGER.debug("Shutting down ZHA ControllerApplication")
        await self.application_controller.shutdown()

@callback
def async_capture_log_levels():
    """Capture current logger levels for ZHA."""
    return {
        BELLOWS: logging.getLogger(BELLOWS).getEffectiveLevel(),
        ZHA: logging.getLogger(ZHA).getEffectiveLevel(),
        ZIGPY: logging.getLogger(ZIGPY).getEffectiveLevel(),
        ZIGPY_XBEE: logging.getLogger(ZIGPY_XBEE).getEffectiveLevel(),
        ZIGPY_DECONZ: logging.getLogger(ZIGPY_DECONZ).getEffectiveLevel(),
    }

@callback
def async_set_logger_levels(levels):
    """Set logger levels for ZHA."""
    logging.getLogger(BELLOWS).setLevel(levels[BELLOWS])
    logging.getLogger(ZHA).setLevel(levels[ZHA])
    logging.getLogger(ZIGPY).setLevel(levels[ZIGPY])
    logging.getLogger(ZIGPY_XBEE).setLevel(levels[ZIGPY_XBEE])
    logging.getLogger(ZIGPY_DECONZ).setLevel(levels[ZIGPY_DECONZ])

class LogRelayHandler(logging.Handler):
    """Log handler for error messages."""

    def __init__(self, hass, gateway):
        """Initialize a new LogErrorHandler."""
        super().__init__()
        self.hass = hass
        self.gateway = gateway

    def emit(self, record):
        """Relay log message via dispatcher."""
        stack = []
        if record.levelno >= logging.WARN:
            if not record.exc_info:
                stack = [f for f, _, _, _ in traceback.extract_stack()]

        entry = LogEntry(record, stack,
                         _figure_out_source(record, stack, self.hass))
        async_dispatcher_send(
            self.hass,
            ZHA_GW_MSG,
            {
                TYPE: LOG_OUTPUT,
                LOG_ENTRY: entry.to_dict()
            }
        )


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information

namespace Dnn.PersonaBar.Users.Components.Prompt.Commands
{
    using System.Collections.Generic;
    using System.Linq;

    using Dnn.PersonaBar.Library.Prompt;
    using Dnn.PersonaBar.Library.Prompt.Attributes;
    using Dnn.PersonaBar.Library.Prompt.Models;
    using Dnn.PersonaBar.Users.Components.Prompt.Models;
    using DotNetNuke.Entities.Portals;
    using DotNetNuke.Entities.Users;

    [ConsoleCommand("get-user", Constants.UsersCategory, "Prompt_GetUser_Description")]
    public class GetUser : ConsoleCommandBase
    {
        [FlagParameter("id", "Prompt_GetUser_FlagId", "Integer")]
        private const string FlagId = "id";

        [FlagParameter("email", "Prompt_GetUser_FlagEmail", "String")]
        private const string FlagEmail = "email";

        [FlagParameter("username", "Prompt_GetUser_FlagUsername", "String")]
        private const string FlagUsername = "username";

        private const int UserIdZero = 0;

        private IUserValidator _userValidator;
        private IUserControllerWrapper _userControllerWrapper;

        public GetUser() : this(new UserValidator(), new UserControllerWrapper())
        {
        }

        public GetUser(IUserValidator userValidator, IUserControllerWrapper userControllerWrapper)
        {
            this._userValidator = userValidator;
            this._userControllerWrapper = userControllerWrapper;
        }

        public override string LocalResourceFile => Constants.LocalResourcesFile;

        private int? UserId { get; set; }

        private string Email { get; set; }

        private string Username { get; set; }

        public override void Init(string[] args, PortalSettings portalSettings, UserInfo userInfo, int activeTabId)
        {

            this.UserId = this.GetFlagValue<int?>(FlagId, "User Id", null);
            this.Email = this.GetFlagValue(FlagEmail, "Email", string.Empty);
            this.Username = this.GetFlagValue(FlagUsername, "Username", string.Empty);

            if (args.Length != 1)
            {
                if (args.Length == 2 && !this.UserId.HasValue && string.IsNullOrEmpty(this.Email) && string.IsNullOrEmpty(this.Username))
                {
                    // only one value passed and it's not a flagged value. Try to interpret it.
                    if (args[1].Contains("@"))
                    {
                        this.Email = args[1];
                    }
                    else
                    {
                        int tmpId;
                        if (int.TryParse(args[1], out tmpId))
                        {
                            this.UserId = tmpId;
                        }
                        else
                        {
                            // assume it's a username
                            this.Username = args[1];
                        }
                    }
                }
                if (!this.UserId.HasValue && string.IsNullOrEmpty(this.Email) && string.IsNullOrEmpty(this.Username))
                {
                    this.AddMessage(this.LocalizeString("Prompt_SearchUserParameterRequired"));
                }
            }
        }

        public override ConsoleResultModel Run()
        {
            var lst = new List<UserModel>();

            // if no argument, default to current user
            if (this.Args.Length == 1)
            {
                lst.Add(new UserModel(this.User));
            }
            else
            {
                var recCount = 0;
                var userId = this.UserId;
                if (!userId.HasValue && !string.IsNullOrEmpty(this.Username))
                {
                    // do username lookup
                    var searchTerm = this.Username.Replace("%", "").Replace("*", "%");

                    userId = this._userControllerWrapper.GetUsersByUserName(this.PortalId, searchTerm, -1, int.MaxValue, ref recCount, true, false) ?? UserIdZero;
                    // search against superusers if no regular user found
                    if (userId == UserIdZero)
                    {
                        // userId = (UserController.GetUsersByUserName(-1, searchTerm, -1, int.MaxValue, ref recCount, true, true).ToArray().FirstOrDefault() as UserInfo)?.UserID ?? UserIdZero;
                        userId = this._userControllerWrapper.GetUsersByUserName(-1, searchTerm, -1, int.MaxValue, ref recCount, true, true) ?? UserIdZero;
                    }
                }
                else if (!userId.HasValue && !string.IsNullOrEmpty(this.Email))
                {
                    // must be email
                    var searchTerm = this.Email.Replace("%", "").Replace("*", "%");

                    userId = this._userControllerWrapper.GetUsersByEmail(this.PortalId, searchTerm, -1, int.MaxValue, ref recCount, true, false) ?? UserIdZero;

                    // search against superusers if no regular user found
                    if (userId == UserIdZero)
                    {
                        userId = this._userControllerWrapper.GetUsersByEmail(-1, searchTerm, -1, int.MaxValue, ref recCount, true, true) ?? UserIdZero;
                    }
                }

                UserInfo userInfo;
                ConsoleErrorResultModel errorResultModel =
                    this._userValidator.ValidateUser(userId, this.PortalSettings, this.User, out userInfo);

                if (errorResultModel != null)
                {
                    return errorResultModel;
                }

                lst.Add(new UserModel(userInfo));
            }

            return new ConsoleResultModel(string.Empty)
            {
                Data = lst,
                Records = lst.Count,
                FieldOrder = new[]
                {
                    "UserId",
                    "Username",
                    "DisplayName",
                    "FirstName",
                    "LastName",
                    "Email",
                    "LastActivity",
                    "LastLogin",
                    "LastLockout",
                    "LastPasswordChange",
                    "IsDeleted",
                    "IsAuthorized",
                    "IsLockedOut",
                    "Created"
                },
            };
        }
    }
}