Jack Hansdampf / mbed-mqtt-GSOE1

Dependents:   ESP8266MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LTopicTable.cpp Source File

LTopicTable.cpp

00001 /**************************************************************************************
00002  * Copyright (c) 2016, Tomoaki Yamaguchi
00003  *
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * and the Eclipse Distribution License is available at
00011  *   http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
00015  **************************************************************************************/
00016 
00017 #include <string.h>
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 
00021 #include "LMqttsnClientApp.h"
00022 #include "LTopicTable.h"
00023 
00024 using namespace std;
00025 using namespace linuxAsyncClient;
00026 /*=====================================
00027         Class Topic
00028  ======================================*/
00029 LTopic::LTopic(){
00030     _topicStr = 0;
00031     _callback = 0;
00032     _topicId = 0;
00033     _topicType = MQTTSN_TOPIC_TYPE_NORMAL;
00034     _next = 0;
00035     _malocFlg = 0;
00036 }
00037 
00038 LTopic::~LTopic(){
00039     if (_malocFlg){
00040         free(_topicStr);
00041     }
00042 }
00043 
00044 TopicCallback LTopic::getCallback(void){
00045     return _callback;
00046 }
00047 
00048 int LTopic::execCallback(uint8_t* payload, uint16_t payloadlen){
00049     if(_callback != 0){
00050         return _callback(payload, payloadlen);
00051     }
00052     return 0;
00053 }
00054 
00055 
00056 uint8_t LTopic::hasWildCard(uint8_t* pos){
00057     *pos = strlen(_topicStr) - 1;
00058     if (*(_topicStr + *pos) == '#'){
00059         return MQTTSN_TOPIC_MULTI_WILDCARD;
00060     }else{
00061         for(uint8_t p = 0; p < strlen(_topicStr); p++){
00062             if (*(_topicStr + p) == '+'){
00063                 *pos = p;
00064                 return MQTTSN_TOPIC_SINGLE_WILDCARD;
00065             }
00066         }
00067     }
00068     return 0;
00069 }
00070 
00071 bool LTopic::isMatch(const char* topic){
00072     uint8_t pos;
00073 
00074     if ( strlen(topic) < strlen(_topicStr)){
00075         return false;
00076     }
00077 
00078     uint8_t wc = hasWildCard(&pos);
00079 
00080     if (wc == MQTTSN_TOPIC_SINGLE_WILDCARD){
00081         if ( strncmp(_topicStr, topic, pos - 1) == 0){
00082             if (*(_topicStr + pos + 1) == '/'){
00083                 for(uint8_t p = pos; p < strlen(topic); p++){
00084                     if (*(topic + p) == '/'){
00085                         if (strcmp(_topicStr + pos + 1, topic + p ) == 0){
00086                             return true;
00087                         }
00088                     }
00089                 }
00090             }else{
00091                 for(uint8_t p = pos + 1;p < strlen(topic); p++){
00092                     if (*(topic + p) == '/'){
00093                         return false;
00094                     }
00095                 }
00096             }
00097             return true;
00098         }
00099     }else if (wc == MQTTSN_TOPIC_MULTI_WILDCARD){
00100         if (strncmp(_topicStr, topic, pos) == 0){
00101             return true;
00102         }
00103     }else if (strcmp(_topicStr, topic) == 0){
00104         return true;
00105     }
00106     return false;
00107 }
00108 
00109 
00110 /*=====================================
00111         Class TopicTable
00112  ======================================*/
00113 LTopicTable::LTopicTable(){
00114     _first = 0;
00115     _last = 0;
00116 }
00117 
00118 LTopicTable::~LTopicTable(){
00119     clearTopic();
00120 }
00121 
00122 
00123 LTopic* LTopicTable::getTopic(const char* topic){
00124     LTopic* p = _first;
00125     while(p){
00126         if (p->_topicStr != 0 && strcmp(p->_topicStr, topic) == 0){
00127             return p;
00128         }
00129         p = p->_next;
00130     }
00131     return 0;
00132 }
00133 
00134 LTopic* LTopicTable::getTopic(uint16_t topicId, MQTTSN_topicTypes topicType){
00135     LTopic* p = _first;
00136     while(p){
00137         if (p->_topicId == topicId && p->_topicType == topicType){
00138             return p;
00139         }
00140         p = p->_next;
00141     }
00142     return 0;
00143 }
00144 
00145 uint16_t LTopicTable::getTopicId(const char* topic){
00146     LTopic* p = getTopic(topic);
00147     if (p){
00148         return p->_topicId;
00149     }
00150     return 0;
00151 }
00152 
00153 
00154 char* LTopicTable::getTopicName(LTopic* topic){
00155     return topic->_topicStr;
00156 }
00157 
00158 
00159 void LTopicTable::setTopicId(const char* topic, uint16_t id, MQTTSN_topicTypes type){
00160     LTopic* tp = getTopic(topic);
00161     if (tp){
00162         tp->_topicId = id;
00163     }else{
00164         add(topic, type, id, 0);
00165     }
00166 }
00167 
00168 
00169 bool LTopicTable::setCallback(const char* topic, TopicCallback callback){
00170     LTopic* p = getTopic(topic);
00171     if (p){
00172         p->_callback = callback;
00173         return true;
00174     }
00175     return false;
00176 }
00177 
00178 
00179 bool LTopicTable::setCallback(uint16_t topicId, MQTTSN_topicTypes topicType, TopicCallback callback){
00180     LTopic* p = getTopic(topicId, topicType);
00181     if (p){
00182         p->_callback = callback;
00183         return true;
00184     }
00185     return false;
00186 }
00187 
00188 
00189 int LTopicTable::execCallback(uint16_t  topicId, uint8_t* payload, uint16_t payloadlen, MQTTSN_topicTypes topicType){
00190     LTopic* p = getTopic(topicId, topicType);
00191     if (p){;
00192         return p->execCallback(payload, payloadlen);
00193     }
00194     return 0;
00195 }
00196 
00197 
00198 LTopic* LTopicTable::add(const char* topicName, MQTTSN_topicTypes type, uint16_t id, TopicCallback callback, uint8_t alocFlg)
00199 {
00200     LTopic* elm;
00201 
00202     if (topicName){
00203         elm = getTopic(topicName);
00204     }else{
00205         elm = getTopic(id, type);
00206     }
00207     
00208     if (elm == 0){
00209         elm = new LTopic();
00210         if(elm == 0){
00211             goto exit;
00212         }
00213         if ( _last == 0){
00214             _first = elm;
00215             _last = elm;
00216         }
00217         else
00218         {
00219             elm->_prev = _last;
00220             _last->_next = elm;
00221             _last = elm;
00222         }
00223 
00224         elm->_topicStr =  const_cast <char*>(topicName);
00225         elm->_topicId = id;
00226         elm->_topicType = type;
00227         elm->_callback = callback;
00228         elm->_malocFlg = alocFlg;
00229         elm->_prev = 0;
00230     }else{
00231         elm->_callback = callback;
00232     }
00233 exit:
00234     return elm;
00235 }
00236 
00237 void LTopicTable::remove(uint16_t topicId, MQTTSN_topicTypes type)
00238 {
00239     LTopic* elm = getTopic(topicId, type);
00240 
00241     if (elm){
00242         if (elm->_prev == 0)
00243         {
00244             _first = elm->_next;
00245             if (elm->_next == 0)
00246             {
00247                 _last = 0;
00248             }
00249             else
00250             {
00251                 elm->_next->_prev = 0;
00252                 _last = elm->_next;
00253             }
00254         }
00255         else
00256         {
00257             if ( elm->_next == 0 )
00258             {
00259                 _last = elm->_prev;
00260             }
00261             elm->_prev->_next = elm->_next;
00262         }
00263         delete elm;
00264     }
00265 }
00266 
00267 LTopic* LTopicTable::match(const char* topicName){
00268     LTopic* elm = _first;
00269     while(elm){
00270         if (elm->isMatch(topicName)){
00271             break;
00272         }
00273         elm = elm->_next;
00274     }
00275     return elm;
00276 }
00277 
00278 
00279 void LTopicTable::clearTopic(void){
00280     LTopic* p = _first;
00281     while(p){
00282         _first = p->_next;
00283         delete p;
00284         p = _first;
00285     }
00286     _last = 0;
00287 }