Commit 0ac7618585b1eef3d2280f35513f8e93909feecd

Authored by Wiebe Cazemier
1 parent 4bbc76ec

Use vector for splitting topic path

It's a little faster.
subscriptionstore.cpp
@@ -66,7 +66,7 @@ void SubscriptionStore::publishNonRecursively(const MqttPacket &packet, const st @@ -66,7 +66,7 @@ void SubscriptionStore::publishNonRecursively(const MqttPacket &packet, const st
66 } 66 }
67 } 67 }
68 68
69 -void SubscriptionStore::publishRecursively(std::list<std::string>::const_iterator cur_subtopic_it, std::list<std::string>::const_iterator end, 69 +void SubscriptionStore::publishRecursively(std::vector<std::string>::const_iterator cur_subtopic_it, std::vector<std::string>::const_iterator end,
70 std::unique_ptr<SubscriptionNode> &this_node, const MqttPacket &packet) const 70 std::unique_ptr<SubscriptionNode> &this_node, const MqttPacket &packet) const
71 { 71 {
72 if (cur_subtopic_it == end) // This is the end of the topic path, so look for subscribers here. 72 if (cur_subtopic_it == end) // This is the end of the topic path, so look for subscribers here.
@@ -105,7 +105,7 @@ void SubscriptionStore::queuePacketAtSubscribers(const std::string &amp;topic, const @@ -105,7 +105,7 @@ void SubscriptionStore::queuePacketAtSubscribers(const std::string &amp;topic, const
105 { 105 {
106 // TODO: keep a cache of topics vs clients 106 // TODO: keep a cache of topics vs clients
107 107
108 - const std::list<std::string> subtopics = split(topic, '/'); 108 + const std::vector<std::string> subtopics = splitToVector(topic, '/');
109 109
110 RWLockGuard lock_guard(&subscriptionsRwlock); 110 RWLockGuard lock_guard(&subscriptionsRwlock);
111 lock_guard.rdlock(); 111 lock_guard.rdlock();
subscriptionstore.h
@@ -43,7 +43,7 @@ class SubscriptionStore @@ -43,7 +43,7 @@ class SubscriptionStore
43 std::unordered_set<RetainedMessage> retainedMessages; 43 std::unordered_set<RetainedMessage> retainedMessages;
44 44
45 void publishNonRecursively(const MqttPacket &packet, const std::forward_list<std::string> &subscribers) const; 45 void publishNonRecursively(const MqttPacket &packet, const std::forward_list<std::string> &subscribers) const;
46 - void publishRecursively(std::list<std::string>::const_iterator cur_subtopic_it, std::list<std::string>::const_iterator end, 46 + void publishRecursively(std::vector<std::string>::const_iterator cur_subtopic_it, std::vector<std::string>::const_iterator end,
47 std::unique_ptr<SubscriptionNode> &next, const MqttPacket &packet) const; 47 std::unique_ptr<SubscriptionNode> &next, const MqttPacket &packet) const;
48 public: 48 public:
49 SubscriptionStore(); 49 SubscriptionStore();
utils.cpp
@@ -125,3 +125,21 @@ bool isValidPublishPath(const std::string &amp;s) @@ -125,3 +125,21 @@ bool isValidPublishPath(const std::string &amp;s)
125 125
126 return true; 126 return true;
127 } 127 }
  128 +
  129 +std::vector<std::string> splitToVector(const std::string &input, const char sep, size_t max, bool keep_empty_parts)
  130 +{
  131 + std::vector<std::string> list;
  132 + list.reserve(16); // This is somewhat arbitratry, knowing some typical MQTT topic use cases
  133 + size_t start = 0;
  134 + size_t end;
  135 +
  136 + while (list.size() < max && (end = input.find(sep, start)) != std::string::npos)
  137 + {
  138 + if (start != end || keep_empty_parts)
  139 + list.push_back(input.substr(start, end - start));
  140 + start = end + 1; // increase by length of seperator.
  141 + }
  142 + if (start != input.size() || keep_empty_parts)
  143 + list.push_back(input.substr(start, std::string::npos));
  144 + return list;
  145 +}
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 #include <string> 6 #include <string>
7 #include <list> 7 #include <list>
8 #include <limits> 8 #include <limits>
  9 +#include <vector>
9 10
10 template<typename T> int check(int rc) 11 template<typename T> int check(int rc)
11 { 12 {
@@ -20,6 +21,7 @@ template&lt;typename T&gt; int check(int rc) @@ -20,6 +21,7 @@ template&lt;typename T&gt; int check(int rc)
20 } 21 }
21 22
22 std::list<std::string> split(const std::string &input, const char sep, size_t max = std::numeric_limits<int>::max(), bool keep_empty_parts = true); 23 std::list<std::string> split(const std::string &input, const char sep, size_t max = std::numeric_limits<int>::max(), bool keep_empty_parts = true);
  24 +std::vector<std::string> splitToVector(const std::string &input, const char sep, size_t max = std::numeric_limits<int>::max(), bool keep_empty_parts = true);
23 25
24 bool topicsMatch(const std::string &subscribeTopic, const std::string &publishTopic); 26 bool topicsMatch(const std::string &subscribeTopic, const std::string &publishTopic);
25 27