#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
typedef struct tagKamiTlv
{
struct tagKamiTlv *next;
struct tagKamiTlv *prev;
struct tagKamiTlv *child;
struct tagKamiTlv *parent;
unsigned short type;
unsigned short length;
int obj_type;
char *value;
} KamiTlv_S;
typedef struct
{
unsigned char *buffer;
size_t length;
size_t offset;
} KamiTlvPrintBuffer;
#define KamiTlv_Invalid (0)
#define KamiTlv_Tlv (1 << 0)
#define KamiTlv_Object (1 << 1)
#define KamiTlv_Array (1 << 2)
unsigned short little2bigs(unsigned short num)
{
unsigned short swapped = (num >> 8) | (num << 8);
return swapped;
}
//大端轉(zhuǎn)小端
unsigned short big2littles(unsigned short be)
{
unsigned short swapped = (be << 8) | (be >> 8);
return swapped;
}
#define htons little2bigs
#define ntohs big2littles
void Kami_Tlv_Delete(KamiTlv_S *pstTlv);
int Kami_Tlv_PrintValue(KamiTlv_S *pstItem, KamiTlvPrintBuffer *output_buffer);
KamiTlv_S *Kami_Tlv_CreateObject()
{
KamiTlv_S *pstTlv = (KamiTlv_S *)malloc(sizeof(KamiTlv_S));
if (!pstTlv)
{
return NULL;
}
memset(pstTlv, 0, sizeof(KamiTlv_S));
pstTlv->obj_type = KamiTlv_Object;
return pstTlv;
}
KamiTlv_S *Kami_Tlv_CreateArray(unsigned short usType)
{
KamiTlv_S *pstTlv = (KamiTlv_S *)malloc(sizeof(KamiTlv_S));
if (!pstTlv)
{
return NULL;
}
memset(pstTlv, 0, sizeof(KamiTlv_S));
pstTlv->obj_type = KamiTlv_Array;
pstTlv->type = usType;
return pstTlv;
}
KamiTlv_S *Kami_Tlv_CreateTlv(unsigned short usType, unsigned short usLength, void *pValue)
{
KamiTlv_S *pstTlv = Kami_Tlv_CreateObject();
if (pstTlv)
{
pstTlv->type = usType;
pstTlv->length = usLength;
if (usLength)
{
pstTlv->value = (char *)malloc(usLength);
if (!pstTlv->value)
{
Kami_Tlv_Delete(pstTlv);
return NULL;
}
memcpy(pstTlv->value, pValue, usLength);
}
pstTlv->obj_type = KamiTlv_Tlv;
}
return pstTlv;
}
void Kami_Tlv_Delete(KamiTlv_S *pstTlv)
{
KamiTlv_S *pstNext = NULL;
while (pstTlv != NULL)
{
pstNext = pstTlv->next;
if (pstTlv->child != NULL)
{
Kami_Tlv_Delete(pstTlv->child);
}
if (pstTlv->value != NULL)
{
printf("free %s\n", pstTlv->value);
free(pstTlv->value);
}
free(pstTlv);
pstTlv = pstNext;
}
}
int Kami_Tlv_AddItemToObject(KamiTlv_S *pstTlv, KamiTlv_S *pstItem)
{
KamiTlv_S *pstChild = pstTlv->child;
pstItem->parent = pstTlv;
if (pstChild == NULL)
{
pstTlv->child = pstItem;
pstItem->prev = pstItem;
pstItem->next = NULL;
}
else
{
if (pstChild->prev)
{
pstChild->prev->next = pstItem;
pstItem->prev = pstChild->prev;
pstTlv->child->prev = pstItem;
}
}
unsigned short usIncLength = 0;
if (pstItem->obj_type == KamiTlv_Tlv || pstItem->obj_type == KamiTlv_Array)
{
usIncLength = (sizeof(unsigned short) * 2 + pstItem->length);
}
else if (pstItem->obj_type == KamiTlv_Object)
{
usIncLength = pstItem->length;
}
while (pstTlv)
{
KamiTlv_S *pstParent = pstTlv->parent;
pstTlv->length += usIncLength;
pstTlv = pstParent;
}
return 0;
}
int Kami_Tlv_AddTlvToObject(KamiTlv_S *pstTlv, unsigned short usType, unsigned short usLength, void *pValue)
{
KamiTlv_S *pstItem = Kami_Tlv_CreateTlv(usType, usLength, pValue);
if (!pstItem)
{
return -1;
}
if (0 == Kami_Tlv_AddItemToObject(pstTlv, pstItem))
{
return 0;
}
Kami_Tlv_Delete(pstItem);
return -1;
}
void Kami_Tlv_UpdateOffset(KamiTlvPrintBuffer *buffer, KamiTlv_S *pstItem)
{
switch ((pstItem->obj_type) & 0xFF)
{
case KamiTlv_Tlv:
buffer->offset += (sizeof(unsigned short) * 2 + pstItem->length);
break;
case KamiTlv_Array:
break;
case KamiTlv_Object:
default:
return;
}
return;
}
static unsigned char *Kami_Tlv_Ensure(KamiTlvPrintBuffer *const p, size_t needed)
{
unsigned char *newbuffer = NULL;
size_t newsize = 0;
if ((p == NULL) || (p->buffer == NULL))
{
return NULL;
}
if ((p->length > 0) && (p->offset >= p->length))
{
return NULL;
}
if (needed > INT_MAX)
{
return NULL;
}
needed += p->offset + 1;
if (needed <= p->length)
{
return p->buffer + p->offset;
}
if (needed > (INT_MAX / 2))
{
if (needed <= INT_MAX)
{
newsize = INT_MAX;
}
else
{
return NULL;
}
}
else
{
newsize = needed * 2;
}
newbuffer = (unsigned char *)realloc(p->buffer, newsize);
if (newbuffer == NULL)
{
free(p->buffer);
p->length = 0;
p->buffer = NULL;
return NULL;
}
p->length = newsize;
p->buffer = newbuffer;
return newbuffer + p->offset;
}
int Kami_Tlv_PrintTlv(KamiTlv_S *input, KamiTlvPrintBuffer *const output_buffer)
{
unsigned char *output = NULL;
if (!input)
{
return -1;
}
output = Kami_Tlv_Ensure(output_buffer, input->length + sizeof(unsigned short) * 2);
if (output == NULL)
{
return -1;
}
*((unsigned short *)output) = htons(input->type);
*((unsigned short *)(output + sizeof(unsigned short))) = htons(input->length);
memcpy(output + 2 * sizeof(unsigned short), input->value, input->length);
output_buffer->offset += (input->length + sizeof(unsigned short) * 2);
return 0;
}
int Kami_Tlv_PrintObject(KamiTlv_S *item, KamiTlvPrintBuffer *const output_buffer)
{
unsigned char *output_pointer = NULL;
size_t length = 0;
KamiTlv_S *current_item = item->child;
if (output_buffer == NULL)
{
return -1;
}
while (current_item)
{
if (Kami_Tlv_PrintValue(current_item, output_buffer))
{
return -1;
}
current_item = current_item->next;
}
return 0;
}
int Kami_Tlv_PrintArray(KamiTlv_S *item, KamiTlvPrintBuffer *const output_buffer)
{
unsigned char *output_pointer = NULL;
size_t length = 0;
KamiTlv_S *current_item = item->child;
if (output_buffer == NULL)
{
return -1;
}
output_pointer = Kami_Tlv_Ensure(output_buffer, sizeof(unsigned short) * 2);
if (output_pointer == NULL)
{
return -1;
}
*((unsigned short *)output_pointer) = htons(item->type);
*((unsigned short *)(output_pointer + sizeof(unsigned short))) = htons(item->length);
output_buffer->offset += sizeof(unsigned short) * 2;
while (current_item)
{
if (Kami_Tlv_PrintValue(current_item, output_buffer))
{
return -1;
}
current_item = current_item->next;
}
return 0;
}
int Kami_Tlv_PrintValue(KamiTlv_S *pstItem, KamiTlvPrintBuffer *output_buffer)
{
unsigned char *output = NULL;
if ((pstItem == NULL) || (output_buffer == NULL))
{
return -1;
}
switch ((pstItem->obj_type) & 0xFF)
{
case KamiTlv_Tlv:
return Kami_Tlv_PrintTlv(pstItem, output_buffer);
case KamiTlv_Array:
return Kami_Tlv_PrintArray(pstItem, output_buffer);
case KamiTlv_Object:
return Kami_Tlv_PrintObject(pstItem, output_buffer);
default:
return -1;
}
}
unsigned char *Kami_Tlv_Print(KamiTlv_S *pstTlv)
{
static const size_t default_buffer_size = 256;
KamiTlvPrintBuffer buffer[1];
unsigned char *printed = NULL;
memset(buffer, 0, sizeof(buffer));
buffer->buffer = (unsigned char *)malloc(default_buffer_size);
buffer->length = default_buffer_size;
if (buffer->buffer == NULL)
{
goto fail;
}
if (Kami_Tlv_PrintValue(pstTlv, buffer))
{
goto fail;
}
printed = (unsigned char *)realloc(buffer->buffer, buffer->offset + 1);
if (printed == NULL)
{
goto fail;
}
buffer->buffer = NULL;
return printed;
fail:
if (buffer->buffer != NULL)
{
free(buffer->buffer);
}
if (printed != NULL)
{
free(printed);
}
return NULL;
}
KamiTlv_S *Kami_Tlv_ParseObject(void *pTlvData, int iLength)
{
if (!pTlvData || iLength < sizeof(unsigned short) * 2)
{
return NULL;
}
KamiTlv_S *pstRoot = Kami_Tlv_CreateObject();
if (!pstRoot)
{
return NULL;
}
int iOffset = 0;
char *pcTmp = (char *)pTlvData;
while (iLength - iOffset > 2 * sizeof(unsigned short))
{
unsigned short *pusType = (unsigned short *)(pcTmp + iOffset);
iOffset += sizeof(unsigned short);
unsigned short *pusLength = (unsigned short *)(pcTmp + iOffset);
iOffset += sizeof(unsigned short);
void *pValue = (void *)(pcTmp + iOffset);
if (Kami_Tlv_AddTlvToObject(pstRoot, ntohs(*pusType), ntohs(*pusLength), pValue))
{
Kami_Tlv_Delete(pstRoot);
pstRoot = NULL;
break;
}
iOffset += ntohs(*pusLength);
}
return pstRoot;
}
KamiTlv_S *Kami_Tlv_GetObjectItem(KamiTlv_S *pstObject, unsigned short usType)
{
KamiTlv_S *pstNext = NULL;
KamiTlv_S *pstChild = pstObject->child;
while (pstChild != NULL)
{
pstNext = pstChild->next;
if (pstChild->type == usType)
{
break;
}
pstChild = pstNext;
}
return pstChild;
}
KamiTlv_S *Kami_Tlv_GetObjectItemIndex(KamiTlv_S *pstObject, int iIndex)
{
KamiTlv_S *pstChild = NULL;
if (!pstObject)
{
return NULL;
}
pstChild = pstObject->child;
while (pstChild != NULL && iIndex > 0)
{
iIndex--;
pstChild = pstChild->next;
}
return pstChild;
}
int Kami_Tlv_GetObjectNumber(KamiTlv_S *pstObject)
{
KamiTlv_S *pstChild = NULL;
int iIndex = 0;
if (!pstObject)
{
return NULL;
}
pstChild = pstObject->child;
while (pstChild != NULL)
{
iIndex++;
pstChild = pstChild->next;
}
return iIndex;
}
int Kami_Tlv_ObjectLength(KamiTlv_S *pstObject)
{
return pstObject->length;
}
int main()
{
KamiTlv_S *pstRoot = Kami_Tlv_CreateObject();
KamiTlv_S *pstArr1 = Kami_Tlv_CreateArray(16);
Kami_Tlv_AddTlvToObject(pstArr1, 1, 2, (void *)"a");
Kami_Tlv_AddTlvToObject(pstArr1, 2, 2, (void *)"b");
KamiTlv_S *pstArr2 = Kami_Tlv_CreateArray(17);
Kami_Tlv_AddTlvToObject(pstArr2, 1, 2, (void *)"c");
Kami_Tlv_AddTlvToObject(pstArr2, 2, 2, (void *)"d");
KamiTlv_S *pstArr3 = Kami_Tlv_CreateArray(18);
Kami_Tlv_AddTlvToObject(pstArr3, 1, 2, (void *)"e");
Kami_Tlv_AddTlvToObject(pstArr3, 2, 2, (void *)"f");
Kami_Tlv_AddItemToObject(pstRoot, pstArr1);
Kami_Tlv_AddItemToObject(pstArr1, pstArr2);
Kami_Tlv_AddItemToObject(pstArr2, pstArr3);
unsigned char *pr = Kami_Tlv_Print(pstRoot);
int length = Kami_Tlv_ObjectLength(pstRoot);
Kami_Tlv_Delete(pstRoot);
KamiTlv_S *pstParsed1 = Kami_Tlv_ParseObject(pr, length);
for (int i = 0; i < Kami_Tlv_GetObjectNumber(pstParsed1); i++)
{
KamiTlv_S *pstTmp = Kami_Tlv_GetObjectItemIndex(pstParsed1, i);
printf("type: %d, length: %d\n", pstTmp->type, pstTmp->length);
}
KamiTlv_S *pstItem16 = Kami_Tlv_GetObjectItem(pstParsed1, 16);
KamiTlv_S *pstParsed2 = Kami_Tlv_ParseObject(pstItem16->value, pstItem16->length);
for (int i = 0; i < Kami_Tlv_GetObjectNumber(pstParsed2); i++)
{
KamiTlv_S *pstTmp = Kami_Tlv_GetObjectItemIndex(pstParsed2, i);
printf("type: %d, length: %d\n", pstTmp->type, pstTmp->length);
}
KamiTlv_S *pstItem17 = Kami_Tlv_GetObjectItem(pstParsed2, 17);
KamiTlv_S *pstParsed3 = Kami_Tlv_ParseObject(pstItem17->value, pstItem17->length);
for (int i = 0; i < Kami_Tlv_GetObjectNumber(pstParsed3); i++)
{
KamiTlv_S *pstTmp = Kami_Tlv_GetObjectItemIndex(pstParsed3, i);
printf("type: %d, length: %d\n", pstTmp->type, pstTmp->length);
}
KamiTlv_S *pstItem18 = Kami_Tlv_GetObjectItem(pstParsed3, 18);
KamiTlv_S *pstParsed4 = Kami_Tlv_ParseObject(pstItem18->value, pstItem18->length);
for (int i = 0; i < Kami_Tlv_GetObjectNumber(pstParsed4); i++)
{
KamiTlv_S *pstTmp = Kami_Tlv_GetObjectItemIndex(pstParsed4, i);
printf("type: %d, length: %d\n", pstTmp->type, pstTmp->length);
}
return 0;
}
簡(jiǎn)單Tlv序列化和反序列化
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)绢慢,“玉大人,你說(shuō)我怎么就攤上這事洛波∫扔撸” “怎么了?”我有些...
- 文/不壞的土叔 我叫張陵蹬挤,是天一觀的道長(zhǎng)缚窿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)焰扳,這世上最難降的妖魔是什么倦零? 我笑而不...
- 正文 為了忘掉前任,我火速辦了婚禮吨悍,結(jié)果婚禮上扫茅,老公的妹妹穿的比我還像新娘。我一直安慰自己育瓜,他們只是感情好葫隙,可當(dāng)我...
- 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著躏仇,像睡著了一般恋脚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上焰手,一...
- 那天糟描,我揣著相機(jī)與錄音,去河邊找鬼书妻。 笑死船响,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灿意,決...
- 文/蒼蘭香墨 我猛地睜開(kāi)眼估灿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了缤剧?” 一聲冷哼從身側(cè)響起馅袁,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荒辕,沒(méi)想到半個(gè)月后汗销,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡抵窒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年弛针,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片李皇。...
- 正文 年R本政府宣布卓囚,位于F島的核電站瘾杭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哪亿。R本人自食惡果不足惜粥烁,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝇棉。 院中可真熱鬧讨阻,春花似錦、人聲如沸银萍。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贴唇。三九已至搀绣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戳气,已是汗流浹背链患。 一陣腳步聲響...
- 正文 我出身青樓纲仍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贸毕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子郑叠,可洞房花燭夜當(dāng)晚...
推薦閱讀更多精彩內(nèi)容
- 名詞解釋 序列化:將Java對(duì)象轉(zhuǎn)化成字節(jié)的過(guò)程 反序列化:將字節(jié)轉(zhuǎn)化成Java對(duì)象的過(guò)程 字節(jié):1字節(jié)(byte...
- 什么是Protocol Buffer? Protocol Buffer是谷歌出品的一種數(shù)據(jù)交換格式明棍,獨(dú)立于語(yǔ)言和平...
- 先來(lái)看一個(gè) json的sample 再看 一個(gè)xml的sample 還不夠乡革?再看yaml的sample 如果喜歡這...
- 首先一般我們傳輸?shù)亩际荍son因?yàn)榭焖龠€比較好理解 在這里下載Json.NET的庫(kù)https://www.newt...
- 引用類(lèi)型(對(duì)象)保留數(shù)據(jù)+類(lèi)型 序列化ObjectOutputStream 反序列化ObjectInputStre...