scansion/stanzacmp.lua

Tue, 10 Jul 2018 11:05:13 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Tue, 10 Jul 2018 11:05:13 +0100
changeset 92
9a58c8ee0757
parent 91
73fe018a0c5a
child 99
dc56d434e406
permissions
-rw-r--r--

stanzacmp: A new iteration of the stanza matching algorithm

6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 -- This is my attempt at a utility library to compare two XMPP stanzas
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 -- It is not testing for exact equivalency, but through some vague rules that felt right.
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 -- For example, the second stanza passed to stanzas_match() is allowed to have unexpected
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 -- elements and attributes at the top level. Beyond this, they must match exactly, except
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 -- for whitespace differences only.
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 --
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 -- There are probably bugs, and it can probably be smarter, but I don't want to spend too
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 -- much time on it right now.
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 local function trim(s)
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 return (s:gsub("^%s+", ""):gsub("%s+$", ""));
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 local function stanzas_strict_match(stanza1, stanza2)
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 if stanza1.name ~= stanza2.name or stanza1.attr.xmlns ~= stanza2.attr.xmlns then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 for k, v in pairs(stanza1.attr) do
91
73fe018a0c5a stanzacmp: Add {scansion:any} magic wildcard value for attributes
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
20 if v ~= "{scansion:any}" and stanza2.attr[k] ~= v then
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 for k, v in pairs(stanza2.attr) do
91
73fe018a0c5a stanzacmp: Add {scansion:any} magic wildcard value for attributes
Matthew Wild <mwild1@gmail.com>
parents: 33
diff changeset
26 if stanza1.attr[k] ~= "{scansion:any}" and stanza1.attr[k] ~= v then
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 if #stanza1.tags ~= #stanza2.tags then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 local stanza2_pos = 1;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 for _, child in ipairs(stanza1) do
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 if type(child) == "table" or child:match("%S") then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 local match;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 local child2 = stanza2[stanza2_pos];
32
0eabed6c91e7 stanzacmp: Check the correct side of the comparsion for whitespace
Kim Alvefur <zash@zash.se>
parents: 6
diff changeset
40 while child2 and not(type(child2) == "table" or child2:match("%S")) do
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 stanza2_pos = stanza2_pos + 1;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 child2 = stanza2[stanza2_pos];
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 if type(child) ~= type(child2) then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 if type(child) == "table" and child2.name == child.name and child2.attr.xmlns == child.attr.xmlns then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 -- Strict deep match
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 match = stanzas_strict_match(child, child2);
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 elseif type(child) == "string" then -- Text nodes, must be equal, ignoring leading/trailing whitespace
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 match = trim(child) == trim(child2);
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 if not match then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 return true;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 -- Everything in stanza1 should be present in stanza2
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 local function stanzas_match(stanza1, stanza2)
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 if stanza1.name ~= stanza2.name or stanza1.attr.xmlns ~= stanza2.attr.xmlns then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 for k, v in pairs(stanza1.attr) do
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 if stanza2.attr[k] ~= v then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73
92
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
74 local matched_children = {};
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 for _, child in ipairs(stanza1) do
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 if type(child) == "table" or child:match("%S") then
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 local match;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 -- Iterate through remaining nodes in stanza2, looking for a match
92
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
79 local stanza2_pos = 1;
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 while stanza2_pos <= #stanza2 do
92
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
81 if not matched_children[stanza2_pos] then
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
82 local child2 = stanza2[stanza2_pos];
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
83 stanza2_pos = stanza2_pos + 1;
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84
92
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
85 if type(child2) == type(child) then
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
86 if type(child) == "table" and child2.name == child.name and child2.attr.xmlns == child.attr.xmlns then
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
87 -- Strict deep match
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
88 match = stanzas_strict_match(child, child2);
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
89 elseif type(child) == "string" then -- Text nodes, must be equal, ignoring leading/trailing whitespace
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
90 match = trim(child) == trim(child2);
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
91 end
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
92 if match then
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
93 break;
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
94 end
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98 if not match then
92
9a58c8ee0757 stanzacmp: A new iteration of the stanza matching algorithm
Matthew Wild <mwild1@gmail.com>
parents: 91
diff changeset
99 --print(_, "No match for ", child:pretty_print())
6
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 return false;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 return true;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 end
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 return {
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 stanzas_match = stanzas_match;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 stanzas_strict_match = stanzas_strict_match;
0c94ea0cabec client: Implement send/receive, including new stanzacmp library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 };

mercurial