From 76c9a6eadb4522e7378dfb42c5a4e50665846993 Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Fri, 24 Mar 2023 17:10:30 +0100 Subject: [PATCH] added object test() vs testProperty() functions --- dist/xrfragment.js | 115 ++++--------- dist/xrfragment.lua | 280 ++++++++++++++++++-------------- dist/xrfragment.py | 140 +++++++++++----- src/Test.hx | 14 +- src/spec/query.class.json | 24 +-- src/spec/query.conditional.json | 6 - src/spec/query.rules.json | 14 ++ src/xrfragment/Query.hx | 85 +++++++--- test/generated/test.js | 142 +++++++++++----- test/generated/test.py | 152 +++++++++++------ 10 files changed, 580 insertions(+), 392 deletions(-) delete mode 100644 src/spec/query.conditional.json create mode 100644 src/spec/query.rules.json diff --git a/dist/xrfragment.js b/dist/xrfragment.js index 0e4ae3f..5736e1d 100644 --- a/dist/xrfragment.js +++ b/dist/xrfragment.js @@ -42,26 +42,6 @@ HxOverrides.substr = function(s,pos,len) { HxOverrides.now = function() { return Date.now(); }; -var Reflect = function() { }; -Reflect.field = function(o,field) { - try { - return o[field]; - } catch( _g ) { - return null; - } -}; -Reflect.fields = function(o) { - var a = []; - if(o != null) { - var hasOwnProperty = Object.prototype.hasOwnProperty; - for( var f in o ) { - if(f != "__id__" && f != "hx__closures__" && hasOwnProperty.call(o,f)) { - a.push(f); - } - } - } - return a; -}; var Std = function() { }; Std.parseInt = function(x) { if(x != null) { @@ -131,6 +111,8 @@ haxe_iterators_ArrayIterator.prototype = { } }; var xrfragment_Query = function(str) { + this.isNumber = new EReg("^[0-9\\.]+$",""); + this.isClass = new EReg("^[-]?class$",""); this.isExclude = new EReg("^-",""); this.isProp = new EReg("^.*:[><=!]?",""); this.q = { }; @@ -159,7 +141,13 @@ xrfragment_Query.prototype = { prefix = ""; } str = StringTools.trim(str); - var value = { }; + var k = str.split(":")[0]; + var v = str.split(":")[1]; + var filter = { }; + if(q[prefix + k]) { + filter = q[prefix + k]; + } + filter["rules"] = filter["rules"] != null ? filter["rules"] : []; if(_gthis.isProp.match(str)) { var oper = ""; if(str.indexOf("*") != -1) { @@ -171,32 +159,39 @@ xrfragment_Query.prototype = { if(str.indexOf("<") != -1) { oper = "<"; } - if(str.indexOf("!=") != -1) { - oper = "!="; - } if(str.indexOf(">=") != -1) { oper = ">="; } if(str.indexOf("<=") != -1) { oper = "<="; } - var k = str.split(":")[0]; - var v = str.split(":")[1]; - if(q[prefix + k]) { - value = q[prefix + k]; - } - if(oper.length > 0) { - value[oper] = parseFloat(HxOverrides.substr(v,oper.length,null)); - q[k] = value; + if(_gthis.isExclude.match(k)) { + oper = "!="; + k = HxOverrides.substr(k,1,null); } else { - value[prefix + (_gthis.isExclude.match(k) ? HxOverrides.substr(k,1,null) : k)] = _gthis.isExclude.match(k) == false; - q[v] = value; + v = HxOverrides.substr(v,oper.length,null); + } + if(oper.length == 0) { + oper = "="; + } + if(_gthis.isClass.match(k)) { + filter[prefix + k] = oper != "!="; + q[v] = filter; + } else { + var rule = { }; + if(_gthis.isNumber.match(v)) { + rule[oper] = parseFloat(v); + } else { + rule[oper] = v; + } + filter["rules"].push(rule); + q[k] = filter; } return; } else { - value["id"] = _gthis.isExclude.match(str) ? false : true; + filter["id"] = _gthis.isExclude.match(str) ? false : true; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; - q[key] = value; + q[key] = filter; } }; var _g = 0; @@ -208,54 +203,6 @@ xrfragment_Query.prototype = { this.q = q; return this.q; } - ,test: function(property,value) { - var conds = 0; - var fails = 0; - var qualify = 0; - var testprop = function(expr) { - conds += 1; - fails += expr ? 0 : 1; - return expr; - }; - if(this.q[value] != null) { - var v = this.q[value]; - if(v[property] != null) { - return v[property]; - } - } - var _g = 0; - var _g1 = Reflect.fields(this.q); - while(_g < _g1.length) { - var k = _g1[_g]; - ++_g; - var qval = Reflect.field(this.q,k); - if(typeof(value) == "string") { - continue; - } - if(Reflect.field(qval,"=") != null && testprop(value == Reflect.field(qval,"="))) { - ++qualify; - } - if(Reflect.field(qval,"*") != null && testprop(value != null)) { - ++qualify; - } - if(Reflect.field(qval,">") != null && testprop(value > parseFloat(Reflect.field(qval,">")))) { - ++qualify; - } - if(Reflect.field(qval,"<") != null && testprop(value < parseFloat(Reflect.field(qval,"<")))) { - ++qualify; - } - if(Reflect.field(qval,">=") != null && testprop(value >= parseFloat(Reflect.field(qval,">=")))) { - ++qualify; - } - if(Reflect.field(qval,"<=") != null && testprop(value >= parseFloat(Reflect.field(qval,"<=")))) { - ++qualify; - } - if(Reflect.field(qval,"!=") != null && testprop(value != parseFloat(Reflect.field(qval,"!=")))) { - ++qualify; - } - } - return qualify > 0; - } }; var xrfragment_Value = $hx_exports["xrfragment"]["Value"] = function() { }; diff --git a/dist/xrfragment.lua b/dist/xrfragment.lua index 861dd3e..f4a3411 100644 --- a/dist/xrfragment.lua +++ b/dist/xrfragment.lua @@ -1234,6 +1234,8 @@ __xrfragment_Query.new = function(str) return self end __xrfragment_Query.super = function(self,str) + self.isNumber = EReg.new("^[0-9\\.]+$", ""); + self.isClass = EReg.new("^[-]?class$", ""); self.isExclude = EReg.new("^-", ""); self.isProp = EReg.new("^.*:[><=!]?", ""); self.q = _hx_e(); @@ -1290,7 +1292,64 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) prefix = ""; end; str = StringTools.trim(str); - local value = _hx_e(); + local idx = 1; + local ret = _hx_tab_array({}, 0); + while (idx ~= nil) do + local newidx = 0; + if (__lua_lib_luautf8_Utf8.len(":") > 0) then + newidx = __lua_lib_luautf8_Utf8.find(str, ":", idx, true); + else + if (idx >= __lua_lib_luautf8_Utf8.len(str)) then + newidx = nil; + else + newidx = idx + 1; + end; + end; + if (newidx ~= nil) then + local match = __lua_lib_luautf8_Utf8.sub(str, idx, newidx - 1); + ret:push(match); + idx = newidx + __lua_lib_luautf8_Utf8.len(":"); + else + ret:push(__lua_lib_luautf8_Utf8.sub(str, idx, __lua_lib_luautf8_Utf8.len(str))); + idx = nil; + end; + end; + local k = ret[0]; + local idx = 1; + local ret = _hx_tab_array({}, 0); + while (idx ~= nil) do + local newidx = 0; + if (__lua_lib_luautf8_Utf8.len(":") > 0) then + newidx = __lua_lib_luautf8_Utf8.find(str, ":", idx, true); + else + if (idx >= __lua_lib_luautf8_Utf8.len(str)) then + newidx = nil; + else + newidx = idx + 1; + end; + end; + if (newidx ~= nil) then + local match = __lua_lib_luautf8_Utf8.sub(str, idx, newidx - 1); + ret:push(match); + idx = newidx + __lua_lib_luautf8_Utf8.len(":"); + else + ret:push(__lua_lib_luautf8_Utf8.sub(str, idx, __lua_lib_luautf8_Utf8.len(str))); + idx = nil; + end; + end; + local v = ret[1]; + local filter = _hx_e(); + if (Reflect.field(q, Std.string(prefix) .. Std.string(k))) then + filter = Reflect.field(q, Std.string(prefix) .. Std.string(k)); + end; + local value = (function() + local _hx_1 + if (Reflect.field(filter, "rules") ~= nil) then + _hx_1 = Reflect.field(filter, "rules"); else + _hx_1 = Array.new(); end + return _hx_1 + end )(); + filter.rules = value; if (_gthis.isProp:match(str)) then local oper = ""; local startIndex = nil; @@ -1301,11 +1360,11 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) end; local r = __lua_lib_luautf8_Utf8.find(str, "*", startIndex, true); if ((function() - local _hx_1 + local _hx_2 if ((r ~= nil) and (r > 0)) then - _hx_1 = r - 1; else - _hx_1 = -1; end - return _hx_1 + _hx_2 = r - 1; else + _hx_2 = -1; end + return _hx_2 end )() ~= -1) then oper = "*"; end; @@ -1317,11 +1376,11 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) end; local r = __lua_lib_luautf8_Utf8.find(str, ">", startIndex, true); if ((function() - local _hx_2 + local _hx_3 if ((r ~= nil) and (r > 0)) then - _hx_2 = r - 1; else - _hx_2 = -1; end - return _hx_2 + _hx_3 = r - 1; else + _hx_3 = -1; end + return _hx_3 end )() ~= -1) then oper = ">"; end; @@ -1332,22 +1391,6 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) startIndex = startIndex + 1; end; local r = __lua_lib_luautf8_Utf8.find(str, "<", startIndex, true); - if ((function() - local _hx_3 - if ((r ~= nil) and (r > 0)) then - _hx_3 = r - 1; else - _hx_3 = -1; end - return _hx_3 - end )() ~= -1) then - oper = "<"; - end; - local startIndex = nil; - if (startIndex == nil) then - startIndex = 1; - else - startIndex = startIndex + 1; - end; - local r = __lua_lib_luautf8_Utf8.find(str, "!=", startIndex, true); if ((function() local _hx_4 if ((r ~= nil) and (r > 0)) then @@ -1355,7 +1398,7 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) _hx_4 = -1; end return _hx_4 end )() ~= -1) then - oper = "!="; + oper = "<"; end; local startIndex = nil; if (startIndex == nil) then @@ -1389,56 +1432,25 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) end )() ~= -1) then oper = "<="; end; - local idx = 1; - local ret = _hx_tab_array({}, 0); - while (idx ~= nil) do - local newidx = 0; - if (__lua_lib_luautf8_Utf8.len(":") > 0) then - newidx = __lua_lib_luautf8_Utf8.find(str, ":", idx, true); + if (_gthis.isExclude:match(k)) then + oper = "!="; + local pos = 1; + local len = nil; + if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(k)))) then + len = __lua_lib_luautf8_Utf8.len(k); else - if (idx >= __lua_lib_luautf8_Utf8.len(str)) then - newidx = nil; - else - newidx = idx + 1; + if (len < 0) then + len = __lua_lib_luautf8_Utf8.len(k) + len; end; end; - if (newidx ~= nil) then - local match = __lua_lib_luautf8_Utf8.sub(str, idx, newidx - 1); - ret:push(match); - idx = newidx + __lua_lib_luautf8_Utf8.len(":"); - else - ret:push(__lua_lib_luautf8_Utf8.sub(str, idx, __lua_lib_luautf8_Utf8.len(str))); - idx = nil; + if (pos < 0) then + pos = __lua_lib_luautf8_Utf8.len(k) + pos; end; - end; - local k = ret[0]; - local idx = 1; - local ret = _hx_tab_array({}, 0); - while (idx ~= nil) do - local newidx = 0; - if (__lua_lib_luautf8_Utf8.len(":") > 0) then - newidx = __lua_lib_luautf8_Utf8.find(str, ":", idx, true); - else - if (idx >= __lua_lib_luautf8_Utf8.len(str)) then - newidx = nil; - else - newidx = idx + 1; - end; + if (pos < 0) then + pos = 0; end; - if (newidx ~= nil) then - local match = __lua_lib_luautf8_Utf8.sub(str, idx, newidx - 1); - ret:push(match); - idx = newidx + __lua_lib_luautf8_Utf8.len(":"); - else - ret:push(__lua_lib_luautf8_Utf8.sub(str, idx, __lua_lib_luautf8_Utf8.len(str))); - idx = nil; - end; - end; - local v = ret[1]; - if (Reflect.field(q, Std.string(prefix) .. Std.string(k))) then - value = Reflect.field(q, Std.string(prefix) .. Std.string(k)); - end; - if (__lua_lib_luautf8_Utf8.len(oper) > 0) then + k = __lua_lib_luautf8_Utf8.sub(k, pos + 1, pos + len); + else local pos = __lua_lib_luautf8_Utf8.len(oper); local len = nil; if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(v)))) then @@ -1454,45 +1466,36 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) if (pos < 0) then pos = 0; end; - local value1 = Std.parseFloat(__lua_lib_luautf8_Utf8.sub(v, pos + 1, pos + len)); - value[oper] = value1; - q[k] = value; + v = __lua_lib_luautf8_Utf8.sub(v, pos + 1, pos + len); + end; + if (__lua_lib_luautf8_Utf8.len(oper) == 0) then + oper = "="; + end; + if (_gthis.isClass:match(k)) then + local value = oper ~= "!="; + filter[Std.string(prefix) .. Std.string(k)] = value; + q[v] = filter; else - local key; - if (_gthis.isExclude:match(k)) then - local pos = 1; - local len = nil; - if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(k)))) then - len = __lua_lib_luautf8_Utf8.len(k); - else - if (len < 0) then - len = __lua_lib_luautf8_Utf8.len(k) + len; - end; - end; - if (pos < 0) then - pos = __lua_lib_luautf8_Utf8.len(k) + pos; - end; - if (pos < 0) then - pos = 0; - end; - key = __lua_lib_luautf8_Utf8.sub(k, pos + 1, pos + len); + local rule = _hx_e(); + if (_gthis.isNumber:match(v)) then + local value = Std.parseFloat(v); + rule[oper] = value; else - key = k; + rule[oper] = v; end; - local value1 = _gthis.isExclude:match(k) == false; - value[Std.string(prefix) .. Std.string(key)] = value1; - q[v] = value; + Reflect.field(filter, "rules"):push(rule); + q[k] = filter; end; do return end; else - local value1 = (function() + local value = (function() local _hx_7 if (_gthis.isExclude:match(str)) then _hx_7 = false; else _hx_7 = true; end return _hx_7 end )(); - value.id = value1; + filter.id = value; local key; if (_gthis.isExclude:match(str)) then local pos = 1; @@ -1514,7 +1517,7 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) else key = str; end; - q[key] = value; + q[key] = filter; end; end; local _g = 0; @@ -1527,7 +1530,31 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse) self.q = q; do return self.q end end -__xrfragment_Query.prototype.test = function(self,property,value) +__xrfragment_Query.prototype.test = function(self,obj) + local qualify = false; + local _g = 0; + local _g1 = Reflect.fields(obj); + while (_g < _g1.length) do + local k = _g1[_g]; + _g = _g + 1; + local v = Std.string(Reflect.field(obj, k)); + if (self:testProperty(k, v)) then + qualify = true; + end; + end; + local _g = 0; + local _g1 = Reflect.fields(obj); + while (_g < _g1.length) do + local k = _g1[_g]; + _g = _g + 1; + local v = Std.string(Reflect.field(obj, k)); + if (self:testProperty(k, v, true)) then + qualify = false; + end; + end; + do return qualify end +end +__xrfragment_Query.prototype.testProperty = function(self,property,value,exclude) local conds = 0; local fails = 0; local qualify = 0; @@ -1554,30 +1581,39 @@ __xrfragment_Query.prototype.test = function(self,property,value) while (_g < _g1.length) do repeat local k = _g1[_g]; _g = _g + 1; - local qval = Reflect.field(self.q, k); - if (__lua_Boot.__instanceof(value, String)) then + local filter = Reflect.field(self.q, k); + if (filter.rules == nil) then break; end; - if ((Reflect.field(qval, "=") ~= nil) and testprop(value == Reflect.field(qval, "="))) then - qualify = qualify + 1; - end; - if ((Reflect.field(qval, "*") ~= nil) and testprop(value ~= nil)) then - qualify = qualify + 1; - end; - if ((Reflect.field(qval, ">") ~= nil) and testprop(value > Std.parseFloat(Reflect.field(qval, ">")))) then - qualify = qualify + 1; - end; - if ((Reflect.field(qval, "<") ~= nil) and testprop(value < Std.parseFloat(Reflect.field(qval, "<")))) then - qualify = qualify + 1; - end; - if ((Reflect.field(qval, ">=") ~= nil) and testprop(value >= Std.parseFloat(Reflect.field(qval, ">=")))) then - qualify = qualify + 1; - end; - if ((Reflect.field(qval, "<=") ~= nil) and testprop(value >= Std.parseFloat(Reflect.field(qval, "<=")))) then - qualify = qualify + 1; - end; - if ((Reflect.field(qval, "!=") ~= nil) and testprop(value ~= Std.parseFloat(Reflect.field(qval, "!=")))) then - qualify = qualify + 1; + local rules = filter.rules; + local _g = 0; + while (_g < rules.length) do + local rule = rules[_g]; + _g = _g + 1; + if (exclude) then + if (((Reflect.field(rule, "!=") ~= nil) and testprop(Std.string(value) == Std.string(Reflect.field(rule, "!=")))) and exclude) then + qualify = qualify + 1; + end; + else + if ((Reflect.field(rule, "*") ~= nil) and testprop(Std.parseFloat(value) ~= nil)) then + qualify = qualify + 1; + end; + if ((Reflect.field(rule, ">") ~= nil) and testprop(Std.parseFloat(value) > Std.parseFloat(Reflect.field(rule, ">")))) then + qualify = qualify + 1; + end; + if ((Reflect.field(rule, "<") ~= nil) and testprop(Std.parseFloat(value) < Std.parseFloat(Reflect.field(rule, "<")))) then + qualify = qualify + 1; + end; + if ((Reflect.field(rule, ">=") ~= nil) and testprop(Std.parseFloat(value) >= Std.parseFloat(Reflect.field(rule, ">=")))) then + qualify = qualify + 1; + end; + if ((Reflect.field(rule, "<=") ~= nil) and testprop(Std.parseFloat(value) <= Std.parseFloat(Reflect.field(rule, "<=")))) then + qualify = qualify + 1; + end; + if ((Reflect.field(rule, "=") ~= nil) and (testprop(value == Reflect.field(rule, "=")) or testprop(Std.parseFloat(value) == Std.parseFloat(Reflect.field(rule, "="))))) then + qualify = qualify + 1; + end; + end; end;until true if _hx_continue_1 then _hx_continue_1 = false; diff --git a/dist/xrfragment.py b/dist/xrfragment.py index 4bcb9d9..9a793f6 100644 --- a/dist/xrfragment.py +++ b/dist/xrfragment.py @@ -1004,7 +1004,7 @@ class python_internal_ArrayImpl: class HxOverrides: _hx_class_name = "HxOverrides" __slots__ = () - _hx_statics = ["eq", "stringOrNull", "arrayGet"] + _hx_statics = ["eq", "stringOrNull", "push", "arrayGet"] @staticmethod def eq(a,b): @@ -1019,6 +1019,14 @@ class HxOverrides: else: return s + @staticmethod + def push(x,e): + if isinstance(x,list): + _this = x + _this.append(e) + return len(_this) + return x.push(e) + @staticmethod def arrayGet(a,i): if isinstance(a,list): @@ -1158,11 +1166,13 @@ class HxString: class xrfragment_Query: _hx_class_name = "xrfragment.Query" - __slots__ = ("str", "q", "isProp", "isExclude") - _hx_fields = ["str", "q", "isProp", "isExclude"] - _hx_methods = ["toObject", "expandAliases", "parse", "test"] + __slots__ = ("str", "q", "isProp", "isExclude", "isClass", "isNumber") + _hx_fields = ["str", "q", "isProp", "isExclude", "isClass", "isNumber"] + _hx_methods = ["toObject", "expandAliases", "parse", "test", "testProperty"] def __init__(self,_hx_str): + self.isNumber = EReg("^[0-9\\.]+$","") + self.isClass = EReg("^[-]?class$","") self.isExclude = EReg("^-","") self.isProp = EReg("^.*:[><=!]?","") self.q = _hx_AnonObject({}) @@ -1191,7 +1201,13 @@ class xrfragment_Query: if (prefix is None): prefix = "" _hx_str = StringTools.trim(_hx_str) - value = _hx_AnonObject({}) + k = HxOverrides.arrayGet(_hx_str.split(":"), 0) + v = HxOverrides.arrayGet(_hx_str.split(":"), 1) + _hx_filter = _hx_AnonObject({}) + if Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))): + _hx_filter = Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))) + value = (Reflect.field(_hx_filter,"rules") if ((Reflect.field(_hx_filter,"rules") is not None)) else list()) + setattr(_hx_filter,(("_hx_" + "rules") if (("rules" in python_Boot.keywords)) else (("_hx_" + "rules") if (((((len("rules") > 2) and ((ord("rules"[0]) == 95))) and ((ord("rules"[1]) == 95))) and ((ord("rules"[(len("rules") - 1)]) != 95)))) else "rules")),value) _this = _gthis.isProp _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) if (_this.matchObj is not None): @@ -1206,41 +1222,48 @@ class xrfragment_Query: if (((_hx_str.find("<") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"<",startIndex))) != -1): oper = "<" startIndex = None - if (((_hx_str.find("!=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"!=",startIndex))) != -1): - oper = "!=" - startIndex = None if (((_hx_str.find(">=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,">=",startIndex))) != -1): oper = ">=" startIndex = None if (((_hx_str.find("<=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"<=",startIndex))) != -1): oper = "<=" - k = HxOverrides.arrayGet(_hx_str.split(":"), 0) - v = HxOverrides.arrayGet(_hx_str.split(":"), 1) - if Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))): - value = Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))) - if (len(oper) > 0): - value1 = Std.parseFloat(HxString.substr(v,len(oper),None)) - setattr(value,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),value1) - setattr(q,(("_hx_" + k) if ((k in python_Boot.keywords)) else (("_hx_" + k) if (((((len(k) > 2) and ((ord(k[0]) == 95))) and ((ord(k[1]) == 95))) and ((ord(k[(len(k) - 1)]) != 95)))) else k)),value) + _this = _gthis.isExclude + _this.matchObj = python_lib_Re.search(_this.pattern,k) + if (_this.matchObj is not None): + oper = "!=" + k = HxString.substr(k,1,None) else: - _this = _gthis.isExclude - _this.matchObj = python_lib_Re.search(_this.pattern,k) - key = (("null" if prefix is None else prefix) + HxOverrides.stringOrNull(((HxString.substr(k,1,None) if ((_this.matchObj is not None)) else k)))) - _this = _gthis.isExclude - _this.matchObj = python_lib_Re.search(_this.pattern,k) - value1 = ((_this.matchObj is not None) == False) - setattr(value,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value1) - setattr(q,(("_hx_" + v) if ((v in python_Boot.keywords)) else (("_hx_" + v) if (((((len(v) > 2) and ((ord(v[0]) == 95))) and ((ord(v[1]) == 95))) and ((ord(v[(len(v) - 1)]) != 95)))) else v)),value) + v = HxString.substr(v,len(oper),None) + if (len(oper) == 0): + oper = "=" + _this = _gthis.isClass + _this.matchObj = python_lib_Re.search(_this.pattern,k) + if (_this.matchObj is not None): + key = (("null" if prefix is None else prefix) + ("null" if k is None else k)) + value = (oper != "!=") + setattr(_hx_filter,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value) + setattr(q,(("_hx_" + v) if ((v in python_Boot.keywords)) else (("_hx_" + v) if (((((len(v) > 2) and ((ord(v[0]) == 95))) and ((ord(v[1]) == 95))) and ((ord(v[(len(v) - 1)]) != 95)))) else v)),_hx_filter) + else: + rule = _hx_AnonObject({}) + _this = _gthis.isNumber + _this.matchObj = python_lib_Re.search(_this.pattern,v) + if (_this.matchObj is not None): + value = Std.parseFloat(v) + setattr(rule,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),value) + else: + setattr(rule,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),v) + Reflect.field(Reflect.field(_hx_filter,"rules"),"push")(rule) + setattr(q,(("_hx_" + k) if ((k in python_Boot.keywords)) else (("_hx_" + k) if (((((len(k) > 2) and ((ord(k[0]) == 95))) and ((ord(k[1]) == 95))) and ((ord(k[(len(k) - 1)]) != 95)))) else k)),_hx_filter) return else: _this = _gthis.isExclude _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) - value1 = (False if ((_this.matchObj is not None)) else True) - setattr(value,(("_hx_" + "id") if (("id" in python_Boot.keywords)) else (("_hx_" + "id") if (((((len("id") > 2) and ((ord("id"[0]) == 95))) and ((ord("id"[1]) == 95))) and ((ord("id"[(len("id") - 1)]) != 95)))) else "id")),value1) + value = (False if ((_this.matchObj is not None)) else True) + setattr(_hx_filter,(("_hx_" + "id") if (("id" in python_Boot.keywords)) else (("_hx_" + "id") if (((((len("id") > 2) and ((ord("id"[0]) == 95))) and ((ord("id"[1]) == 95))) and ((ord("id"[(len("id") - 1)]) != 95)))) else "id")),value) _this = _gthis.isExclude _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) key = (HxString.substr(_hx_str,1,None) if ((_this.matchObj is not None)) else _hx_str) - setattr(q,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value) + setattr(q,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),_hx_filter) process = _hx_local_0 _g = 0 _g1 = len(token) @@ -1251,13 +1274,33 @@ class xrfragment_Query: self.q = q return self.q - def test(self,property,value = None): + def test(self,obj = None): + qualify = False + _g = 0 + _g1 = python_Boot.fields(obj) + while (_g < len(_g1)): + k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) + _g = (_g + 1) + v = Std.string(Reflect.field(obj,k)) + if self.testProperty(k,v): + qualify = True + _g = 0 + _g1 = python_Boot.fields(obj) + while (_g < len(_g1)): + k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) + _g = (_g + 1) + v = Std.string(Reflect.field(obj,k)) + if self.testProperty(k,v,True): + qualify = False + return qualify + + def testProperty(self,property,value,exclude = None): conds = 0 fails = 0 qualify = 0 def _hx_local_2(expr): - nonlocal conds nonlocal fails + nonlocal conds conds = (conds + 1) fails = (fails + (0 if expr else 1)) return expr @@ -1271,23 +1314,30 @@ class xrfragment_Query: while (_g < len(_g1)): k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) _g = (_g + 1) - qval = Reflect.field(self.q,k) - if Std.isOfType(value,str): + _hx_filter = Reflect.field(self.q,k) + if (Reflect.field(_hx_filter,"rules") is None): continue - if ((Reflect.field(qval,"=") is not None) and testprop(HxOverrides.eq(value,Reflect.field(qval,"=")))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"*") is not None) and testprop((value is not None))): - qualify = (qualify + 1) - if ((Reflect.field(qval,">") is not None) and testprop((value > Std.parseFloat(Reflect.field(qval,">"))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"<") is not None) and testprop((value < Std.parseFloat(Reflect.field(qval,"<"))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,">=") is not None) and testprop((value >= Std.parseFloat(Reflect.field(qval,">="))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"<=") is not None) and testprop((value >= Std.parseFloat(Reflect.field(qval,"<="))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"!=") is not None) and testprop((value != Std.parseFloat(Reflect.field(qval,"!="))))): - qualify = (qualify + 1) + rules = Reflect.field(_hx_filter,"rules") + _g2 = 0 + while (_g2 < len(rules)): + rule = (rules[_g2] if _g2 >= 0 and _g2 < len(rules) else None) + _g2 = (_g2 + 1) + if exclude: + if (((Reflect.field(rule,"!=") is not None) and testprop((Std.string(value) == Std.string(Reflect.field(rule,"!="))))) and exclude): + qualify = (qualify + 1) + else: + if ((Reflect.field(rule,"*") is not None) and testprop((Std.parseFloat(value) is not None))): + qualify = (qualify + 1) + if ((Reflect.field(rule,">") is not None) and testprop((Std.parseFloat(value) > Std.parseFloat(Reflect.field(rule,">"))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,"<") is not None) and testprop((Std.parseFloat(value) < Std.parseFloat(Reflect.field(rule,"<"))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,">=") is not None) and testprop((Std.parseFloat(value) >= Std.parseFloat(Reflect.field(rule,">="))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,"<=") is not None) and testprop((Std.parseFloat(value) <= Std.parseFloat(Reflect.field(rule,"<="))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,"=") is not None) and ((testprop((value == Reflect.field(rule,"="))) or testprop((Std.parseFloat(value) == Std.parseFloat(Reflect.field(rule,"="))))))): + qualify = (qualify + 1) return (qualify > 0) diff --git a/src/Test.hx b/src/Test.hx index f1fe933..5548475 100644 --- a/src/Test.hx +++ b/src/Test.hx @@ -14,7 +14,7 @@ class Test { static public function main():Void { test( Spec.load("src/spec/url.json") ); test( Spec.load("src/spec/query.class.json") ); - test( Spec.load("src/spec/query.conditional.json") ); + test( Spec.load("src/spec/query.rules.json") ); //test( Spec.load("src/spec/tmp.json") ); } @@ -28,12 +28,14 @@ class Test { var item:Dynamic = spec[i]; if( item.fn == "query" ) q = new Query(item.data); if( item.fn == "url" ) res = Url.parse(item.data); - if( item.expect.fn == "test" ) valid = item.expect.out == q.test( item.expect.input[0], item.expect.input[1] ); - if( item.expect.fn == "equal.string" ) valid = item.expect.out == res.get(item.expect.input).string; - if( item.expect.fn == "equal.xy" ) valid = item.expect.out == (Std.string(res.get(item.expect.input).x) + Std.string(res.get(item.expect.input).y) ); - if( item.expect.fn == "equal.multi" ) valid = equalMulti(res, item); + if( item.expect.fn == "test" ) valid = item.expect.out == q.test( item.expect.input[0] ); + if( item.expect.fn == "testProperty" ) valid = item.expect.out == q.testProperty( item.expect.input[0], item.expect.input[1] ); + if( item.expect.fn == "testPropertyExclude" ) valid = item.expect.out == q.testProperty( item.expect.input[0], item.expect.input[1], true ); + if( item.expect.fn == "equal.string" ) valid = item.expect.out == res.get(item.expect.input).string; + if( item.expect.fn == "equal.xy" ) valid = item.expect.out == (Std.string(res.get(item.expect.input).x) + Std.string(res.get(item.expect.input).y) ); + if( item.expect.fn == "equal.multi" ) valid = equalMulti(res, item); var ok:String = valid ? "[ ✔ ] " : "[ ❌] "; - trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " <= " + (item.label?item.label:item.expect.fn) : "")); + trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " (" + (item.label?item.label:item.expect.fn) +")" : "")); if( !valid ) errors += 1; } if( errors > 1 ) trace("\n-----\n[ ❌] "+errors+" errors :/"); diff --git a/src/spec/query.class.json b/src/spec/query.class.json index bddc929..5cf9b38 100644 --- a/src/spec/query.class.json +++ b/src/spec/query.class.json @@ -1,14 +1,14 @@ [ - {"fn":"query","data":"class:bar", "expect":{ "fn":"test","input":["class","bar"],"out":true}}, - {"fn":"query","data":".bar", "expect":{ "fn":"test","input":["class","bar"],"out":true}, "label":".bar shorthand"}, - {"fn":"query","data":".bar -.foo", "expect":{ "fn":"test","input":["class","foo"],"out":false}}, - {"fn":"query","data":".bar -.foo .foo", "expect":{ "fn":"test","input":["class","foo"],"out":true}}, - {"fn":"query","data":".bar -.bar .bar", "expect":{ "fn":"test","input":["class","bar"],"out":true}}, - {"fn":"query","data":"foo -foo foo", "expect":{ "fn":"test","input":["id","foo"],"out":true},"label":"id:foo?"}, - {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"test","input":["class","foo"],"out":true},"label":"class:foo"}, - {"fn":"query","data":".foo -.foo bar:5 .foo", "expect":{ "fn":"test","input":["class","foo"],"out":true},"label":"class:foo"}, - {"fn":"query","data":".foo -.foo bar:>5 .foo", "expect":{ "fn":"test","input":["class","foo"],"out":true},"label":"class:foo"}, - {"fn":"query","data":".foo -.foo bar:>5 .foo", "expect":{ "fn":"test","input":["class","foo"],"out":true},"label":"class:foo"}, - {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"test","input":["class","foo"],"out":true},"label":"class:foo"}, - {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"test","input":["id","foo"],"out":false},"label":"!id:foo"} + {"fn":"query","data":"class:bar", "expect":{ "fn":"testProperty","input":["class","bar"],"out":true}}, + {"fn":"query","data":".bar", "expect":{ "fn":"testProperty","input":["class","bar"],"out":true}, "label":".bar shorthand"}, + {"fn":"query","data":".bar -.foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":false}}, + {"fn":"query","data":".bar -.foo .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true}}, + {"fn":"query","data":".bar -.bar .bar", "expect":{ "fn":"testProperty","input":["class","bar"],"out":true}}, + {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, + {"fn":"query","data":".foo -.foo bar:5 .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, + {"fn":"query","data":".foo -.foo bar:>5 .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, + {"fn":"query","data":".foo -.foo bar:>5 .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, + {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, + {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":false},"label":"!id:foo"}, + {"fn":"query","data":"foo -foo foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":true},"label":"id:foo?"} ] diff --git a/src/spec/query.conditional.json b/src/spec/query.conditional.json deleted file mode 100644 index 4b340fc..0000000 --- a/src/spec/query.conditional.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"fn":"query","data":"price:>=5", "expect":{ "fn":"test","input":["price","10"],"out":true}}, - {"fn":"query","data":"price:>=15", "expect":{ "fn":"test","input":["price","10"],"out":false}}, - {"fn":"query","data":"price:>=5", "expect":{ "fn":"test","input":["price","4"],"out":false}}, - {"fn":"query","data":"price:>=5", "expect":{ "fn":"test","input":["price","0"],"out":false}} -] diff --git a/src/spec/query.rules.json b/src/spec/query.rules.json new file mode 100644 index 0000000..1be24b1 --- /dev/null +++ b/src/spec/query.rules.json @@ -0,0 +1,14 @@ +[ + {"fn":"query","data":"price:>=5", "expect":{ "fn":"testProperty","input":["price","10"],"out":true}}, + {"fn":"query","data":"price:>=15", "expect":{ "fn":"testProperty","input":["price","10"],"out":false}}, + {"fn":"query","data":"price:>=5", "expect":{ "fn":"testProperty","input":["price","4"],"out":false}}, + {"fn":"query","data":"price:>=5", "expect":{ "fn":"testProperty","input":["price","0"],"out":false}}, + {"fn":"query","data":"price:>=5 price:0", "expect":{ "fn":"testProperty","input":["price","1"],"out":false},"label":"price=1"}, + {"fn":"query","data":"price:>=5 price:0", "expect":{ "fn":"testProperty","input":["price","0"],"out":true},"label":"price=0"}, + {"fn":"query","data":"price:>=5 price:0", "expect":{ "fn":"testProperty","input":["price","6"],"out":true},"label":"price=6"}, + {"fn":"query","data":"tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true}}, + {"fn":"query","data":"-tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}}, + {"fn":"query","data":"-tag:foo", "expect":{ "fn":"testPropertyExclude","input":["tag","foo"],"out":true},"label":"testExclude"}, + {"fn":"query","data":".foo price:5 -tag:foo", "expect":{ "fn":"test","input":[{"price":5}],"out":true}}, + {"fn":"query","data":".foo price:5 -tag:foo", "expect":{ "fn":"test","input":[{"tag":"foo","price":5}],"out":false}} +] diff --git a/src/xrfragment/Query.hx b/src/xrfragment/Query.hx index 4e46655..6a61824 100644 --- a/src/xrfragment/Query.hx +++ b/src/xrfragment/Query.hx @@ -42,6 +42,8 @@ class Query { private var q:haxe.DynamicAccess = {}; private var isProp:EReg = ~/^.*:[><=!]?/; private var isExclude:EReg = ~/^-/; + private var isClass:EReg = ~/^[-]?class$/; + private var isNumber:EReg = ~/^[0-9\.]+$/; public function new(str:String){ if( str != null ) this.parse(str); @@ -65,29 +67,40 @@ class Query { function process(str,prefix = ""){ str = StringTools.trim(str); - var value:haxe.DynamicAccess = {}; + var k:String = str.split(":")[0]; + var v:String = str.split(":")[1]; + // retrieve existing filter if any + var filter:haxe.DynamicAccess = {}; + if( q.get(prefix+k) ) filter = q.get(prefix+k); + filter['rules'] = filter['rules'] != null ? filter['rules'] : new Array(); + if( isProp.match(str) ){ var oper:String = ""; if( str.indexOf("*") != -1 ) oper = "*"; if( str.indexOf(">") != -1 ) oper = ">"; if( str.indexOf("<") != -1 ) oper = "<"; - if( str.indexOf("!=") != -1 ) oper = "!="; if( str.indexOf(">=") != -1 ) oper = ">="; if( str.indexOf("<=") != -1 ) oper = "<="; - var k:String = str.split(":")[0]; - var v:String = str.split(":")[1]; - if( q.get(prefix+k) ) value = q.get(prefix+k); - if( oper.length > 0 ){ - value[ oper ] = Std.parseFloat( v.substr(oper.length) ); - q.set( k, value ); + if( isExclude.match(k) ){ + oper = "!="; + k = k.substr(1); // convert "-foo" into "foo" + }else v = v.substr(oper.length); // change ">=foo" into "foo" (strip operator) + if( oper.length == 0 ) oper = "="; + + if( isClass.match(k) ){ + filter[ prefix+ k ] = oper != "!="; + q.set(v,filter); }else{ - value[ prefix+ (isExclude.match(k) ? k.substr(1) : k) ] = isExclude.match(k) == false; - q.set(v,value); + var rule:haxe.DynamicAccess = {}; + if( isNumber.match(v) ) rule[ oper ] = Std.parseFloat(v); + else rule[oper] = v; + filter['rules'].push( rule ); + q.set( k, filter ); } return; }else{ // id - value[ "id" ] = isExclude.match(str) ? false: true; - q.set( (isExclude.match(str) ? str.substr(1) : str ) ,value ); + filter[ "id" ] = isExclude.match(str) ? false: true; + q.set( (isExclude.match(str) ? str.substr(1) : str ) ,filter ); } } for( i in 0...token.length ) process( expandAliases(token[i]) ); @@ -95,8 +108,21 @@ class Query { return this.q; } - @:keep - public function test( property:String, ?value:Dynamic ):Bool{ + public function test( ?obj:Dynamic ):Bool{ + var qualify:Bool = false; + // first apply includes, then excludes + for ( k in Reflect.fields(obj) ){ + var v:String = Std.string( Reflect.field(obj,k) ); + if( testProperty( k, v) ) qualify = true; + } + for ( k in Reflect.fields(obj) ){ + var v:String = Std.string( Reflect.field(obj,k) ); + if( testProperty( k, v, true) ) qualify = false; + } + return qualify; + } + + public function testProperty( property:String, value:String, ?exclude:Bool ):Bool{ var conds:Int = 0; var fails:Int = 0; var qualify:Int = 0; @@ -113,17 +139,28 @@ class Query { if( v.get(property) != null ) return v.get(property); } - // conditional props + // conditional rules for ( k in Reflect.fields(q) ){ - var qval:Dynamic = Reflect.field(q,k); - if( Std.isOfType(value, String) ) continue; - if( Reflect.field(qval,'=') != null && testprop( value == Reflect.field(qval,'=') ) ) qualify += 1; - if( Reflect.field(qval,'*') != null && testprop( value != null ) ) qualify += 1; - if( Reflect.field(qval,'>') != null && testprop( value > Std.parseFloat(Reflect.field(qval,'>' )) ) ) qualify += 1; - if( Reflect.field(qval,'<') != null && testprop( value < Std.parseFloat(Reflect.field(qval,'<' )) ) ) qualify += 1; - if( Reflect.field(qval,'>=') != null && testprop( value >= Std.parseFloat(Reflect.field(qval,'>=')) ) ) qualify += 1; - if( Reflect.field(qval,'<=') != null && testprop( value >= Std.parseFloat(Reflect.field(qval,'<=')) ) ) qualify += 1; - if( Reflect.field(qval,'!=') != null && testprop( value != Std.parseFloat(Reflect.field(qval,'!=')) ) ) qualify += 1; + var filter:Dynamic = Reflect.field(q,k); + if( filter.rules == null ) continue; + var rules:Array = filter.rules; + + for( rule in rules ){ + //if( Std.isOfType(value, String) ) contiggnue; + if( exclude ){ + if( Reflect.field(rule,'!=') != null && testprop( Std.string(value) == Std.string(Reflect.field(rule,'!='))) && exclude ) qualify += 1; + }else{ + if( Reflect.field(rule,'*') != null && testprop( Std.parseFloat(value) != null ) ) qualify += 1; + if( Reflect.field(rule,'>') != null && testprop( Std.parseFloat(value) > Std.parseFloat(Reflect.field(rule,'>' )) ) ) qualify += 1; + if( Reflect.field(rule,'<') != null && testprop( Std.parseFloat(value) < Std.parseFloat(Reflect.field(rule,'<' )) ) ) qualify += 1; + if( Reflect.field(rule,'>=') != null && testprop( Std.parseFloat(value) >= Std.parseFloat(Reflect.field(rule,'>=')) ) ) qualify += 1; + if( Reflect.field(rule,'<=') != null && testprop( Std.parseFloat(value) <= Std.parseFloat(Reflect.field(rule,'<=')) ) ) qualify += 1; + if( Reflect.field(rule,'=') != null && ( + testprop( value == Reflect.field(rule,'=')) || + testprop( Std.parseFloat(value) == Std.parseFloat(Reflect.field(rule,'='))) + )) qualify += 1; + } + } } return qualify > 0; } diff --git a/test/generated/test.js b/test/generated/test.js index 392373b..835c156 100644 --- a/test/generated/test.js +++ b/test/generated/test.js @@ -131,8 +131,8 @@ var Test = function() { }; Test.__name__ = true; Test.main = function() { Test.test([{ fn : "url", expect : { fn : "equal.string", input : "bar", out : "flop"}, data : "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3"},{ fn : "url", expect : { fn : "equal.xy", input : "a", out : "1.22.2"}, label : "a equal.xy", data : "http://foo.com?foo=1#bar=flop&a=1.2,2.2&b=c|d|1,2,3"},{ fn : "url", expect : { fn : "equal.multi", input : "b", out : "c|d|1,2,3"}, label : "b equal.multi", data : "http://foo.com?foo=1#b=c|d|1,2,3"}]); - Test.test([{ fn : "query", expect : { fn : "test", input : ["class","bar"], out : true}, data : "class:bar"},{ fn : "query", expect : { fn : "test", input : ["class","bar"], out : true}, label : ".bar shorthand", data : ".bar"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : false}, data : ".bar -.foo"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : true}, data : ".bar -.foo .foo"},{ fn : "query", expect : { fn : "test", input : ["class","bar"], out : true}, data : ".bar -.bar .bar"},{ fn : "query", expect : { fn : "test", input : ["id","foo"], out : true}, label : "id:foo?", data : "foo -foo foo"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:5 .foo"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:>5 .foo"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:>5 .foo"},{ fn : "query", expect : { fn : "test", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "test", input : ["id","foo"], out : false}, label : "!id:foo", data : ".foo -.foo .foo"}]); - Test.test([{ fn : "query", expect : { fn : "test", input : ["price","10"], out : true}, data : "price:>=5"},{ fn : "query", expect : { fn : "test", input : ["price","10"], out : false}, data : "price:>=15"},{ fn : "query", expect : { fn : "test", input : ["price","4"], out : false}, data : "price:>=5"},{ fn : "query", expect : { fn : "test", input : ["price","0"], out : false}, data : "price:>=5"}]); + Test.test([{ fn : "query", expect : { fn : "testProperty", input : ["class","bar"], out : true}, data : "class:bar"},{ fn : "query", expect : { fn : "testProperty", input : ["class","bar"], out : true}, label : ".bar shorthand", data : ".bar"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : false}, data : ".bar -.foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, data : ".bar -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","bar"], out : true}, data : ".bar -.bar .bar"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:5 .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:>5 .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:>5 .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["id","foo"], out : false}, label : "!id:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["id","foo"], out : true}, label : "id:foo?", data : "foo -foo foo"}]); + Test.test([{ fn : "query", expect : { fn : "testProperty", input : ["price","10"], out : true}, data : "price:>=5"},{ fn : "query", expect : { fn : "testProperty", input : ["price","10"], out : false}, data : "price:>=15"},{ fn : "query", expect : { fn : "testProperty", input : ["price","4"], out : false}, data : "price:>=5"},{ fn : "query", expect : { fn : "testProperty", input : ["price","0"], out : false}, data : "price:>=5"},{ fn : "query", expect : { fn : "testProperty", input : ["price","1"], out : false}, label : "price=1", data : "price:>=5 price:0"},{ fn : "query", expect : { fn : "testProperty", input : ["price","0"], out : true}, label : "price=0", data : "price:>=5 price:0"},{ fn : "query", expect : { fn : "testProperty", input : ["price","6"], out : true}, label : "price=6", data : "price:>=5 price:0"},{ fn : "query", expect : { fn : "testProperty", input : ["tag","foo"], out : true}, data : "tag:foo"},{ fn : "query", expect : { fn : "testProperty", input : ["tag","foo"], out : false}, data : "-tag:foo"},{ fn : "query", expect : { fn : "testPropertyExclude", input : ["tag","foo"], out : true}, label : "testExclude", data : "-tag:foo"},{ fn : "query", expect : { fn : "test", input : [{ price : 5}], out : true}, data : ".foo price:5 -tag:foo"},{ fn : "query", expect : { fn : "test", input : [{ tag : "foo", price : 5}], out : false}, data : ".foo price:5 -tag:foo"}]); }; Test.test = function(spec) { var Query = xrfragment_Query; @@ -152,7 +152,13 @@ Test.test = function(spec) { res = xrfragment_Url.parse(item.data); } if(item.expect.fn == "test") { - valid = item.expect.out == q.test(item.expect.input[0],item.expect.input[1]); + valid = item.expect.out == q.test(item.expect.input[0]); + } + if(item.expect.fn == "testProperty") { + valid = item.expect.out == q.testProperty(item.expect.input[0],item.expect.input[1]); + } + if(item.expect.fn == "testPropertyExclude") { + valid = item.expect.out == q.testProperty(item.expect.input[0],item.expect.input[1],true); } if(item.expect.fn == "equal.string") { valid = item.expect.out == res[item.expect.input].string; @@ -164,13 +170,13 @@ Test.test = function(spec) { valid = Test.equalMulti(res,item); } var ok = valid ? "[ ✔ ] " : "[ ❌] "; - console.log("src/Test.hx:36:",ok + Std.string(item.fn) + ": '" + Std.string(item.data) + "'" + (item.label ? " <= " + (item.label ? item.label : item.expect.fn) : "")); + console.log("src/Test.hx:38:",ok + Std.string(item.fn) + ": '" + Std.string(item.data) + "'" + (item.label ? " (" + (item.label ? item.label : item.expect.fn) + ")" : "")); if(!valid) { ++errors; } } if(errors > 1) { - console.log("src/Test.hx:39:","\n-----\n[ ❌] " + errors + " errors :/"); + console.log("src/Test.hx:41:","\n-----\n[ ❌] " + errors + " errors :/"); } }; Test.equalMulti = function(res,item) { @@ -265,6 +271,8 @@ js_Boot.__string_rec = function(o,s) { } }; var xrfragment_Query = function(str) { + this.isNumber = new EReg("^[0-9\\.]+$",""); + this.isClass = new EReg("^[-]?class$",""); this.isExclude = new EReg("^-",""); this.isProp = new EReg("^.*:[><=!]?",""); this.q = { }; @@ -294,7 +302,13 @@ xrfragment_Query.prototype = { prefix = ""; } str = StringTools.trim(str); - var value = { }; + var k = str.split(":")[0]; + var v = str.split(":")[1]; + var filter = { }; + if(q[prefix + k]) { + filter = q[prefix + k]; + } + filter["rules"] = filter["rules"] != null ? filter["rules"] : []; if(_gthis.isProp.match(str)) { var oper = ""; if(str.indexOf("*") != -1) { @@ -306,32 +320,39 @@ xrfragment_Query.prototype = { if(str.indexOf("<") != -1) { oper = "<"; } - if(str.indexOf("!=") != -1) { - oper = "!="; - } if(str.indexOf(">=") != -1) { oper = ">="; } if(str.indexOf("<=") != -1) { oper = "<="; } - var k = str.split(":")[0]; - var v = str.split(":")[1]; - if(q[prefix + k]) { - value = q[prefix + k]; - } - if(oper.length > 0) { - value[oper] = parseFloat(HxOverrides.substr(v,oper.length,null)); - q[k] = value; + if(_gthis.isExclude.match(k)) { + oper = "!="; + k = HxOverrides.substr(k,1,null); } else { - value[prefix + (_gthis.isExclude.match(k) ? HxOverrides.substr(k,1,null) : k)] = _gthis.isExclude.match(k) == false; - q[v] = value; + v = HxOverrides.substr(v,oper.length,null); + } + if(oper.length == 0) { + oper = "="; + } + if(_gthis.isClass.match(k)) { + filter[prefix + k] = oper != "!="; + q[v] = filter; + } else { + var rule = { }; + if(_gthis.isNumber.match(v)) { + rule[oper] = parseFloat(v); + } else { + rule[oper] = v; + } + filter["rules"].push(rule); + q[k] = filter; } return; } else { - value["id"] = _gthis.isExclude.match(str) ? false : true; + filter["id"] = _gthis.isExclude.match(str) ? false : true; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; - q[key] = value; + q[key] = filter; } }; var _g = 0; @@ -343,7 +364,31 @@ xrfragment_Query.prototype = { this.q = q; return this.q; } - ,test: function(property,value) { + ,test: function(obj) { + var qualify = false; + var _g = 0; + var _g1 = Reflect.fields(obj); + while(_g < _g1.length) { + var k = _g1[_g]; + ++_g; + var v = Std.string(Reflect.field(obj,k)); + if(this.testProperty(k,v)) { + qualify = true; + } + } + var _g = 0; + var _g1 = Reflect.fields(obj); + while(_g < _g1.length) { + var k = _g1[_g]; + ++_g; + var v = Std.string(Reflect.field(obj,k)); + if(this.testProperty(k,v,true)) { + qualify = false; + } + } + return qualify; + } + ,testProperty: function(property,value,exclude) { var conds = 0; var fails = 0; var qualify = 0; @@ -363,30 +408,39 @@ xrfragment_Query.prototype = { while(_g < _g1.length) { var k = _g1[_g]; ++_g; - var qval = Reflect.field(this.q,k); - if(typeof(value) == "string") { + var filter = Reflect.field(this.q,k); + if(filter.rules == null) { continue; } - if(Reflect.field(qval,"=") != null && testprop(value == Reflect.field(qval,"="))) { - ++qualify; - } - if(Reflect.field(qval,"*") != null && testprop(value != null)) { - ++qualify; - } - if(Reflect.field(qval,">") != null && testprop(value > parseFloat(Reflect.field(qval,">")))) { - ++qualify; - } - if(Reflect.field(qval,"<") != null && testprop(value < parseFloat(Reflect.field(qval,"<")))) { - ++qualify; - } - if(Reflect.field(qval,">=") != null && testprop(value >= parseFloat(Reflect.field(qval,">=")))) { - ++qualify; - } - if(Reflect.field(qval,"<=") != null && testprop(value >= parseFloat(Reflect.field(qval,"<=")))) { - ++qualify; - } - if(Reflect.field(qval,"!=") != null && testprop(value != parseFloat(Reflect.field(qval,"!=")))) { - ++qualify; + var rules = filter.rules; + var _g2 = 0; + while(_g2 < rules.length) { + var rule = rules[_g2]; + ++_g2; + if(exclude) { + if(Reflect.field(rule,"!=") != null && testprop((value == null ? "null" : "" + value) == Std.string(Reflect.field(rule,"!="))) && exclude) { + ++qualify; + } + } else { + if(Reflect.field(rule,"*") != null && testprop(parseFloat(value) != null)) { + ++qualify; + } + if(Reflect.field(rule,">") != null && testprop(parseFloat(value) > parseFloat(Reflect.field(rule,">")))) { + ++qualify; + } + if(Reflect.field(rule,"<") != null && testprop(parseFloat(value) < parseFloat(Reflect.field(rule,"<")))) { + ++qualify; + } + if(Reflect.field(rule,">=") != null && testprop(parseFloat(value) >= parseFloat(Reflect.field(rule,">=")))) { + ++qualify; + } + if(Reflect.field(rule,"<=") != null && testprop(parseFloat(value) <= parseFloat(Reflect.field(rule,"<=")))) { + ++qualify; + } + if(Reflect.field(rule,"=") != null && (testprop(value == Reflect.field(rule,"=")) || testprop(parseFloat(value) == parseFloat(Reflect.field(rule,"="))))) { + ++qualify; + } + } } } return qualify > 0; diff --git a/test/generated/test.py b/test/generated/test.py index 179be46..99b4752 100644 --- a/test/generated/test.py +++ b/test/generated/test.py @@ -380,8 +380,8 @@ class Test: @staticmethod def main(): Test.test([_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.string", 'input': "bar", 'out': "flop"}), 'data': "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "a", 'out': "1.22.2"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#bar=flop&a=1.2,2.2&b=c|d|1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.multi", 'input': "b", 'out': "c|d|1,2,3"}), 'label': "b equal.multi", 'data': "http://foo.com?foo=1#b=c|d|1,2,3"})]) - Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "bar"], 'out': True}), 'data': "class:bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "bar"], 'out': True}), 'label': ".bar shorthand", 'data': ".bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': False}), 'data': ".bar -.foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': True}), 'data': ".bar -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "bar"], 'out': True}), 'data': ".bar -.bar .bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["id", "foo"], 'out': True}), 'label': "id:foo?", 'data': "foo -foo foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:>5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:>5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["id", "foo"], 'out': False}), 'label': "!id:foo", 'data': ".foo -.foo .foo"})]) - Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["price", "10"], 'out': True}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["price", "10"], 'out': False}), 'data': "price:>=15"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["price", "4"], 'out': False}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': ["price", "0"], 'out': False}), 'data': "price:>=5"})]) + Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "bar"], 'out': True}), 'data': "class:bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "bar"], 'out': True}), 'label': ".bar shorthand", 'data': ".bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': False}), 'data': ".bar -.foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'data': ".bar -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "bar"], 'out': True}), 'data': ".bar -.bar .bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:>5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:>5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["id", "foo"], 'out': False}), 'label': "!id:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["id", "foo"], 'out': True}), 'label': "id:foo?", 'data': "foo -foo foo"})]) + Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "10"], 'out': True}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "10"], 'out': False}), 'data': "price:>=15"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "4"], 'out': False}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "0"], 'out': False}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "1"], 'out': False}), 'label': "price=1", 'data': "price:>=5 price:0"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "0"], 'out': True}), 'label': "price=0", 'data': "price:>=5 price:0"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "6"], 'out': True}), 'label': "price=6", 'data': "price:>=5 price:0"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': True}), 'data': "tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': False}), 'data': "-tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testPropertyExclude", 'input': ["tag", "foo"], 'out': True}), 'label': "testExclude", 'data': "-tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': [_hx_AnonObject({'price': 5})], 'out': True}), 'data': ".foo price:5 -tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': [_hx_AnonObject({'tag': "foo", 'price': 5})], 'out': False}), 'data': ".foo price:5 -tag:foo"})]) @staticmethod def test(spec): @@ -401,7 +401,11 @@ class Test: if (Reflect.field(item,"fn") == "url"): res = xrfragment_Url.parse(Reflect.field(item,"data")) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "test"): - valid = (Reflect.field(Reflect.field(item,"expect"),"out") == q.test(HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 0),HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 1))) + valid = (Reflect.field(Reflect.field(item,"expect"),"out") == q.test(HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 0))) + if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testProperty"): + valid = (Reflect.field(Reflect.field(item,"expect"),"out") == q.testProperty(HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 0),HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 1))) + if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testPropertyExclude"): + valid = (Reflect.field(Reflect.field(item,"expect"),"out") == q.testProperty(HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 0),HxOverrides.arrayGet(Reflect.field(Reflect.field(item,"expect"),"input"), 1),True)) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.string"): valid = HxOverrides.eq(Reflect.field(Reflect.field(item,"expect"),"out"),Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"string")) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.xy"): @@ -409,7 +413,7 @@ class Test: if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.multi"): valid = Test.equalMulti(res,item) ok = ("[ ✔ ] " if valid else "[ ❌] ") - print(str((((((("null" if ok is None else ok) + Std.string(Reflect.field(item,"fn"))) + ": '") + Std.string(Reflect.field(item,"data"))) + "'") + HxOverrides.stringOrNull((((" <= " + HxOverrides.stringOrNull(((Reflect.field(item,"label") if (Reflect.field(item,"label")) else Reflect.field(Reflect.field(item,"expect"),"fn"))))) if (Reflect.field(item,"label")) else "")))))) + print(str((((((("null" if ok is None else ok) + Std.string(Reflect.field(item,"fn"))) + ": '") + Std.string(Reflect.field(item,"data"))) + "'") + HxOverrides.stringOrNull(((((" (" + HxOverrides.stringOrNull(((Reflect.field(item,"label") if (Reflect.field(item,"label")) else Reflect.field(Reflect.field(item,"expect"),"fn"))))) + ")") if (Reflect.field(item,"label")) else "")))))) if (not valid): errors = (errors + 1) if (errors > 1): @@ -1153,7 +1157,7 @@ class python_internal_ArrayImpl: class HxOverrides: _hx_class_name = "HxOverrides" __slots__ = () - _hx_statics = ["eq", "stringOrNull", "length", "arrayGet"] + _hx_statics = ["eq", "stringOrNull", "push", "length", "arrayGet"] @staticmethod def eq(a,b): @@ -1168,6 +1172,14 @@ class HxOverrides: else: return s + @staticmethod + def push(x,e): + if isinstance(x,list): + _this = x + _this.append(e) + return len(_this) + return x.push(e) + @staticmethod def length(x): if isinstance(x,str): @@ -1319,11 +1331,13 @@ class HxString: class xrfragment_Query: _hx_class_name = "xrfragment.Query" - __slots__ = ("str", "q", "isProp", "isExclude") - _hx_fields = ["str", "q", "isProp", "isExclude"] - _hx_methods = ["toObject", "expandAliases", "parse", "test"] + __slots__ = ("str", "q", "isProp", "isExclude", "isClass", "isNumber") + _hx_fields = ["str", "q", "isProp", "isExclude", "isClass", "isNumber"] + _hx_methods = ["toObject", "expandAliases", "parse", "test", "testProperty"] def __init__(self,_hx_str): + self.isNumber = EReg("^[0-9\\.]+$","") + self.isClass = EReg("^[-]?class$","") self.isExclude = EReg("^-","") self.isProp = EReg("^.*:[><=!]?","") self.q = _hx_AnonObject({}) @@ -1352,7 +1366,13 @@ class xrfragment_Query: if (prefix is None): prefix = "" _hx_str = StringTools.trim(_hx_str) - value = _hx_AnonObject({}) + k = HxOverrides.arrayGet(_hx_str.split(":"), 0) + v = HxOverrides.arrayGet(_hx_str.split(":"), 1) + _hx_filter = _hx_AnonObject({}) + if Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))): + _hx_filter = Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))) + value = (Reflect.field(_hx_filter,"rules") if ((Reflect.field(_hx_filter,"rules") is not None)) else list()) + setattr(_hx_filter,(("_hx_" + "rules") if (("rules" in python_Boot.keywords)) else (("_hx_" + "rules") if (((((len("rules") > 2) and ((ord("rules"[0]) == 95))) and ((ord("rules"[1]) == 95))) and ((ord("rules"[(len("rules") - 1)]) != 95)))) else "rules")),value) _this = _gthis.isProp _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) if (_this.matchObj is not None): @@ -1367,41 +1387,48 @@ class xrfragment_Query: if (((_hx_str.find("<") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"<",startIndex))) != -1): oper = "<" startIndex = None - if (((_hx_str.find("!=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"!=",startIndex))) != -1): - oper = "!=" - startIndex = None if (((_hx_str.find(">=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,">=",startIndex))) != -1): oper = ">=" startIndex = None if (((_hx_str.find("<=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"<=",startIndex))) != -1): oper = "<=" - k = HxOverrides.arrayGet(_hx_str.split(":"), 0) - v = HxOverrides.arrayGet(_hx_str.split(":"), 1) - if Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))): - value = Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))) - if (len(oper) > 0): - value1 = Std.parseFloat(HxString.substr(v,len(oper),None)) - setattr(value,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),value1) - setattr(q,(("_hx_" + k) if ((k in python_Boot.keywords)) else (("_hx_" + k) if (((((len(k) > 2) and ((ord(k[0]) == 95))) and ((ord(k[1]) == 95))) and ((ord(k[(len(k) - 1)]) != 95)))) else k)),value) + _this = _gthis.isExclude + _this.matchObj = python_lib_Re.search(_this.pattern,k) + if (_this.matchObj is not None): + oper = "!=" + k = HxString.substr(k,1,None) else: - _this = _gthis.isExclude - _this.matchObj = python_lib_Re.search(_this.pattern,k) - key = (("null" if prefix is None else prefix) + HxOverrides.stringOrNull(((HxString.substr(k,1,None) if ((_this.matchObj is not None)) else k)))) - _this = _gthis.isExclude - _this.matchObj = python_lib_Re.search(_this.pattern,k) - value1 = ((_this.matchObj is not None) == False) - setattr(value,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value1) - setattr(q,(("_hx_" + v) if ((v in python_Boot.keywords)) else (("_hx_" + v) if (((((len(v) > 2) and ((ord(v[0]) == 95))) and ((ord(v[1]) == 95))) and ((ord(v[(len(v) - 1)]) != 95)))) else v)),value) + v = HxString.substr(v,len(oper),None) + if (len(oper) == 0): + oper = "=" + _this = _gthis.isClass + _this.matchObj = python_lib_Re.search(_this.pattern,k) + if (_this.matchObj is not None): + key = (("null" if prefix is None else prefix) + ("null" if k is None else k)) + value = (oper != "!=") + setattr(_hx_filter,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value) + setattr(q,(("_hx_" + v) if ((v in python_Boot.keywords)) else (("_hx_" + v) if (((((len(v) > 2) and ((ord(v[0]) == 95))) and ((ord(v[1]) == 95))) and ((ord(v[(len(v) - 1)]) != 95)))) else v)),_hx_filter) + else: + rule = _hx_AnonObject({}) + _this = _gthis.isNumber + _this.matchObj = python_lib_Re.search(_this.pattern,v) + if (_this.matchObj is not None): + value = Std.parseFloat(v) + setattr(rule,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),value) + else: + setattr(rule,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),v) + Reflect.field(Reflect.field(_hx_filter,"rules"),"push")(rule) + setattr(q,(("_hx_" + k) if ((k in python_Boot.keywords)) else (("_hx_" + k) if (((((len(k) > 2) and ((ord(k[0]) == 95))) and ((ord(k[1]) == 95))) and ((ord(k[(len(k) - 1)]) != 95)))) else k)),_hx_filter) return else: _this = _gthis.isExclude _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) - value1 = (False if ((_this.matchObj is not None)) else True) - setattr(value,(("_hx_" + "id") if (("id" in python_Boot.keywords)) else (("_hx_" + "id") if (((((len("id") > 2) and ((ord("id"[0]) == 95))) and ((ord("id"[1]) == 95))) and ((ord("id"[(len("id") - 1)]) != 95)))) else "id")),value1) + value = (False if ((_this.matchObj is not None)) else True) + setattr(_hx_filter,(("_hx_" + "id") if (("id" in python_Boot.keywords)) else (("_hx_" + "id") if (((((len("id") > 2) and ((ord("id"[0]) == 95))) and ((ord("id"[1]) == 95))) and ((ord("id"[(len("id") - 1)]) != 95)))) else "id")),value) _this = _gthis.isExclude _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) key = (HxString.substr(_hx_str,1,None) if ((_this.matchObj is not None)) else _hx_str) - setattr(q,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value) + setattr(q,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),_hx_filter) process = _hx_local_0 _g = 0 _g1 = len(token) @@ -1412,13 +1439,33 @@ class xrfragment_Query: self.q = q return self.q - def test(self,property,value = None): + def test(self,obj = None): + qualify = False + _g = 0 + _g1 = python_Boot.fields(obj) + while (_g < len(_g1)): + k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) + _g = (_g + 1) + v = Std.string(Reflect.field(obj,k)) + if self.testProperty(k,v): + qualify = True + _g = 0 + _g1 = python_Boot.fields(obj) + while (_g < len(_g1)): + k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) + _g = (_g + 1) + v = Std.string(Reflect.field(obj,k)) + if self.testProperty(k,v,True): + qualify = False + return qualify + + def testProperty(self,property,value,exclude = None): conds = 0 fails = 0 qualify = 0 def _hx_local_2(expr): - nonlocal fails nonlocal conds + nonlocal fails conds = (conds + 1) fails = (fails + (0 if expr else 1)) return expr @@ -1432,23 +1479,30 @@ class xrfragment_Query: while (_g < len(_g1)): k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None) _g = (_g + 1) - qval = Reflect.field(self.q,k) - if Std.isOfType(value,str): + _hx_filter = Reflect.field(self.q,k) + if (Reflect.field(_hx_filter,"rules") is None): continue - if ((Reflect.field(qval,"=") is not None) and testprop(HxOverrides.eq(value,Reflect.field(qval,"=")))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"*") is not None) and testprop((value is not None))): - qualify = (qualify + 1) - if ((Reflect.field(qval,">") is not None) and testprop((value > Std.parseFloat(Reflect.field(qval,">"))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"<") is not None) and testprop((value < Std.parseFloat(Reflect.field(qval,"<"))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,">=") is not None) and testprop((value >= Std.parseFloat(Reflect.field(qval,">="))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"<=") is not None) and testprop((value >= Std.parseFloat(Reflect.field(qval,"<="))))): - qualify = (qualify + 1) - if ((Reflect.field(qval,"!=") is not None) and testprop((value != Std.parseFloat(Reflect.field(qval,"!="))))): - qualify = (qualify + 1) + rules = Reflect.field(_hx_filter,"rules") + _g2 = 0 + while (_g2 < len(rules)): + rule = (rules[_g2] if _g2 >= 0 and _g2 < len(rules) else None) + _g2 = (_g2 + 1) + if exclude: + if (((Reflect.field(rule,"!=") is not None) and testprop((Std.string(value) == Std.string(Reflect.field(rule,"!="))))) and exclude): + qualify = (qualify + 1) + else: + if ((Reflect.field(rule,"*") is not None) and testprop((Std.parseFloat(value) is not None))): + qualify = (qualify + 1) + if ((Reflect.field(rule,">") is not None) and testprop((Std.parseFloat(value) > Std.parseFloat(Reflect.field(rule,">"))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,"<") is not None) and testprop((Std.parseFloat(value) < Std.parseFloat(Reflect.field(rule,"<"))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,">=") is not None) and testprop((Std.parseFloat(value) >= Std.parseFloat(Reflect.field(rule,">="))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,"<=") is not None) and testprop((Std.parseFloat(value) <= Std.parseFloat(Reflect.field(rule,"<="))))): + qualify = (qualify + 1) + if ((Reflect.field(rule,"=") is not None) and ((testprop((value == Reflect.field(rule,"="))) or testprop((Std.parseFloat(value) == Std.parseFloat(Reflect.field(rule,"="))))))): + qualify = (qualify + 1) return (qualify > 0)