Beispiel #1
0
 internal static List<GroupInfo> DoGrouping(List<OrderByPropertyEntry> orderMatrix, OrderByPropertyComparer comparer, bool noElement)
 {
     if (((orderMatrix == null) || (orderMatrix.Count == 0)) || (comparer == null))
     {
         return null;
     }
     List<GroupInfo> groups = new List<GroupInfo>();
     foreach (OrderByPropertyEntry entry in orderMatrix)
     {
         int num = FindInObjectGroups(groups, entry, comparer);
         if (num == -1)
         {
             tracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Create a new group: {0}", new object[] { entry.orderValues }), new object[0]);
             GroupInfo item = noElement ? new GroupInfoNoElement(entry) : new GroupInfo(entry);
             groups.Add(item);
         }
         else
         {
             tracer.WriteLine(string.Format(CultureInfo.InvariantCulture, "Add to group {0}: {1}", new object[] { num, entry.orderValues }), new object[0]);
             PSObject inputObject = entry.inputObject;
             groups[num].Add(inputObject);
         }
     }
     return groups;
 }
        /// <summary>
        /// Moves unique entries to the front of the list.
        /// </summary>
        private int MoveUniqueEntriesToFront(List <OrderByPropertyEntry> sortedData, OrderByPropertyComparer comparer)
        {
            // If we have sorted data then we know we have at least one unique item
            int uniqueCount = sortedData.Count > 0 ? 1 : 0;

            // Move the first of each unique entry to the front of the list
            for (int uniqueItemIndex = 0, nextUniqueItemIndex = 1; uniqueItemIndex < sortedData.Count && uniqueCount != Top; uniqueItemIndex++, nextUniqueItemIndex++)
            {
                // Identify the index of the next unique item
                while (nextUniqueItemIndex < sortedData.Count && comparer.Compare(sortedData[uniqueItemIndex], sortedData[nextUniqueItemIndex]) == 0)
                {
                    nextUniqueItemIndex++;
                }

                // If there are no more unique items, break
                if (nextUniqueItemIndex == sortedData.Count)
                {
                    break;
                }

                // Move the next unique item forward and increment the unique item counter
                sortedData[uniqueItemIndex + 1] = sortedData[nextUniqueItemIndex];
                uniqueCount++;
            }

            return(uniqueCount);
        }
Beispiel #3
0
        private static OrderByPropertyComparer CreateComparer(
            List <OrderByPropertyEntry> orderMatrix,
            List <MshParameter> mshParameterList,
            bool ascending,
            CultureInfo cultureInfo,
            bool caseSensitive)
        {
            if (orderMatrix == null || orderMatrix.Count == 0)
            {
                return(null);
            }

            bool?[] ascendingOverrides = null;
            if (mshParameterList != null && mshParameterList.Count != 0)
            {
                ascendingOverrides = new bool?[mshParameterList.Count];
                for (int k = 0; k < ascendingOverrides.Length; k++)
                {
                    object ascendingVal = mshParameterList[k].GetEntry(
                        SortObjectParameterDefinitionKeys.AscendingEntryKey);
                    object descendingVal = mshParameterList[k].GetEntry(
                        SortObjectParameterDefinitionKeys.DescendingEntryKey);
                    bool isAscendingDefined  = isOrderEntryKeyDefined(ascendingVal);
                    bool isDescendingDefined = isOrderEntryKeyDefined(descendingVal);
                    if (!isAscendingDefined && !isDescendingDefined)
                    {
                        // if neither ascending nor descending is defined
                        ascendingOverrides[k] = null;
                    }
                    else if (isAscendingDefined && isDescendingDefined &&
                             (bool)ascendingVal == (bool)descendingVal)
                    {
                        // if both ascending and descending defined but their values conflict
                        // they are ignored.
                        ascendingOverrides[k] = null;
                    }
                    else if (isAscendingDefined)
                    {
                        ascendingOverrides[k] = (bool)ascendingVal;
                    }
                    else
                    {
                        ascendingOverrides[k] = !(bool)descendingVal;
                    }
                }
            }

            OrderByPropertyComparer comparer =
                OrderByPropertyComparer.CreateComparer(orderMatrix, ascending,
                                                       ascendingOverrides, cultureInfo, caseSensitive);

            return(comparer);
        }
        /// <summary>
        /// Sort unsorted OrderByPropertyEntry data using a full sort.
        /// </summary>
        private int FullSort(List <OrderByPropertyEntry> dataToSort, OrderByPropertyComparer comparer)
        {
            // Track how many items in the list are sorted
            int sortedItemCount = dataToSort.Count;

            // Future: It may be worth comparing List.Sort with SortedSet when handling unique
            // records in case SortedSet is faster (SortedSet was not an option in earlier
            // versions of PowerShell).
            dataToSort.Sort(comparer);

            if (Unique)
            {
                // Move unique entries to the front of the list (this is significantly faster
                // than removing them)
                sortedItemCount = MoveUniqueEntriesToFront(dataToSort, comparer);
            }

            return(sortedItemCount);
        }
