昨日、 TLV形式で情報を表現することを知りました。
ポータブルBERTLVエンコーダー/デコーダーをANSICで作成する場合、どのデータ構造を使用しますか(*)?
次のようなことはしますか?
struct TlvElement
{
    int nTag;
    int nLength;
    unsigned char *pValue; // Byte array
    TlvElement *pNext;
}; 
(*)残念ながら、これにはC++とSTLを使用できません。
昨日、 TLV形式で情報を表現することを知りました。
ポータブルBERTLVエンコーダー/デコーダーをANSICで作成する場合、どのデータ構造を使用しますか(*)?
次のようなことはしますか?
struct TlvElement
{
    int nTag;
    int nLength;
    unsigned char *pValue; // Byte array
    TlvElement *pNext;
}; 
(*)残念ながら、これにはC++とSTLを使用できません。
wikiの記事から:
タイプと長さはサイズが固定されています(通常は1〜4バイト)
そこで、nTagとnLengthを固定長タイプに変更します。intのサイズはプラットフォーム固有であり、これにより問題が発生する可能性があります。プロトコルに合わせてサイズを修正し、、、などを使用しますint8_t。int16_tのint32_t場合nLengthは、unsignedを使用することもできます。
値は任意のタイプである可能性があるvoid*ためpValue、の代わりにを使用しunsigned char*ます。
このデータ構造をどのように使用しますか?さまざまなTLVにどのようにアクセスしたいですか?
私のポイントは-リンクリストが必要ですか?または、リンクリストはあなたのケース/アプリケーション/目的などに最適なオプションですか?
私が言おうとしているのは、pNext要素を削除して、TLVを(動的に成長する)配列の要素として扱うことができるということです。これは本当にあなたのニーズに依存します。
おそらく、TLVを実装しているときに、何らかの接続を介してTLVを送信する必要がありますよね?もしそうなら、あなたはいくつかのプロトコルについて考える必要があります。私はこのようなことをします-最初にTLVの総数を送信し、リンクリストではなく動的配列を使用します。
このようなデータ構造をネットワーク経由で送信する場合は注意が必要pNextです。ポインタは有効ではないため、接続の反対側でリセットする必要があります。
また、慎重にデータを送信する必要がありますが、私はあなたがこれらのことを知っていると思います。私はそれらについて言及したかっただけです。
編集ネストされたTLVの意味を理解するのに問題があるようです。
ネストされたTLVは、TLVタイプの値を持つ単なるTLV要素です。そして、これはTLVの「コンテナ」(動的配列またはリンクリスト)とは何の関係もありません。
これは、アイデアを得るために、テストされていない例です。私はこれをこのようにします:
struct TLV
{
    uint32_t nTag;
    uint32_t nLength;
    void* pValue;
};
// created dynamic array with 3 TLVs:
TLV* pMyTLVs = malloc( 3 * sizeof( struct TLV ) );
// set the first 2 TLVs, some primitives, for example
// ..
// now, set the third TLV to be nested:
pMyTLVs[ 2 ].nTag = ...; // set some tag, that will indicate nested TLV
pMyTLVs[ 2 ].nLength = ...; // set length of the TLV element
pMyTLVs[ 2 ].pValue = malloc( sizeof( struct TLV ) );
// get pointer to the new, _nested_ TLV:
TLV* pNested = (TLV*)pMyTLVs[ 2 ].pValue; 
// now use the pNested TLV as an usual TLV:
pNested->nTag = ...;
pNested->nLength = ...;
pNested->pValue = ...;
// of course, pNested is not absolutely necessary, you may use directly
// pMyTLVs[ 2 ].pValue->...;
// but using pNested, makes the code more clear
注:繰り返しになりますが、これはテスト済みのコードではありませんが、あなたはその考えを理解していると思います。お役に立てば幸いです。
TLVエンコーダー/デコーダーをANSICで作成する場合は、実績のある、標準化された、柔軟なデータシリアル化(つまり、オンワイヤー)形式を選択します:ASN.1 BER、Thriftなど。
これは、ホイールが日常的に再発明される古典的なエリアです。賢明な人々は、効率的で、保守可能で、柔軟性のあるソリューションをすでに考えています。同じプロセスをもう一度実行しても意味がありません。
たとえば、例の構造がシリアル化に使用された場合でも、次のことを考慮する必要があります。
intコンパイラプラットフォームとOSによって異なります)一部の既存の形式は、セマンティクスと構文を分離します。その他の方法では、データスキーマのエンコーダー/デコーダーを自動的に生成できます。
シリアル化形式を選択したら、メモリ内形式の検討を開始できます。これは、アプリケーションがデータを操作する方法に大きく依存します。たとえば、次のようになります。
ASN.1 BERを処理するためにasn1cによって生成されたAPI、またはlibtasn1のAPIを確認することをお勧めします。