This repository has been archived by the owner on Nov 20, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 199
/
MediaTypeHeaderValueComparer.cs
132 lines (122 loc) · 5.25 KB
/
MediaTypeHeaderValueComparer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.Net.Http.Headers
{
/// <summary>
/// Implementation of <see cref="IComparer{T}"/> that can compare accept media type header fields
/// based on their quality values (a.k.a q-values).
/// </summary>
public class MediaTypeHeaderValueComparer : IComparer<MediaTypeHeaderValue>
{
private static readonly MediaTypeHeaderValueComparer _mediaTypeComparer =
new MediaTypeHeaderValueComparer();
private MediaTypeHeaderValueComparer()
{
}
public static MediaTypeHeaderValueComparer QualityComparer
{
get { return _mediaTypeComparer; }
}
/// <inheritdoc />
/// <remarks>
/// Performs comparisons based on the arguments' quality values
/// (aka their "q-value"). Values with identical q-values are considered equal (i.e. the result is 0)
/// with the exception that suffixed subtype wildcards are considered less than subtype wildcards, subtype wildcards
/// are considered less than specific media types and full wildcards are considered less than
/// subtype wildcards. This allows callers to sort a sequence of <see cref="MediaTypeHeaderValue"/> following
/// their q-values in the order of specific media types, subtype wildcards, and last any full wildcards.
/// </remarks>
/// <example>
/// If we had a list of media types (comma separated): { text/*;q=0.8, text/*+json;q=0.8, */*;q=1, */*;q=0.8, text/plain;q=0.8 }
/// Sorting them using Compare would return: { */*;q=0.8, text/*;q=0.8, text/*+json;q=0.8, text/plain;q=0.8, */*;q=1 }
/// </example>
public int Compare(MediaTypeHeaderValue mediaType1, MediaTypeHeaderValue mediaType2)
{
if (object.ReferenceEquals(mediaType1, mediaType2))
{
return 0;
}
var returnValue = CompareBasedOnQualityFactor(mediaType1, mediaType2);
if (returnValue == 0)
{
if (!mediaType1.Type.Equals(mediaType2.Type, StringComparison.OrdinalIgnoreCase))
{
if (mediaType1.MatchesAllTypes)
{
return -1;
}
else if (mediaType2.MatchesAllTypes)
{
return 1;
}
else if (mediaType1.MatchesAllSubTypes && !mediaType2.MatchesAllSubTypes)
{
return -1;
}
else if (!mediaType1.MatchesAllSubTypes && mediaType2.MatchesAllSubTypes)
{
return 1;
}
else if (mediaType1.MatchesAllSubTypesWithoutSuffix && !mediaType2.MatchesAllSubTypesWithoutSuffix)
{
return -1;
}
else if (!mediaType1.MatchesAllSubTypesWithoutSuffix && mediaType2.MatchesAllSubTypesWithoutSuffix)
{
return 1;
}
}
else if (!mediaType1.SubType.Equals(mediaType2.SubType, StringComparison.OrdinalIgnoreCase))
{
if (mediaType1.MatchesAllSubTypes)
{
return -1;
}
else if (mediaType2.MatchesAllSubTypes)
{
return 1;
}
else if (mediaType1.MatchesAllSubTypesWithoutSuffix && !mediaType2.MatchesAllSubTypesWithoutSuffix)
{
return -1;
}
else if (!mediaType1.MatchesAllSubTypesWithoutSuffix && mediaType2.MatchesAllSubTypesWithoutSuffix)
{
return 1;
}
}
else if (!mediaType1.Suffix.Equals(mediaType2.Suffix, StringComparison.OrdinalIgnoreCase))
{
if (mediaType1.MatchesAllSubTypesWithoutSuffix)
{
return -1;
}
else if (mediaType2.MatchesAllSubTypesWithoutSuffix)
{
return 1;
}
}
}
return returnValue;
}
private static int CompareBasedOnQualityFactor(
MediaTypeHeaderValue mediaType1,
MediaTypeHeaderValue mediaType2)
{
var mediaType1Quality = mediaType1.Quality ?? HeaderQuality.Match;
var mediaType2Quality = mediaType2.Quality ?? HeaderQuality.Match;
var qualityDifference = mediaType1Quality - mediaType2Quality;
if (qualityDifference < 0)
{
return -1;
}
else if (qualityDifference > 0)
{
return 1;
}
return 0;
}
}
}