3 * Copyright(c) 2012 Isaac Z. Schlueter
4 * Copyright(c) 2014 Federico Romero
5 * Copyright(c) 2014-2015 Douglas Christopher Wilson
16 module.exports = preferredCharsets;
17 module.exports.preferredCharsets = preferredCharsets;
24 var simpleCharsetRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
27 * Parse the Accept-Charset header.
31 function parseAcceptCharset(accept) {
32 var accepts = accept.split(',');
34 for (var i = 0, j = 0; i < accepts.length; i++) {
35 var charset = parseCharset(accepts[i].trim(), i);
38 accepts[j++] = charset;
49 * Parse a charset from the Accept-Charset header.
53 function parseCharset(str, i) {
54 var match = simpleCharsetRegExp.exec(str);
55 if (!match) return null;
57 var charset = match[1];
60 var params = match[2].split(';')
61 for (var j = 0; j < params.length; j++) {
62 var p = params[j].trim().split('=');
78 * Get the priority of a charset.
82 function getCharsetPriority(charset, accepted, index) {
83 var priority = {o: -1, q: 0, s: 0};
85 for (var i = 0; i < accepted.length; i++) {
86 var spec = specify(charset, accepted[i], index);
88 if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
97 * Get the specificity of the charset.
101 function specify(charset, spec, index) {
103 if(spec.charset.toLowerCase() === charset.toLowerCase()){
105 } else if (spec.charset !== '*' ) {
118 * Get the preferred charsets from an Accept-Charset header.
122 function preferredCharsets(accept, provided) {
123 // RFC 2616 sec 14.2: no header = *
124 var accepts = parseAcceptCharset(accept === undefined ? '*' : accept || '');
127 // sorted list of all charsets
131 .map(getFullCharset);
134 var priorities = provided.map(function getPriority(type, index) {
135 return getCharsetPriority(type, accepts, index);
138 // sorted list of accepted charsets
139 return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) {
140 return provided[priorities.indexOf(priority)];
149 function compareSpecs(a, b) {
150 return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
154 * Get full charset string.
158 function getFullCharset(spec) {
163 * Check if a spec has any quality.
167 function isQuality(spec) {