I tried implementing TLV(https://en.wikipedia.org/wiki/Type-length-value).Actually my implementation is more than TLV because it supports additional Tag elements (which you can use for naming certain TLV objects) for TLV objects.My goal is to serialize the array of TLV objects to byte array and vice versa (this I didn't implement yet).But I wrote class which handles single TLV and their serialization/deserialization. If this class is OK I believe it is much easier to extend it to arrays.Here is implementation. Feel free to comment.Btw: the class assumes little endian encoding for integersand no unicode strings are supportedPS. So basically single TLV object is a data structure which can either hold: a numeric type, string, or byte array, a type variable indicating which type of data it is, and a tag name indicating what value it is e.g. phone number..cpp file:#include stdafx.h#include TLVObject.hTLVObject::TLVObject(void){    clearMembers();}TLVObject::~TLVObject(void){}//////////////////////////////////////// Integers to byte arraysvector<uint8_t> TLVObject::UINT16ToByteArrayLE(uint16_t paramInt){    vector<uint8_t> arrayOfByte(2);    for (int i = 0; i < 2; i++)        arrayOfByte[i] = ((paramInt >> (i * 8)) & 0xFF);    return arrayOfByte;}vector<uint8_t> TLVObject::UINT32ToByteArrayLE(uint32_t paramInt){    vector<uint8_t> arrayOfByte(4);    for (int i = 0; i < 4; i++)        arrayOfByte[i] = ((paramInt >> (i * 8)) & 0xFF);    return arrayOfByte;}vector<uint8_t> TLVObject::UINT64ToByteArrayLE(uint64_t paramInt){    vector<uint8_t> arrayOfByte(8);    for (int i = 0; i < 8; i++)        arrayOfByte[i] = ((paramInt >> (i * 8)) & 0xFF);    return arrayOfByte;}/////////////////////////////////////////////////// Byte array to integersuint16_t TLVObject::LEToUINT16(vector<uint8_t> value){    if(value.size() != 2)        throw exception(LEToUINT16: Wrong size);    return (uint16_t)(((uint16_t)value[1] << 8) | (uint16_t)value[0]);}uint32_t TLVObject::LEToUINT32(vector<uint8_t> value){    if(value.size() != 4)        throw exception(LEToUINT32: Wrong size);    return (uint32_t)(((uint32_t)value[3] << 24) | ((uint32_t)value[2] << 16) | ((uint32_t)value[1] << 8) | (uint32_t)value[0]);    }uint64_t TLVObject::LEToUINT64(vector<uint8_t> value){    if(value.size() != 8)        throw exception(LEToUINT64: Wrong size);    uint64_t result =  static_cast<uint64_t>(value[0]) |        static_cast<uint64_t>(value[1]) << 8 |        static_cast<uint64_t>(value[2]) << 16 |        static_cast<uint64_t>(value[3]) << 24 |        static_cast<uint64_t>(value[4]) << 32 |        static_cast<uint64_t>(value[5]) << 40 |        static_cast<uint64_t>(value[6]) << 48 |        static_cast<uint64_t>(value[7]) << 56;    return result;}///////////////////////////////////////////////// Serialization and Deserialization methodsvector<uint8_t> TLVObject::Serialize(){    vector<uint8_t> tmp;    // Serialize type first    tmp.push_back((uint8_t)m_tlvType);    // Serialize tag name length (which is 2 bytes max) as little endian byte array    uint16_t tagLen = (uint16_t)m_tagName.length();    tmp.push_back(UINT16ToByteArrayLE(tagLen).at(0));    tmp.push_back(UINT16ToByteArrayLE(tagLen).at(1));    // Now serialize tag name itself    for(int i = 0; i < tagLen; i++)    {        tmp.push_back((uint8_t)m_tagName.at(i));    }    // Data size 4 byte integer.    uint32_t dataSize = 0;    if(m_tlvType == BLOB)    {        dataSize = m_blob.size();        // Serialize size        vector<uint8_t> tmp1 = UINT32ToByteArrayLE(dataSize);        tmp.push_back(tmp1.at(0));        tmp.push_back(tmp1.at(1));        tmp.push_back(tmp1.at(2));        tmp.push_back(tmp1.at(3));        // Now, serialize the blob.        for(uint32_t i = 0; i<dataSize; i++)            tmp.push_back(m_blob[i]);    }else if(m_tlvType == STRING)    {        dataSize = m_strValue.length();        // Serialize size        vector<uint8_t> tmp1 = UINT32ToByteArrayLE(dataSize);        tmp.push_back(tmp1.at(0));        tmp.push_back(tmp1.at(1));        tmp.push_back(tmp1.at(2));        tmp.push_back(tmp1.at(3));        // Now, serialize the string.        for(uint32_t i = 0; i<dataSize; i++)            tmp.push_back(m_strValue[i]);    }else if(m_tlvType == BYTE)    {        dataSize = 1;        // Serialize size        vector<uint8_t> tmp1 = UINT32ToByteArrayLE(dataSize);        tmp.push_back(tmp1.at(0));        tmp.push_back(tmp1.at(1));        tmp.push_back(tmp1.at(2));        tmp.push_back(tmp1.at(3));        // Serialize the byte.        tmp.push_back(m_BYTE);    }else if(m_tlvType == WORD)    {        dataSize = 2;        // Serialize size        vector<uint8_t> tmp1 = UINT32ToByteArrayLE(dataSize);        tmp.push_back(tmp1.at(0));        tmp.push_back(tmp1.at(1));        tmp.push_back(tmp1.at(2));        tmp.push_back(tmp1.at(3));        // Now, serialize the WORD value.        tmp.push_back(UINT16ToByteArrayLE(m_WORD).at(0));        tmp.push_back(UINT16ToByteArrayLE(m_WORD).at(1));    }else if(m_tlvType == DWORD)    {        dataSize = 4;        // Serialize size        vector<uint8_t> tmp1 = UINT32ToByteArrayLE(dataSize);        tmp.push_back(tmp1.at(0));        tmp.push_back(tmp1.at(1));        tmp.push_back(tmp1.at(2));        tmp.push_back(tmp1.at(3));        // Now, serialize the unsigned integer.        vector<uint8_t> tmp2 = UINT32ToByteArrayLE(m_DWORD);        tmp.push_back(tmp2.at(0));        tmp.push_back(tmp2.at(1));        tmp.push_back(tmp2.at(2));        tmp.push_back(tmp2.at(3));    }else if(m_tlvType == QWORD)    {        dataSize = 8;        // Serialize size        vector<uint8_t> tmp1 = UINT32ToByteArrayLE(dataSize);        tmp.push_back(tmp1.at(0));        tmp.push_back(tmp1.at(1));        tmp.push_back(tmp1.at(2));        tmp.push_back(tmp1.at(3));        // Serialize data        vector<uint8_t> tmp2 = UINT64ToByteArrayLE(m_QWORD);        tmp.push_back(tmp2.at(0));        tmp.push_back(tmp2.at(1));        tmp.push_back(tmp2.at(2));        tmp.push_back(tmp2.at(3));        tmp.push_back(tmp2.at(4));        tmp.push_back(tmp2.at(5));        tmp.push_back(tmp2.at(6));        tmp.push_back(tmp2.at(7));    }    return tmp;}void  TLVObject::Deserialize(vector<uint8_t> value){    // Get type    TLV_TYPE tlvType =  static_cast<TLV_TYPE>(value.at(0));    // Get tag name size.    vector<uint8_t> tmp;    tmp.push_back(value.at(1));    tmp.push_back(value.at(2));    uint16_t tagLength = LEToUINT16(tmp);    if(tagLength > MAXTAGLENGTH)        throw exception(Tag name length exceeded);    // Now get tag name    std::string tagName;    for(int i = 0; i<tagLength; i++)        tagName += value.at(3 + i); // Use an offset.    if(tlvType == STRING)    {        // Get value size        vector<uint8_t> tmp;        tmp.push_back(value.at(3 + tagLength + 0));        tmp.push_back(value.at(3 + tagLength + 1));        tmp.push_back(value.at(3 + tagLength + 2));        tmp.push_back(value.at(3 + tagLength + 3));        uint32_t valueSize = LEToUINT32(tmp);        clearMembers();        // Get value        m_strValue=;        for(uint32_t i = 0; i<valueSize; i++)            m_strValue += value.at(3 + tagLength + 4 + i);        // Assign other values too if we got this far.        m_tlvType = tlvType;        m_tagName = tagName;    }else if (tlvType == BLOB)    {        // Get value size        vector<uint8_t> tmp;        tmp.push_back(value.at(3 + tagLength + 0));        tmp.push_back(value.at(3 + tagLength + 1));        tmp.push_back(value.at(3 + tagLength + 2));        tmp.push_back(value.at(3 + tagLength + 3));        uint32_t valueSize = LEToUINT32(tmp);        clearMembers();        // Get value        m_blob.clear();        for(uint32_t i = 0; i<valueSize; i++)            m_blob.push_back(value.at(3 + tagLength + 4 + i));        // Assign other values too if we got this far.        m_tlvType = tlvType;        m_tagName = tagName;    }else if (tlvType == BYTE)    {        // Get value size        vector<uint8_t> tmp;        tmp.push_back(value.at(3 + tagLength + 0));        tmp.push_back(value.at(3 + tagLength + 1));        tmp.push_back(value.at(3 + tagLength + 2));        tmp.push_back(value.at(3 + tagLength + 3));        uint32_t valueSize = LEToUINT32(tmp);        clearMembers();        // Get value        m_BYTE = value.at(3 + tagLength + 4);        // Assign other values too if we got this far.        m_tlvType = tlvType;        m_tagName = tagName;    } else if (tlvType == WORD)    {        // Get value size        vector<uint8_t> tmp;        tmp.push_back(value.at(3 + tagLength + 0));        tmp.push_back(value.at(3 + tagLength + 1));        tmp.push_back(value.at(3 + tagLength + 2));        tmp.push_back(value.at(3 + tagLength + 3));        uint32_t valueSize = LEToUINT32(tmp);        // Get byte array represenginf the WORD        vector<uint8_t> tmp2;        for(int i = 0; i<2; i++)            tmp2.push_back(value.at(3 + tagLength + 4 + i));        clearMembers();        // Store word        m_WORD = LEToUINT16(tmp2);        // Assign other values too if we got this far.        m_tlvType = tlvType;        m_tagName = tagName;    }else if (tlvType == DWORD)    {        // Get value size        vector<uint8_t> tmp;        tmp.push_back(value.at(3 + tagLength + 0));        tmp.push_back(value.at(3 + tagLength + 1));        tmp.push_back(value.at(3 + tagLength + 2));        tmp.push_back(value.at(3 + tagLength + 3));        uint32_t valueSize = LEToUINT32(tmp);        // Get byte array represenginf the WORD        vector<uint8_t> tmp2;        for(int i = 0; i<4; i++)            tmp2.push_back(value.at(3 + tagLength + 4 + i));        clearMembers();        // Store work        m_DWORD = LEToUINT32(tmp2);        // Assign other values too if we got this far.        m_tlvType = tlvType;        m_tagName = tagName;    }else if (tlvType == QWORD)    {        // Get value size        vector<uint8_t> tmp;        tmp.push_back(value.at(3 + tagLength + 0));        tmp.push_back(value.at(3 + tagLength + 1));        tmp.push_back(value.at(3 + tagLength + 2));        tmp.push_back(value.at(3 + tagLength + 3));        uint32_t valueSize = LEToUINT32(tmp);        // Get byte array represenginf the WORD        vector<uint8_t> tmp2;        for(int i = 0; i<8; i++)            tmp2.push_back(value.at(3 + tagLength + 4 + i));        clearMembers();        // Store work        m_QWORD = LEToUINT64(tmp2);        // Assign other values too if we got this far.        m_tlvType = tlvType;        m_tagName = tagName;    }}header:#pragma once#include <cstdint>#include <string.h>#include <vector>#define MAXTAGLENGTH 20000using namespace std;enum TLV_TYPE {UNDEFINED = 0, BYTE, WORD, DWORD, QWORD, STRING, BLOB};class TLVObject{private:    TLV_TYPE m_tlvType;    // TLV type    std::string m_tagName; // TLV tag name; tag name max length is MAXTAGLENGTH    // Possible TLV values:    // TLV data size is 4 byte unsigned integer max.    uint8_t m_BYTE;    uint16_t m_WORD;    uint32_t m_DWORD;    uint64_t m_QWORD;    string m_strValue;    vector<uint8_t> m_blob;    void clearMembers()    {        m_tlvType = UNDEFINED;        m_tagName = ;        m_BYTE = 0;        m_WORD = 0;        m_DWORD = 0;        m_QWORD = 0;        m_strValue = ;    }    // Helpers    // These work exclusively assuming little endian encoding    vector<uint8_t> UINT16ToByteArrayLE(uint16_t paramInt);    vector<uint8_t> UINT32ToByteArrayLE(uint32_t paramInt);    vector<uint8_t> UINT64ToByteArrayLE(uint64_t paramInt);    uint16_t LEToUINT16(vector<uint8_t> value);    uint32_t LEToUINT32(vector<uint8_t> value);    uint64_t LEToUINT64(vector<uint8_t> value);public:    vector<uint8_t> Serialize();    void  Deserialize(vector<uint8_t> value);    TLVObject(string tag, vector<uint8_t> blob)    {        if(tag.length() > MAXTAGLENGTH)            throw exception(Tag name length exceeded);        m_tlvType = BLOB;        m_tagName = tag;        m_blob = blob;    }    TLVObject(string tag, uint8_t value)    {        if(tag.length() > MAXTAGLENGTH)            throw exception(Tag name length exceeded);        m_tlvType = BYTE;        m_tagName = tag;        m_BYTE = value;    }    TLVObject(string tag, uint16_t value)    {        if(tag.length() > MAXTAGLENGTH)            throw exception(Tag name length exceeded);        m_tlvType = WORD;        m_tagName = tag;        m_WORD = value;    }    TLVObject(string tag, uint32_t value)    {        if(tag.length() > MAXTAGLENGTH)            throw exception(Tag name length exceeded);        m_tlvType = DWORD;        m_tagName = tag;        m_DWORD = value;    }    TLVObject(string tag, uint64_t value)    {        if(tag.length() > MAXTAGLENGTH)            throw exception(Tag name length exceeded);        m_tlvType = QWORD;        m_tagName = tag;        m_QWORD = value;    }    TLVObject(string tag, string value)    {        if(tag.length() > MAXTAGLENGTH)            throw exception(Tag name length exceeded);        m_tlvType = STRING;        m_tagName = tag;        m_strValue = value;    }    string GetStringValue()    {        if(m_tlvType != STRING)            throw exception(This is not string TLV);        return m_strValue;    }    vector<uint8_t> GetBlobValue()    {        if(m_tlvType != BLOB)            throw exception(This is not BLOB TLV);        return m_blob;    }    uint8_t GetBYTEValue()    {        if(m_tlvType != BYTE)            throw exception(This is not BYTE TLV);        return m_BYTE;    }    uint16_t GetUINT16Value()    {        if(m_tlvType != WORD)            throw exception(This is not WORD TLV);        return m_WORD;    }    uint32_t GetUINT32Value()    {        if(m_tlvType != DWORD)            throw exception(This is not DWORD TLV);        return m_DWORD;    }    uint64_t GetUINT64Value()    {        if(m_tlvType != QWORD)            throw exception(This is not QWORD TLV);        return m_QWORD;    }    TLV_TYPE GetType()    {        return m_tlvType;    }    TLVObject(void);    ~TLVObject(void);};Test program for single TLV  TLVObject obj(Name, (uint16_t)255);  vector<uint8_t> tmp = obj.Serialize(); // Serialize as byte array  TLVObject obj1;  obj1.Deserialize(tmp); // Reconstruct TLV from byte array
TLV implementation in C++
c++;serialization