Until now I only supported multi-level wildcards because it was easy and I couldn't find an example that was fast enough on micropython (20ms was not an option) but now I wrote an optimized matcher that supports single-level wildcards too and it finishes all operations in about 1ms on the esp8266.
Code: Select all
def matchesSubscription(subscription, topic):
if topic == subscription:
return True
if subscription.endswith("/#") or subscription.endswith("/+"):
lens = len(subscription)
if memoryview(topic)[:lens - 2] == memoryview(subscription)[:-2]:
if subscription.endswith("/#"):
if len(topic) == lens - 2 or memoryview(topic)[lens - 2:lens - 1] == b"/":
# check if identifier matches subscription or has sublevel
# (home/test/# does not listen to home/testing but to home/test)
return True
else:
if topic.count("/") == subscription.count("/"):
# only the same sublevel matches
return True
pl = subscription.find("/+/")
if pl != -1:
st = topic.find("/", pl + 1) + 1
if memoryview(subscription)[:pl + 1] == memoryview(topic)[:pl + 1]:
if memoryview(subscription)[pl + 3:] == memoryview(topic)[st:]:
return True
return False
return False
Code: Select all
import time
def timeit(f, *args):
a = time.ticks_us()
r = f(*args)
b = time.ticks_us()
return b - a, r
def match(sub, topic):
print("-------------------")
print(sub, topic)
gc.collect()
t, r = timeit(matchesSubscription, sub, topic)
print("Result:", r, t, "us")
match("home/kevin/set", "home/kevin")
match("home/kevin/set", "home/kevin/set")
match("home/kevin/gpio/+/set", "home/kevin/gpio/13/set2")
match("home/kevin/gpio/+/set", "home/kevin/gpio/13/set")
match("home/kevin/gpio/+/set", "home/kevin/gpio/13")
match("home/kevin/#", "home/kevin/test")
match("home/kevin/#", "home/kevin")
match("home/kevin/#", "home/kevinNot")
match("home/88c3b900/gpio/14/set", "home/88c3b900/gpio/14/set")
match("home/88c3b900/+/14/set", "home/88c3b900/gpio/14")