標籤:tlv c 鏈表
/*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;}