var depth = 0;
var str = [];
query = query.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,function(t){
depth += t == '[' ? 1 : t == ']' ? -1 : 0; // keep track of bracket depth
return (t == ']' && depth > 0) ? '`]' : // we mark all the inner brackets as skippable
(t.charAt(0) == '"' || t.charAt(0) == "'") ? "`" + (str.push(t) - 1) :// and replace all the strings
t;
});
var prefix = '';
function call(name){
// creates a function call and puts the expression so far in a parameter for a call
prefix = name + "(" + prefix;
}
function makeRegex(t,a,b,c,d,e,f,g){
// creates a regular expression matcher for when wildcards and ignore case is used
return str[g].match(/[\*\?]/) || f == '~' ?
"/^" + str[g].substring(1,str[g].length-1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g,"\\$1$2").replace(/([\*\?])/g,"[\\w\\W]$1") + (f == '~' ? '$/i' : '$/') + ".test(" + a + ")" :
t;
}
query.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,function(){
throw new Error("Unsafe function call");
});
query = query.replace(/([^=]=)([^=])/g,"$1=$2"). // change the equals to comparisons
replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,function(t){
return t.charAt(0) == '.' ? t : // leave .prop alone
t == '@' ? "$obj" :// the reference to the current object
(t.match(/:|^(\$|Math|true|false|null)$/) ? "" : "$obj.") + t; // plain names should be properties of root... unless they are a label in object initializer
}).
replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,function(t,a,b){
var oper = t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/); // [?expr] and ?expr and [=expr and =expr
if(oper){
var prefix = '';
if(t.match(/^\./)){
// recursive object search
call("dojox.json._find");
prefix = ",true)";
}
call(oper[1].match(/\=/) ? "dojo.map" : oper[1].match(/\^/) ? "dojox.json._distinctFilter" : "dojo.filter");
return prefix + ",function($obj){return " + oper[2] + "})";
}
oper = t.match(/^\[\s*([\/\\].*)\]/); // [/sortexpr,\sortexpr]
if(oper){
// make a copy of the array and then sort it using the sorting expression
return ".concat().sort(function(a,b){" + oper[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,function(t,a,b){
return "var av= " + b.replace(/\$obj/,"a") + ",bv= " + b.replace(/\$obj/,"b") + // FIXME: Should check to make sure the $obj token isn't followed by characters
";if(av>bv||bv==null){return " + (a== "/" ? 1 : -1) +";}\n" +
"if(bv>av||av==null){return " + (a== "/" ? -1 : 1) +";}\n";
}) + "return 0;})";
}
oper = t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/); // slice [0:3]
if(oper){
call("dojox.json._slice");
return "," + (oper[1] || 0) + "," + (oper[2] || 0) + "," + (oper[3] || 1) + ")";
}
if(t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)){ // ..prop and [*]
call("dojox.json._find");
return (t.charAt(1) == '.' ?
",'" + b + "'" : // ..prop
t.match(/,/) ?
"," + t : // [prop1,prop2]
"") + ")"; // [*]
}
return t;
}).
replace(/(\$obj\s*((\.\s*[\w_$]+\s*)|(\[\s*`([0-9]+)\s*`\]))*)(==|~)\s*`([0-9]+)/g,makeRegex). // create regex matching
replace(/`([0-9]+)\s*(==|~)\s*(\$obj\s*((\.\s*[\w_$]+)|(\[\s*`([0-9]+)\s*`\]))*)/g,function(t,a,b,c,d,e,f,g){ // and do it for reverse =
return makeRegex(t,c,d,e,f,g,b,a);
});
query = prefix + (query.charAt(0) == '$' ? "" : "$") + query.replace(/`([0-9]+|\])/g,function(t,a){
//restore the strings
return a == ']' ? ']' : str[a];
});
// create a function within this scope (so it can use expand and slice)
var executor = eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return " + query + "}");
for(var i = 0;i
arguments[i] = arguments[i+1];
}
return obj ? executor.apply(this,arguments) : executor;