/*
1、TLV简介:
在通信系统中,两个设备之前必然存在消息交互,消息的格式也存在各种编码类型,
本文仅描述TLV编码的消息格式。Type-length-value(TLV)格式中T、L的长度固定,
通常为1-8个4个字节,V的长度不固定,由L的值表示,V的内容也可以嵌套子TLV格式。
举例:假设消息按大端模式存放,T占4个字节,L占2个字节,下面的消息:
unsigned char pMsg[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01}
T = {0x09, 0x00, 0x00, 0x00},值为9。
L = {0x04, 0x00},值为4。
V = {0x01,0x01,0x01, 0x01} ,长度为4,每个字节的值均为1。
2、代码实现:a、按T的值由小到大排序一个消息(假定消息中不存在T相同的信元);
b、在两个消息中查找相同的信元(T、L、V)均相同,并输出信元个数。
作者:Socrates
日期:2014-08-05
*/
#include "stdafx.h"
#include <stdlib.h>
#include <memory.h>
#define TLV_T_LEN (4)
#define TLV_L_LEN (2)
/*错误码*/
enum _RetCode
{
ERR = -1, /*失败*/
OK = 0 /*成功*/
}RETCODE;
/*信元TLV结构*/
typedef struct _stIE
{
unsigned int ulTag; /*T*/
unsigned short usLen; /*L*/
unsigned char *pValue; /*V*/
}IE;
/*消息链表*/
typedef struct _stMsg
{
IE ie;
struct _stMsg *pNext;
}Msg;
/*
功能:创建链表
*/
int CreateMsgList(Msg *&pList)
{
pList = (Msg *)malloc(sizeof(Msg));
if (NULL == pList)
{
return ERR;
}
memset(&(pList->ie), 0, sizeof(IE));
pList->pNext = NULL;
return OK;
}
/*
功能:销毁链表
*/
void DestoryMsgList(Msg *pList)
{
if (NULL == pList)
{
return;
}
Msg *p = pList;
while(NULL != p)
{
p = p->pNext;
free(pList);
pList = p;
}
free(pList);
pList = NULL;
return;
}
/*
功能:向消息链表中插入信元,并保持按Tag递增
*/
int InsertIEToMsgList(Msg *pMsgList, const IE *pIE)
{
if ((NULL == pMsgList)
|| (NULL == pIE))
{
return ERR;
}
/*链表销毁时释放*/
Msg *pInsertMsg = (Msg *)malloc(sizeof(Msg));
if (NULL == pInsertMsg)
{
return ERR;
}
/*创建链表结点*/
memcpy(&(pInsertMsg->ie), pIE, sizeof(IE));
pInsertMsg->pNext = NULL;
/*按Tag递增插入结点,保持链表有序,不带头结点*/
Msg *p = pMsgList;
while(NULL != p->pNext)
{
if ((p->pNext->ie.ulTag) > (pIE->ulTag))
{
break;
}
p = p->pNext;
}
pInsertMsg->pNext = p->pNext;
p->pNext = pInsertMsg;
return OK;
}
/*
功能:获取指定消息中的第一个信元
*/
IE *GetIEFromMsg(const unsigned char *pInMsg)
{
if (NULL == pInMsg)
{
return NULL;
}
/*链表销毁时释放*/
IE *pIE = (IE *)malloc(sizeof(IE));
if (NULL == pIE)
{
return NULL;
}
memset(pIE, 0, sizeof(IE));
pIE->ulTag = *(unsigned int *)pInMsg;
pIE->usLen = *(unsigned short *)(pInMsg + TLV_T_LEN);
pIE->pValue = (unsigned char *)(pInMsg + TLV_T_LEN + TLV_L_LEN);
return pIE;
}
/*
功能:构造有序消息链表
*/
int CreateSortMsgList(unsigned char *pInMsg, unsigned int ulMsgLen, Msg *&pOutMsgList)
{
if ((NULL == pInMsg)
||(0 == ulMsgLen))
{
return ERR;
}
/*建立链表*/
if (ERR == CreateMsgList(pOutMsgList))
{
return ERR;
}
unsigned int iTmpMsgLen = 0;
IE *pIE = NULL;
/*遍历消息,注意获取信元并插入消息链表*/
while(iTmpMsgLen < ulMsgLen)
{
pIE = GetIEFromMsg(pInMsg);
if (NULL == pIE)
{
return ERR;
}
if(ERR == InsertIEToMsgList(pOutMsgList, pIE))
{
return ERR;
}
pInMsg += (TLV_T_LEN + TLV_L_LEN + pIE->usLen);
iTmpMsgLen += (TLV_T_LEN + TLV_L_LEN + pIE->usLen);
}
return OK;
}
/*
功能:消息排序
*/
int Sort(unsigned char *pInMsg, unsigned int ulMsgLen, unsigned char *pOutMsg)
{
if ((NULL == pInMsg)
|| (NULL == pOutMsg)
|| (0 == ulMsgLen))
{
return ERR;
}
/*建立有序消息链表*/
unsigned char *pTmp = pOutMsg;
Msg *pMsgList = NULL;
if (ERR == CreateSortMsgList(pInMsg, ulMsgLen, pMsgList))
{
DestoryMsgList(pMsgList);
return ERR;
}
/*输出排序后的消息*/
Msg *pList = pMsgList->pNext;
while(NULL != pList)
{
memcpy(pTmp, &(pList->ie), TLV_T_LEN + TLV_L_LEN);
memcpy(pTmp + TLV_T_LEN + TLV_L_LEN, pList->ie.pValue, pList->ie.usLen);
pTmp += (TLV_T_LEN + TLV_L_LEN + pList->ie.usLen);
pList = pList->pNext;
}
DestoryMsgList(pMsgList);
return OK;
}
/*
功能:比较两个信元是否相同
*/
int IsSameIE(IE *pIE1, IE *pIE2)
{
if ((NULL == pIE1)
|| (NULL == pIE2))
{
return ERR;
}
if ((pIE1->ulTag == pIE2->ulTag)
&& (pIE1->usLen == pIE2->usLen)
&& (0 == memcmp(pIE1->pValue, pIE2->pValue, pIE1->usLen)))
{
return OK;
}
return ERR;
}
/*
功能:比较两个消息,并输出相同信元个数
*/
int CompareMsg(unsigned char *pMsg1,
unsigned int ulMsgLen1,
unsigned char *pMsg2,
unsigned int ulMsgLen2,
unsigned int *ulSameNum)
{
/*创建有序消息链表1*/
Msg *pMsgList1 = NULL;
if (ERR == CreateSortMsgList(pMsg1, ulMsgLen1, pMsgList1))
{
DestoryMsgList(pMsgList1);
return ERR;
}
/*创建有序消息链表2*/
Msg *pMsgList2 = NULL;
if (ERR == CreateSortMsgList(pMsg2, ulMsgLen2, pMsgList2))
{
DestoryMsgList(pMsgList1);
DestoryMsgList(pMsgList2);
return ERR;
}
Msg *p = pMsgList1->pNext;
Msg *q = NULL;
unsigned int iCount = 0;
/*比较消息*/
while(NULL != p)
{
q = pMsgList2->pNext;
while(NULL != q)
{
if (OK == IsSameIE(&(p->ie), &(q->ie)))
{
iCount++;
}
q = q->pNext;
}
p = p->pNext;
}
DestoryMsgList(pMsgList1);
DestoryMsgList(pMsgList2);
*ulSameNum = iCount;
return OK;
}
int main(int argc, char* argv[])
{
unsigned char pMsg[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02,0x02,0x02, 0x02, 0x02, 0x02, 0x02,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03,0x03,0x03, 0x03, 0x03,
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08,0x08,
0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x09,0x09,0x09, 0x09};
unsigned char pMsg2[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02,0x02,0x02, 0x02, 0x02, 0x02, 0x02,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03,0x03,0x03, 0x03, 0x03,
0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01,0x01, 0x01,
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08,0x08,
0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x09,0x09,0x09, 0x09};
int iLen = sizeof(pMsg) / sizeof(pMsg[0]);
for (int i = 0; i < iLen; i++)
{
printf("0x%x,", pMsg[i]);
}
printf("\n\n");
unsigned char *pSortMsg = (unsigned char *)malloc(iLen);
if (NULL == pSortMsg)
{
return ERR;
}
if (ERR != Sort(pMsg, iLen, pSortMsg))
{
for (int i = 0; i < iLen; i++)
{
printf("0x%x,", pSortMsg[i]);
}
}
int iLen2 = sizeof(pMsg2) / sizeof(pMsg2[0]);
unsigned int iSameNum = 0;
if (ERR != CompareMsg(pMsg, iLen, pMsg2, iLen2, &iSameNum))
{
printf("\nSame Number is %d", iSameNum);
}
getchar();
return 0;
}