116 lines
2.5 KiB
JavaScript
116 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
import every from '@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));
|
|
}
|
|
|
|
export 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 [];
|
|
}
|
|
|
|
export 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;
|
|
}
|
|
|
|
export 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;
|
|
}
|