Skip to content

Commit

Permalink
using arrays instead of strings for expr and path aggregators in trace()
Browse files Browse the repository at this point in the history
  • Loading branch information
rksm committed Oct 23, 2013
1 parent 4df3f6c commit b38e0c6
Showing 1 changed file with 25 additions and 19 deletions.
44 changes: 25 additions & 19 deletions lib/jsonpath.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ var vm = isNode ?
exports.eval = jsonPath;

var cache = {};

function push(arr, elem) { arr = arr.slice(); arr.push(elem); return arr; }
function unshift(elem, arr) { arr = arr.slice(); arr.unshift(elem); return arr; }

function jsonPath(obj, expr, arg) {
var P = {
resultType: arg && arg.resultType || "VALUE",
Expand All @@ -36,11 +40,13 @@ function jsonPath(obj, expr, arg) {
normalize: function(expr) {
if (cache[expr]) return cache[expr];
var subx = [];
return cache[expr] = expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";})
var normalized = expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";})
.replace(/'?\.'?|\['?/g, ";")
.replace(/(;)?(\^+)(;)?/g, function(_, front, ups, back) { return ';' + ups.split('').join(';') + ';'; })
.replace(/;;;|;;/g, ";..;")
.replace(/;$|'?\]|'$/g, "")
.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
return cache[expr] = normalized.split(';');
},
asPath: function(path) {
var x = path.split(";"), p = "$";
Expand All @@ -64,25 +70,24 @@ function jsonPath(obj, expr, arg) {
return true;
},
trace: function(expr, val, path) {
if (expr) {
var x = expr.split(";"), loc = x.shift();
x = x.join(";");
if (val && val.hasOwnProperty(loc))
P.trace(x, val[loc], path + ";" + loc);
if (expr && expr.length) {
var loc = expr[0], x = expr.slice(1);
if (val && val.hasOwnProperty(loc)) // simple case, directly follow property
P.trace(x, val[loc], push(path, loc));
else if (loc === "*")
P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+";"+x,v,p); });
P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(unshift(m, x), v, p); });
else if (loc === "..") {
P.trace(x, val, path);
P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === "object" && P.trace("..;"+x,v[m],p+";"+m); });
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (typeof v[m] === "object") P.trace(unshift("..", x), v[m], push(p, m)); });
}
else if (/,/.test(loc)) { // [name1,name2,...]
for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
P.trace(s[i]+";"+x, val, path);
else if (loc[0] === '(') // [(expr)]
P.trace(unshift(P.eval(loc, val, path[path.length]),x), val, path);
else if (loc.indexOf('?(') === 0) // [?(expr)]
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m)) P.trace(unshift(m,x),v,p); });
else if (loc.indexOf(',') > -1) { // [name1,name2,...]
for (var parts = loc.split(','), i = 0; i < parts.length; i++)
P.trace(unshift(parts[i], x), val, path);
}
else if (/^\(.*?\)$/.test(loc)) // [(expr)]
P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(";")+1))+";"+x, val, path);
else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m)) P.trace(m+";"+x,v,p); });
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] python slice syntax
P.slice(loc, x, val, path);
}
Expand All @@ -92,8 +97,7 @@ function jsonPath(obj, expr, arg) {
walk: function(loc, expr, val, path, f) {
if (val instanceof Array) {
for (var i=0,n=val.length; i<n; i++)
if (i in val)
f(i,loc,expr,val,path);
f(i,loc,expr,val,path);
}
else if (typeof val === "object") {
for (var m in val)
Expand All @@ -109,7 +113,7 @@ function jsonPath(obj, expr, arg) {
step = (parts[2] && parseInt(parts[2])) || 1;
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
for (var i=start; i<end; i+=step) P.trace(i+";"+expr, val, path);
for (var i=start; i<end; i+=step) P.trace(unshift(i,expr), val, path);
},
eval: function(x, _v, _vname) {
P.sandbox["_v"] = _v;
Expand All @@ -126,7 +130,9 @@ function jsonPath(obj, expr, arg) {

var $ = obj;
if (expr && obj && (P.resultType == "VALUE" || P.resultType == "PATH")) {
P.trace(P.normalize(expr).replace(/^\$;/,""), obj, "$");
var exprList = P.normalize(expr);
if (exprList[0] === "$" && exprList.length > 1) exprList.shift();
P.trace(exprList, obj, ["$"]);
if(!Array.isArray(P.result) && P.wrap) P.result = [P.result];
return P.result ? P.result : false;
}
Expand Down

0 comments on commit b38e0c6

Please sign in to comment.