@@ -228,33 +228,56 @@ static int mqtt_is_topic_equals(const char *topic_filter, const char *topic)
228
228
return 0 ;
229
229
}
230
230
231
- static char mqtt_topic_is_matched (char * topic_filter , MQTTString * topic_name )
231
+ static char mqtt_topic_is_matched (const char * topic_filter , MQTTString * topic_name )
232
232
{
233
- char * curf = topic_filter ;
234
- char * curn = topic_name -> lenstring .data ;
235
- char * curn_end = curn + topic_name -> lenstring .len ;
236
-
237
- while (* curf && curn < curn_end )
238
- {
239
- if (* curn == '/' && * curf != '/' )
240
- break ;
241
-
242
- /* support wildcards for MQTT topics, such as '#' '+' */
243
- if (* curf != '+' && * curf != '#' && * curf != * curn )
244
- break ;
245
-
246
- if (* curf == '+' ) {
247
- char * nextpos = curn + 1 ;
248
- while (nextpos < curn_end && * nextpos != '/' )
249
- nextpos = ++ curn + 1 ;
233
+ const char * filter = topic_filter ;
234
+ const char * topic = topic_name -> lenstring .data ;
235
+ int topic_len = topic_name != NULL && topic != NULL ? strnlen (topic , topic_name -> lenstring .len ) : 0 ;
236
+ int filter_len = strlen (filter );
237
+ int i = 0 , j = 0 ;
238
+ while (i < filter_len && j < topic_len ) {
239
+ if (filter [i ] == '#' ) {
240
+ // '#' must be at the end and must be preceded by '/' or be the first character
241
+ if ((i == filter_len - 1 ) && (i == 0 || filter [i - 1 ] == '/' )) {
242
+ return 1 ;
243
+ }
244
+ else {
245
+ return 0 ;
246
+ }
247
+ }
248
+ if (filter [i ] == '+' ) {
249
+ // '+' must occupy an entire level
250
+ if ((i > 0 && filter [i - 1 ] != '/' ) || (i < filter_len - 1 && filter [i + 1 ] != '/' && filter [i + 1 ] != '\0' )) {
251
+ return 0 ;
252
+ }
253
+ // Skip one level in the topic
254
+ while (j < topic_len && topic [j ] != '/' ) j ++ ;
255
+ i ++ ;
250
256
}
251
- else if (* curf == '#' )
252
- curn = curn_end - 1 ;
253
- curf ++ ;
254
- curn ++ ;
255
- };
257
+ else {
258
+ // Ordinary characters match one by one
259
+ if (filter [i ] != topic [j ]) {
260
+ return 0 ;
261
+ }
262
+ i ++ ;
263
+ j ++ ;
264
+ }
265
+ // Skip '/'
266
+ if (i < filter_len && filter [i ] == '/' && j < topic_len && topic [j ] == '/' ) {
267
+ i ++ ;
268
+ j ++ ;
269
+ }
270
+ }
256
271
257
- return (curn == curn_end ) && (* curf == '\0' );
272
+ // Process ending
273
+ if (i == filter_len && j == topic_len ) {
274
+ return 1 ;
275
+ }
276
+ // Allow ending with "/#" and topic is entirely consumed
277
+ if ((i == filter_len - 2 ) && filter [i ] == '/' && filter [i + 1 ] == '#' && j == topic_len ) {
278
+ return 1 ;
279
+ }
280
+ return 0 ;
258
281
}
259
282
260
283
static void mqtt_new_message_data (message_data_t * md , MQTTString * topic_name , mqtt_message_t * message )
0 commit comments