/* * Copyright (c) 2014 ThoughtWorks, Inc. * * Pixelated is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pixelated is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pixelated. If not, see . */ /* jshint curly: false */ define([], function () { 'use strict'; var exports = {}; // Licence: PUBLIC DOMAIN // Author: Austin Wright function MediaType(s, p){ this.type = ''; this.params = {}; var c, i, n; if(typeof s==='string'){ c = splitQuotedString(s); this.type = c.shift(); for(i=0; i=0){ offset = [delim,quote].reduce(findNextChar, 1/0); if(offset===1/0) break; switch(str[offset]){ case quote: // Skip to end of quoted string while(1){ offset=str.indexOf(quote, offset+1); if(offset<0) break; if(str[offset-1]==='\\') continue; break; } continue; case delim: res.push(str.substr(start, offset-start).trim()); start = ++offset; break; } } res.push(str.substr(start).trim()); return res; } exports.splitQuotedString = splitQuotedString; // Split a list of content types found in an Accept header // Maybe use it like: splitContentTypes(request.headers.accept).map(parseMedia) function splitContentTypes(str){ return splitQuotedString(str, ','); } exports.splitContentTypes = splitContentTypes; function parseMedia(str){ var o = new MediaType(str); if(o.q===undefined) o.q=1; return o; } exports.parseMedia = parseMedia; // Pick an ideal representation to send given a list of representations to choose from and the client-preferred list function select(reps, accept){ var cr = {q:0}; var ca = {q:0}; var cq = 0; for(var i=0; i=0){ if(aq*rq>cq){ ca = a; cr = r; cq = ca.q*cr.q; if(cq===1 && cr.type) return cr; } } } } return cr.type&&cr; } exports.select = select; // Determine if one media type is a subset of another // If a is a superset of b (b is smaller than a), return 1 // If b is a superset of a, return -1 // If they are the exact same, return 0 // If they are disjoint, return null function mediaCmp(a, b){ if(a.type==='*/*' && b.type!=='*/*') return 1; else if(a.type!=='*/*' && b.type==='*/*') return -1; var ac = (a.type||'').split('/'); var bc = (b.type||'').split('/'); if(ac[0]==='*' && bc[0]!=='*') return 1; if(ac[0]!=='*' && bc[0]==='*') return -1; if(a.type!==b.type) return null; var ap = a.params || {}; var bp = b.params || {}; var ak = Object.keys(ap); var bk = Object.keys(bp); if(ak.length < bk.length) return 1; if(ak.length > bk.length) return -1; var k = ak.concat(bk).sort(); var dir = 0; for(var n in ap){ if(ap[n] && !bp[n]){ if(dir<0) return null; else dir=1; } if(!ap[n] && bp[n]){ if(dir>0) return null; else dir=-1; } } return dir; } exports.mediaCmp = mediaCmp; return exports; });