2

データを逆シリアル化するためのライブラリを作成しています。次のような構造体定義があります。

#ifndef SEARCHRESULTS_H
#define SEARCHRESULTS_H

typedef struct {
    char *url;
} SearchResult;

typedef struct {
    int count;
    SearchResult *searchResults;
} SearchResults;

#endif

C にはリフレクションがないため、すべての関数を手動で作成する必要がありますが、ヘッダーを解析し、struct名前とフィールドを見つけ、関数を生成するための優れた方法があるはずです (疑似 C):

#include "SearchResults.h"
#include "pdata_serialization.h"

void SearchResult_parse(pdata *data, SearchResult *obj) {
    obj->url = strdup(data->values["url"]);
}

void SearchResult_free(SearchResult *obj) {
    free(obj->url);
    free(obj);
}

void SearchResults_parse(pdata *data, SearchResults *obj) {
    obj->count = data->values["count"];
    obj->searchResults = malloc(sizeof(SearchResult) * obj->count);
    for (int i = 0; i < obj->count; i++)
        SearchResult_parse(data->values["searchResults"][i], &obj->searchResults[i]);
}

void SearchResults_free(SearchResults *obj) {
    for (int i = 0; i < obj->count; i++)
        SearchResult_free(&obj->searchResults[i]);
    free(obj);
}

私は完全な解決策を探しているわけではありませんが、正気で最小限のアイデアと小さな例を探しています。

4

2 に答える 2

1

これをGNU Autogenで解決しました。構造体ごとに 1 つずつ、ヘッダーを定義ファイルに変換しました。

// SearchResult.def
AutoGen Definitions struct;
struct = {
    type = "char *";
    name = "url";
};

// SearchResults.def
AutoGen Definitions struct;
struct = {
    type = "SearchResult *";
    name = "searchResults";
};

そして、次のそれほどきれいではないテンプレートを作成しました。

[= AutoGen5 Template h c =][=
    (define model (string-substitute (def-file) ".def" ""))
=][=
    CASE (suffix)
=][=
    == h
=][=
    (make-header-guard "")
=]

typedef struct _[= (. model) =] {[=
    FOR struct =]
    [=
        (get "type")
    =][=
        (get "name")
    =];[=
        IF (and (*== (get "type") "*") (not (== (get "type") "char *"))) =]
    size_t [= (get "name") =]Count;[=
        ENDIF =][=
    ENDFOR struct
=]
} [= (. model) =];

#endif /* [= (. header-guard) =] */
[=
    == c
=]#include "[= (. header-file) =]"
#include "pdata_serialization.h"

void [= (. model) =]_parse(pdata *data, [= (. model) =] *obj) {[=
    FOR struct =][=
        IF (== (get "type") "char *")
    =]
    obj->[= (get "name") =] = strdup(data->values["[= (get "name") =]"]);[=
        ELIF (*== (get "type") "*")
    =]
    obj->[= (get "name") =]Count = data->values["[= (get "name") =]Count"];
    obj->[= (get "name") =] = malloc(sizeof([= (string-substitute (get "type") " *" "") =]) * obj->[= (get "name") =]Count);
    for (size_t i = 0; i < obj->[= (get "name") =]Count; i++)
        [= (string-substitute (get "type") " *" "") =]_parse(data->values["[= (get "name") =]"][i], &obj->[= (get "name") =][i]);[=
        ENDIF
    =][=
    ENDFOR struct
=]
}

void [= (. model) =]_free([= (. model) =] *obj) {[=
    FOR struct =][=
        IF (== (get "type") "char *")
    =]
    free(obj->[= (get "name") =]);[=
        ELIF (*== (get "type") "*")
    =]
    for (size_t i = 0; i < obj->[= (get "name") =]Count; i++)
        [= (string-substitute (get "type") " *" "") =]_free(&obj->[= (get "name") =][i]);
    free(obj->[= (get "name") =]);[=
        ENDIF
    =][=
    ENDFOR struct
=]
    free(obj);
}
[= ESAC =]

できます!

于 2014-06-09T12:53:01.953 に答える
0

解析されたデータをキーと値のペアとしてハッシュテーブルに保存し、エンティティを検索できるようにすることをお勧めします。

もちろん、要求された属性が利用できない場合(たとえば、url属性が欠落している場合)の対策を講じる必要があります。ハッシュテーブルに情報を格納する方法によっては、型の安全性の問題もあります。ただし、キーと値のペアを文字列として保存し、必要に応じて数値などに変換することは価値があるかもしれません。

于 2013-01-28T16:19:13.300 に答える