Files
paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester/src/LTopicTable.cpp
tomoaki bb993aed5b Update: Add Pre-defined-Topic
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-14 19:20:48 +09:00

288 lines
5.6 KiB
C++

/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "LMqttsnClientApp.h"
#include "LTopicTable.h"
using namespace std;
using namespace linuxAsyncClient;
/*=====================================
Class Topic
======================================*/
LTopic::LTopic(){
_topicStr = 0;
_callback = 0;
_topicId = 0;
_topicType = MQTTSN_TOPIC_TYPE_NORMAL;
_next = 0;
_malocFlg = 0;
}
LTopic::~LTopic(){
if (_malocFlg){
free(_topicStr);
}
}
TopicCallback LTopic::getCallback(void){
return _callback;
}
int LTopic::execCallback(uint8_t* payload, uint16_t payloadlen){
if(_callback != 0){
return _callback(payload, payloadlen);
}
return 0;
}
uint8_t LTopic::hasWildCard(uint8_t* pos){
*pos = strlen(_topicStr) - 1;
if (*(_topicStr + *pos) == '#'){
return MQTTSN_TOPIC_MULTI_WILDCARD;
}else{
for(uint8_t p = 0; p < strlen(_topicStr); p++){
if (*(_topicStr + p) == '+'){
*pos = p;
return MQTTSN_TOPIC_SINGLE_WILDCARD;
}
}
}
return 0;
}
bool LTopic::isMatch(const char* topic){
uint8_t pos;
if ( strlen(topic) < strlen(_topicStr)){
return false;
}
uint8_t wc = hasWildCard(&pos);
if (wc == MQTTSN_TOPIC_SINGLE_WILDCARD){
if ( strncmp(_topicStr, topic, pos - 1) == 0){
if (*(_topicStr + pos + 1) == '/'){
for(uint8_t p = pos; p < strlen(topic); p++){
if (*(topic + p) == '/'){
if (strcmp(_topicStr + pos + 1, topic + p ) == 0){
return true;
}
}
}
}else{
for(uint8_t p = pos + 1;p < strlen(topic); p++){
if (*(topic + p) == '/'){
return false;
}
}
}
return true;
}
}else if (wc == MQTTSN_TOPIC_MULTI_WILDCARD){
if (strncmp(_topicStr, topic, pos) == 0){
return true;
}
}else if (strcmp(_topicStr, topic) == 0){
return true;
}
return false;
}
/*=====================================
Class TopicTable
======================================*/
LTopicTable::LTopicTable(){
_first = 0;
_last = 0;
}
LTopicTable::~LTopicTable(){
clearTopic();
}
LTopic* LTopicTable::getTopic(const char* topic){
LTopic* p = _first;
while(p){
if (p->_topicStr != 0 && strcmp(p->_topicStr, topic) == 0){
return p;
}
p = p->_next;
}
return 0;
}
LTopic* LTopicTable::getTopic(uint16_t topicId, MQTTSN_topicTypes topicType){
LTopic* p = _first;
while(p){
if (p->_topicId == topicId && p->_topicType == topicType){
return p;
}
p = p->_next;
}
return 0;
}
uint16_t LTopicTable::getTopicId(const char* topic){
LTopic* p = getTopic(topic);
if (p){
return p->_topicId;
}
return 0;
}
char* LTopicTable::getTopicName(LTopic* topic){
return topic->_topicStr;
}
void LTopicTable::setTopicId(const char* topic, uint16_t id, MQTTSN_topicTypes type){
LTopic* tp = getTopic(topic);
if (tp){
tp->_topicId = id;
}else{
add(topic, type, id, 0);
}
}
bool LTopicTable::setCallback(const char* topic, TopicCallback callback){
LTopic* p = getTopic(topic);
if (p){
p->_callback = callback;
return true;
}
return false;
}
bool LTopicTable::setCallback(uint16_t topicId, MQTTSN_topicTypes topicType, TopicCallback callback){
LTopic* p = getTopic(topicId, topicType);
if (p){
p->_callback = callback;
return true;
}
return false;
}
int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, MQTTSN_topicTypes topicType){
LTopic* p = getTopic(topicId, topicType);
if (p){;
return p->execCallback(payload, payloadlen);
}
return 0;
}
LTopic* LTopicTable::add(const char* topicName, MQTTSN_topicTypes type, uint16_t id, TopicCallback callback, uint8_t alocFlg)
{
LTopic* elm;
if (topicName){
elm = getTopic(topicName);
}else{
elm = getTopic(id, type);
}
if (elm == 0){
elm = new LTopic();
if(elm == 0){
goto exit;
}
if ( _last == 0){
_first = elm;
_last = elm;
}
else
{
elm->_prev = _last;
_last->_next = elm;
_last = elm;
}
elm->_topicStr = const_cast <char*>(topicName);
elm->_topicId = id;
elm->_topicType = type;
elm->_callback = callback;
elm->_malocFlg = alocFlg;
elm->_prev = 0;
}else{
elm->_callback = callback;
}
exit:
return elm;
}
void LTopicTable::remove(uint16_t topicId, MQTTSN_topicTypes type)
{
LTopic* elm = getTopic(topicId, type);
if (elm){
if (elm->_prev == 0)
{
_first = elm->_next;
if (elm->_next == 0)
{
_last = 0;
}
else
{
elm->_next->_prev = 0;
_last = elm->_next;
}
}
else
{
if ( elm->_next == 0 )
{
_last = elm->_prev;
}
elm->_prev->_next = elm->_next;
}
delete elm;
}
}
LTopic* LTopicTable::match(const char* topicName){
LTopic* elm = _first;
while(elm){
if (elm->isMatch(topicName)){
break;
}
elm = elm->_next;
}
return elm;
}
void LTopicTable::clearTopic(void){
LTopic* p = _first;
while(p){
_first = p->_next;
delete p;
p = _first;
}
_last = 0;
}