1 module.exports = preferredCharsets;
2 preferredCharsets.preferredCharsets = preferredCharsets;
4 function parseAcceptCharset(accept) {
5 var accepts = accept.split(',');
7 for (var i = 0, j = 0; i < accepts.length; i++) {
8 var charset = parseCharset(accepts[i].trim(), i);
11 accepts[j++] = charset;
21 function parseCharset(s, i) {
22 var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
23 if (!match) return null;
25 var charset = match[1];
28 var params = match[2].split(';')
29 for (var i = 0; i < params.length; i ++) {
30 var p = params[i].trim().split('=');
45 function getCharsetPriority(charset, accepted, index) {
46 var priority = {o: -1, q: 0, s: 0};
48 for (var i = 0; i < accepted.length; i++) {
49 var spec = specify(charset, accepted[i], index);
51 if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
59 function specify(charset, spec, index) {
61 if(spec.charset.toLowerCase() === charset.toLowerCase()){
63 } else if (spec.charset !== '*' ) {
75 function preferredCharsets(accept, provided) {
76 // RFC 2616 sec 14.2: no header = *
77 var accepts = parseAcceptCharset(accept === undefined ? '*' : accept || '');
80 // sorted list of all charsets
81 return accepts.filter(isQuality).sort(compareSpecs).map(function getCharset(spec) {
86 var priorities = provided.map(function getPriority(type, index) {
87 return getCharsetPriority(type, accepts, index);
90 // sorted list of accepted charsets
91 return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) {
92 return provided[priorities.indexOf(priority)];
96 function compareSpecs(a, b) {
97 return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
100 function isQuality(spec) {