Beispiel #5
0
        /// <summary>
        /// Process every input object to group them.
        /// </summary>
        protected override void ProcessRecord()
        {
            if (InputObject != null && InputObject != AutomationNull.Value)
            {
                OrderByPropertyEntry currentEntry = null;

                if (!_hasProcessedFirstInputObject)
                {
                    if (Property == null)
                    {
                        Property = OrderByProperty.GetDefaultKeyPropertySet(InputObject);
                    }
                    _orderByProperty.ProcessExpressionParameter(this, Property);

                    currentEntry = _orderByProperty.CreateOrderByPropertyEntry(this, InputObject, CaseSensitive, _cultureInfo);
                    bool[] ascending = new bool[currentEntry.orderValues.Count];
                    for (int index = 0; index < currentEntry.orderValues.Count; index++)
                    {
                        ascending[index] = true;
                    }
                    _orderByPropertyComparer = new OrderByPropertyComparer(ascending, _cultureInfo, CaseSensitive);

                    _hasProcessedFirstInputObject = true;
                }
                else
                {
                    currentEntry = _orderByProperty.CreateOrderByPropertyEntry(this, InputObject, CaseSensitive, _cultureInfo);
                }

                DoGrouping(currentEntry, this.NoElement, _groups, _tupleToGroupInfoMappingDictionary, _orderByPropertyComparer);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Utility function called by Group-Object to create Groups.
        /// </summary>
        /// <param name="currentObjectEntry">Input object that needs to be grouped.</param>
        /// <param name="noElement">true if we are not accumulating objects</param>
        /// <param name="groups">List containing Groups.</param>
        /// <param name="groupInfoDictionary">Dictionary used to keep track of the groups with hash of the property values being the key.</param>
        /// <param name="orderByPropertyComparer">The Comparer to be used while comparing to check if new group has to be created.</param>
        internal static void DoGrouping(OrderByPropertyEntry currentObjectEntry, bool noElement, List<GroupInfo> groups, Dictionary<object, GroupInfo> groupInfoDictionary,
            OrderByPropertyComparer orderByPropertyComparer)
        {
            if (currentObjectEntry != null && currentObjectEntry.orderValues != null && currentObjectEntry.orderValues.Count > 0)
            {
                object currentTupleObject = PSTuple.ArrayToTuple(currentObjectEntry.orderValues.ToArray());

                GroupInfo currentGroupInfo = null;
                if (groupInfoDictionary.TryGetValue(currentTupleObject, out currentGroupInfo))
                {
                    if (currentGroupInfo != null)
                    {
                        //add this inputObject to an existing group
                        currentGroupInfo.Add(currentObjectEntry.inputObject);
                    }
                }
                else
                {
                    bool isCurrentItemGrouped = false;

                    for (int groupsIndex = 0; groupsIndex < groups.Count; groupsIndex++)
                    {
                        // Check if the current input object can be converted to one of the already known types 
                        // by looking up in the type to GroupInfo mapping.
                        if (orderByPropertyComparer.Compare(groups[groupsIndex].GroupValue, currentObjectEntry) == 0)
                        {
                            groups[groupsIndex].Add(currentObjectEntry.inputObject);
                            isCurrentItemGrouped = true;
                            break;
                        }
                    }

                    if (!isCurrentItemGrouped)
                    {
                        // create a new group
                        s_tracer.WriteLine("Create a new group: {0}", currentObjectEntry.orderValues);
                        GroupInfo newObjGrp = noElement ? new GroupInfoNoElement(currentObjectEntry) : new GroupInfo(currentObjectEntry);
                        groups.Add(newObjGrp);

                        groupInfoDictionary.Add(currentTupleObject, newObjGrp);
                    }
                }
            }
        }
Beispiel #7
0
        private void InitComparer()
        {
            if (null != _comparer)
                return;

            List<PSObject> referenceObjectList = new List<PSObject>(ReferenceObject);
            _orderByProperty = new OrderByProperty(
                this, referenceObjectList, Property, true, _cultureInfo, CaseSensitive);
            Diagnostics.Assert(_orderByProperty.Comparer != null, "no comparer");
            Diagnostics.Assert(
                _orderByProperty.OrderMatrix != null &&
                _orderByProperty.OrderMatrix.Count == ReferenceObject.Length,
                "no OrderMatrix");
            if (_orderByProperty.Comparer == null || _orderByProperty.OrderMatrix == null || _orderByProperty.OrderMatrix.Count == 0)
            {
                return;
            }

            _comparer = _orderByProperty.Comparer;
            _referenceEntries = _orderByProperty.OrderMatrix;
        }
Beispiel #8
0
 internal OrderByProperty(PSCmdlet cmdlet, List<PSObject> inputObjects, object[] expr, bool ascending, CultureInfo cultureInfo, bool caseSensitive)
 {
     ProcessExpressionParameter(inputObjects, cmdlet, expr, out this._mshParameterList);
     this.orderMatrix = CreateOrderMatrix(cmdlet, inputObjects, this._mshParameterList);
     this.comparer = CreateComparer(this.orderMatrix, this._mshParameterList, ascending, cultureInfo, caseSensitive);
 }
 internal IndexedOrderByPropertyComparer(OrderByPropertyComparer orderByPropertyComparer)
 {
     _orderByPropertyComparer = orderByPropertyComparer;
 }
Beispiel #10
0
 private static int FindInObjectGroups(List<GroupInfo> groups, OrderByPropertyEntry target, OrderByPropertyComparer comparer)
 {
     for (int i = 0; i < groups.Count; i++)
     {
         if (comparer.Compare(groups[i].GroupValue, target) == 0)
         {
             return i;
         }
     }
     return -1;
 }
Beispiel #11
0
        /// <summary>
        /// Sort unsorted OrderByPropertyEntry data using an indexed min-/max-heap sort.
        /// </summary>
        private int Heapify(List <OrderByPropertyEntry> dataToSort, OrderByPropertyComparer orderByPropertyComparer)
        {
            // Instantiate the Heapify comparer, which takes index into account for sort stability
            var comparer = new IndexedOrderByPropertyComparer(orderByPropertyComparer);

            // Identify how many items will be in the heap and the current number of items
            int heapCount    = 0;
            int heapCapacity = Stable ? int.MaxValue
                                      : Top > 0 ? Top : Bottom;

            // Identify the comparator (the value all comparisons will be made against based on whether we're
            // doing a Top N or Bottom N sort)
            // Note: All comparison results in the loop below are performed related to the value of the
            // comparator. OrderByPropertyComparer.Compare will return -1 to indicate that the lhs is smaller
            // if an ascending sort is being executed, or -1 to indicate that the lhs is larger if a descending
            // sort is being executed. The comparator will be -1 if we're executing a Top N sort, or 1 if we're
            // executing a Bottom N sort. These two pairs of states allow us to perform the proper comparison
            // regardless of whether we're executing an ascending or descending Top N or Bottom N sort. This
            // allows us to build a min-heap or max-heap for each of these sorts with the exact same logic.
            // Min-heap: used for faster processing of a top N descending sort and a bottom N ascending sort
            // Max-heap: used for faster processing of a top N ascending sort and a bottom N descending sort
            int comparator = Top > 0 ? -1 : 1;

            // For unique sorts, use a sorted set to avoid adding unique items to the heap
            SortedSet <OrderByPropertyEntry> uniqueSet = Unique ? new SortedSet <OrderByPropertyEntry>(orderByPropertyComparer) : null;

            // Tracking the index is necessary so that unsortable items can be output at the end, in the order
            // in which they were received.
            for (int dataIndex = 0, discardedDuplicates = 0; dataIndex < dataToSort.Count - discardedDuplicates; dataIndex++)
            {
                // Min-heap: if the heap is full and the root item is larger than the entry, discard the entry
                // Max-heap: if the heap is full and the root item is smaller than the entry, discard the entry
                if (heapCount == heapCapacity && comparer.Compare(dataToSort[0], dataToSort[dataIndex]) == comparator)
                {
                    continue;
                }

                // If we're doing a unique sort and the entry is not unique, discard the duplicate entry
                if (Unique && !uniqueSet.Add(dataToSort[dataIndex]))
                {
                    discardedDuplicates++;
                    if (dataIndex != dataToSort.Count - discardedDuplicates)
                    {
                        // When discarding duplicates, replace them with an item at the end of the list and
                        // adjust our counter so that we check the item we just swapped in next
                        dataToSort[dataIndex] = dataToSort[dataToSort.Count - discardedDuplicates];
                        dataIndex--;
                    }

                    continue;
                }

                // Add the current item to the heap and bubble it up into the correct position
                int childIndex = dataIndex;
                while (childIndex > 0)
                {
                    int parentIndex = ((childIndex > (heapCapacity - 1) ? heapCapacity : childIndex) - 1) >> 1;

                    // Min-heap: if the child item is larger than its parent, break
                    // Max-heap: if the child item is smaller than its parent, break
                    if (comparer.Compare(dataToSort[childIndex], dataToSort[parentIndex]) == comparator)
                    {
                        break;
                    }

                    var temp = dataToSort[parentIndex];
                    dataToSort[parentIndex] = dataToSort[childIndex];
                    dataToSort[childIndex]  = temp;

                    childIndex = parentIndex;
                }

                heapCount++;

                // If the heap size is too large, remove the root and rearrange the heap
                if (heapCount > heapCapacity)
                {
                    // Move the last item to the root and reset the heap count (this effectively removes the last item)
                    dataToSort[0] = dataToSort[dataIndex];
                    heapCount     = heapCapacity;

                    // Bubble the root item down into the correct position
                    int parentIndex     = 0;
                    int parentItemCount = heapCapacity >> 1;
                    while (parentIndex < parentItemCount)
                    {
                        // Min-heap: use the smaller of the two children in the comparison
                        // Max-heap: use the larger of the two children in the comparison
                        int leftChildIndex  = (parentIndex << 1) + 1;
                        int rightChildIndex = leftChildIndex + 1;
                        childIndex = rightChildIndex == heapCapacity || comparer.Compare(dataToSort[leftChildIndex], dataToSort[rightChildIndex]) != comparator
                            ? leftChildIndex
                            : rightChildIndex;

                        // Min-heap: if the smallest child is larger than or equal to its parent, break
                        // Max-heap: if the largest child is smaller than or equal to its parent, break
                        int childComparisonResult = comparer.Compare(dataToSort[childIndex], dataToSort[parentIndex]);
                        if (childComparisonResult == 0 || childComparisonResult == comparator)
                        {
                            break;
                        }

                        var temp = dataToSort[childIndex];
                        dataToSort[childIndex]  = dataToSort[parentIndex];
                        dataToSort[parentIndex] = temp;

                        parentIndex = childIndex;
                    }
                }
            }

            dataToSort.Sort(0, heapCount, comparer);

            return(heapCount);
        }
Beispiel #12
0
 private void InitComparer()
 {
     if (this.comparer == null)
     {
         List<PSObject> inputObjects = new List<PSObject>(this.ReferenceObject);
         this.orderByProperty = new OrderByProperty(this, inputObjects, this.Property, true, base._cultureInfo, (bool) base.CaseSensitive);
         if (((this.orderByProperty.Comparer != null) && (this.orderByProperty.OrderMatrix != null)) && (this.orderByProperty.OrderMatrix.Count != 0))
         {
             this.comparer = this.orderByProperty.Comparer;
             this.referenceEntries = this.orderByProperty.OrderMatrix;
         }
     }
 }