aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Sorting/BaseItemComparer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/Sorting/BaseItemComparer.cs')
-rw-r--r--MediaBrowser.Controller/Sorting/BaseItemComparer.cs231
1 files changed, 231 insertions, 0 deletions
diff --git a/MediaBrowser.Controller/Sorting/BaseItemComparer.cs b/MediaBrowser.Controller/Sorting/BaseItemComparer.cs
new file mode 100644
index 000000000..6e49f396f
--- /dev/null
+++ b/MediaBrowser.Controller/Sorting/BaseItemComparer.cs
@@ -0,0 +1,231 @@
+using MediaBrowser.Common.Logging;
+using MediaBrowser.Controller.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Sorting {
+ /// <summary>
+ /// Class BaseItemComparer
+ /// </summary>
+ public class BaseItemComparer : IComparer<BaseItem> {
+ /// <summary>
+ /// The _order
+ /// </summary>
+ private readonly SortOrder _order;
+ /// <summary>
+ /// The _property name
+ /// </summary>
+ private readonly string _propertyName;
+ /// <summary>
+ /// The _compare culture
+ /// </summary>
+ private readonly StringComparison _compareCulture = StringComparison.CurrentCultureIgnoreCase;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseItemComparer" /> class.
+ /// </summary>
+ /// <param name="order">The order.</param>
+ public BaseItemComparer(SortOrder order) {
+ _order = order;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseItemComparer" /> class.
+ /// </summary>
+ /// <param name="order">The order.</param>
+ /// <param name="compare">The compare.</param>
+ public BaseItemComparer(SortOrder order, StringComparison compare) {
+ _order = order;
+ _compareCulture = compare;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseItemComparer" /> class.
+ /// </summary>
+ /// <param name="property">The property.</param>
+ public BaseItemComparer(string property) {
+ _order = SortOrder.Custom;
+ _propertyName = property;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseItemComparer" /> class.
+ /// </summary>
+ /// <param name="property">The property.</param>
+ /// <param name="compare">The compare.</param>
+ public BaseItemComparer(string property, StringComparison compare) {
+ _order = SortOrder.Custom;
+ _propertyName = property;
+ _compareCulture = compare;
+ }
+
+ #region IComparer<BaseItem> Members
+
+ /// <summary>
+ /// Compares the specified x.
+ /// </summary>
+ /// <param name="x">The x.</param>
+ /// <param name="y">The y.</param>
+ /// <returns>System.Int32.</returns>
+ public int Compare(BaseItem x, BaseItem y) {
+ int compare = 0;
+
+ switch (_order) {
+
+ case SortOrder.Date:
+ compare = -x.DateCreated.CompareTo(y.DateCreated);
+ break;
+
+ case SortOrder.Year:
+
+ var xProductionYear = x.ProductionYear ?? 0;
+ var yProductionYear = y.ProductionYear ?? 0;
+
+
+ compare = yProductionYear.CompareTo(xProductionYear);
+ break;
+
+ case SortOrder.Rating:
+
+ var xRating = x.CommunityRating ?? 0;
+ var yRating = y.CommunityRating ?? 0;
+
+ compare = yRating.CompareTo(xRating);
+ break;
+
+ case SortOrder.Runtime:
+ var xRuntime = x.RunTimeTicks ?? 0;
+ var yRuntime = y.RunTimeTicks ?? 0;
+
+ compare = xRuntime.CompareTo(yRuntime);
+ break;
+
+ case SortOrder.Custom:
+
+ Logger.LogDebugInfo("Sorting on custom field " + _propertyName);
+ var yProp = y.GetType().GetProperty(_propertyName);
+ var xProp = x.GetType().GetProperty(_propertyName);
+ if (yProp == null || xProp == null) break;
+ var yVal = yProp.GetValue(y, null);
+ var xVal = xProp.GetValue(x,null);
+ if (yVal == null && xVal == null) break;
+ if (yVal == null) return 1;
+ if (xVal == null) return -1;
+ compare = String.Compare(xVal.ToString(), yVal.ToString(),_compareCulture);
+ break;
+
+ default:
+ compare = 0;
+ break;
+ }
+
+ if (compare == 0) {
+
+ var name1 = x.SortName ?? x.Name ?? "";
+ var name2 = y.SortName ?? y.Name ?? "";
+
+ //if (Config.Instance.EnableAlphanumericSorting)
+ compare = AlphaNumericCompare(name1, name2,_compareCulture);
+ //else
+ // compare = String.Compare(name1,name2,_compareCulture);
+ }
+
+ return compare;
+ }
+
+
+ #endregion
+
+ /// <summary>
+ /// Alphas the numeric compare.
+ /// </summary>
+ /// <param name="s1">The s1.</param>
+ /// <param name="s2">The s2.</param>
+ /// <param name="compareCulture">The compare culture.</param>
+ /// <returns>System.Int32.</returns>
+ public static int AlphaNumericCompare(string s1, string s2, StringComparison compareCulture) {
+ // http://dotnetperls.com/Content/Alphanumeric-Sorting.aspx
+
+ int len1 = s1.Length;
+ int len2 = s2.Length;
+ int marker1 = 0;
+ int marker2 = 0;
+
+ // Walk through two the strings with two markers.
+ while (marker1 < len1 && marker2 < len2) {
+ char ch1 = s1[marker1];
+ char ch2 = s2[marker2];
+
+ // Some buffers we can build up characters in for each chunk.
+ var space1 = new char[len1];
+ var loc1 = 0;
+ var space2 = new char[len2];
+ var loc2 = 0;
+
+ // Walk through all following characters that are digits or
+ // characters in BOTH strings starting at the appropriate marker.
+ // Collect char arrays.
+ do {
+ space1[loc1++] = ch1;
+ marker1++;
+
+ if (marker1 < len1) {
+ ch1 = s1[marker1];
+ } else {
+ break;
+ }
+ } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
+
+ do {
+ space2[loc2++] = ch2;
+ marker2++;
+
+ if (marker2 < len2) {
+ ch2 = s2[marker2];
+ } else {
+ break;
+ }
+ } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
+
+ // If we have collected numbers, compare them numerically.
+ // Otherwise, if we have strings, compare them alphabetically.
+ var str1 = new string(space1);
+ var str2 = new string(space2);
+
+ var result = 0;
+
+ //biggest int - 2147483647
+ if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]) /*&& str1.Length < 10 && str2.Length < 10*/) //this assumed the entire string was a number...
+ {
+ int thisNumericChunk;
+ var isValid = false;
+
+ if (int.TryParse(str1.Substring(0, str1.Length > 9 ? 10 : str1.Length), out thisNumericChunk))
+ {
+ int thatNumericChunk;
+
+ if (int.TryParse(str2.Substring(0, str2.Length > 9 ? 10 : str2.Length), out thatNumericChunk))
+ {
+ isValid = true;
+ result = thisNumericChunk.CompareTo(thatNumericChunk);
+ }
+ }
+
+ if (!isValid)
+ {
+ Logger.LogError("Error comparing numeric strings: " + str1 + "/" + str2);
+ result = String.Compare(str1, str2, compareCulture);
+ }
+
+ } else {
+ result = String.Compare(str1,str2,compareCulture);
+ }
+
+ if (result != 0) {
+ return result;
+ }
+ }
+ return len1 - len2;
+ }
+ }
+}