'use strict'; const every = require('@arr/every'); const SEP = '/'; // Types ~> static, param, any, optional const STYPE=0, PTYPE=1, ATYPE=2, OTYPE=3; // Char Codes ~> / : * const SLASH=47, COLON=58, ASTER=42, QMARK=63; function strip(str) { if (str === SEP) return str; (str.charCodeAt(0) === SLASH) && (str=str.substring(1)); var len = str.length - 1; return str.charCodeAt(len) === SLASH ? str.substring(0, len) : str; } function split(str) { return (str=strip(str)) === SEP ? [SEP] : str.split(SEP); } function isMatch(arr, obj, idx) { idx = arr[idx]; return (obj.val === idx && obj.type === STYPE) || (idx === SEP ? obj.type > PTYPE : obj.type !== STYPE && (idx || '').endsWith(obj.end)); } function match(str, all) { var i=0, tmp, segs=split(str), len=segs.length, l; var fn = isMatch.bind(isMatch, segs); for (; i < all.length; i++) { tmp = all[i]; if ((l=tmp.length) === len || (l < len && tmp[l-1].type === ATYPE) || (l > len && tmp[l-1].type === OTYPE)) { if (every(tmp, fn)) return tmp; } } return []; } function parse(str) { if (str === SEP) { return [{ old:str, type:STYPE, val:str, end:'' }]; } var c, x, t, sfx, nxt=strip(str), i=-1, j=0, len=nxt.length, out=[]; while (++i < len) { c = nxt.charCodeAt(i); if (c === COLON) { j = i + 1; // begining of param t = PTYPE; // set type x = 0; // reset mark sfx = ''; while (i < len && nxt.charCodeAt(i) !== SLASH) { c = nxt.charCodeAt(i); if (c === QMARK) { x=i; t=OTYPE; } else if (c === 46 && sfx.length === 0) { sfx = nxt.substring(x=i); } i++; // move on } out.push({ old: str, type: t, val: nxt.substring(j, x||i), end: sfx }); // shorten string & update pointers nxt=nxt.substring(i); len-=i; i=0; continue; // loop } else if (c === ASTER) { out.push({ old: str, type: ATYPE, val: nxt.substring(i), end: '' }); continue; // loop } else { j = i; while (i < len && nxt.charCodeAt(i) !== SLASH) { ++i; // skip to next slash } out.push({ old: str, type: STYPE, val: nxt.substring(j, i), end: '' }); // shorten string & update pointers nxt=nxt.substring(i); len-=i; i=j=0; } } return out; } function exec(str, arr) { var i=0, x, y, segs=split(str), out={}; for (; i < arr.length; i++) { x=segs[i]; y=arr[i]; if (x === SEP) continue; if (x !== void 0 && y.type | 2 === OTYPE) { out[ y.val ] = x.replace(y.end, ''); } } return out; } exports.exec = exec; exports.match = match; exports.parse = parse;