具有相互依赖的外键的结构上的gperf

时间:2019-02-17 23:12:16

标签: c foreign-keys bsearch gperf

我可能有很多静态数据,包括指向其他​​需要解析的静态数据的外键。我希望将数据文件作为常量编译到我的程序中。我编写了一个简单的C代码生成器,将类型信息作为输入,

Animal
string key
text description
~
Creature
string name
Animal animal
~

数据,

X
Neil
~
Animal
Bear
A bear is eating all the food.
.
Animal
Ostrich
An Ostrich is chilling.
.
Creature
Steve
Bear
Creature
Sam
Ostrich
Creature
Alice
Bear

并根据类型信息生成一个.h文件,

/** Auto-generated from ./ by Loader. */

#include <stddef.h> /* size_t */

/* These are datatypes that are loaded from ./. */

struct AutoAnimal;
struct AutoCreature;

struct AutoAnimal {
    const char *const key; /* key */
    const char *const description;
};

struct AutoCreature {
    const char *const name; /* key */
    const struct AutoAnimal *animal;
};

/* Search. */
struct AutoAnimal *AutoAnimalSearch(const char *const animal);
struct AutoCreature *AutoCreatureSearch(const char *const creature);

.c来自组合的类型信息和数据。例如,这会将Alice的外键解析为&auto_animal[0],即Bear

/** Auto-generated from ./ by Loader. */

#include <stdlib.h> /* bsearch */
#include <string.h> /* strcmp */
#include "x.h"

/*
 ./X.lore: "X" by Neil
*/

/* forward reference */
const struct AutoAnimal auto_animal[];
const struct AutoCreature auto_creature[];

/* loaded 5 lores */

const struct AutoAnimal auto_animal[] = {
    { "Bear", "A bear is eating all the food." },
    { "Ostrich", "An Ostrich is chilling." }
};
const int max_auto_animal = sizeof auto_animal / sizeof *auto_animal;

const struct AutoCreature auto_creature[] = {
    { "Alice", &auto_animal[0]/*Bear*/ },
    { "Sam", &auto_animal[1]/*Ostrich*/ },
    { "Steve", &auto_animal[0]/*Bear*/ }
};
const int max_auto_creature = sizeof auto_creature / sizeof *auto_creature;

static int animal_comp(const void *key, const void *elem) {
    const char *const k = key;
    const char *const e = ((const struct AutoAnimal *)elem)->key;
    return strcmp(k, e);
}

struct AutoAnimal *AutoAnimalSearch(const char *const key) {
    return bsearch(&key, auto_animal, max_auto_animal, sizeof *auto_animal, &animal_comp);
}

static int creature_comp(const char *const *key_ptr, const struct AutoCreature *elem) {
    const char *const k = *key_ptr;
    const char *const e = elem->name;
    return strcmp(k, e);
}

struct AutoCreature *AutoCreatureSearch(const char *const key) {
    return bsearch(&key, auto_creature, max_auto_creature, sizeof(struct AutoCreature), (int (*)(const void *, const void *))&creature_comp);
}

对输出进行排序,以便我可以在其上运行bsearch。如果我将程序与自动生成的源链接,

#include <stdlib.h>
#include <stdio.h>
#include "x.h"

int main(void) {
    const struct AutoCreature *creatures[] = {
        AutoCreatureSearch("Sam"),
        AutoCreatureSearch("Alice"),
        AutoCreatureSearch("Eve")
    }, **ac, **ac_end, *c;
    const size_t creatures_size = sizeof creatures / sizeof *creatures;
    for(ac = creatures, ac_end = creatures + creatures_size; ac < ac_end; ac++){
        if(!(c = *ac)) { printf("Creature is not on record.\n"); continue; }
        printf("Creature %s is a(n) %s. %s\n", c->name, c->animal->key,
            c->animal->description);
    }
    return EXIT_SUCCESS;
}

它给出了

Creature Sam is a(n) Ostrich. An Ostrich is chilling.
Creature Alice is a(n) Bear. A bear is eating all the food.
Creature is not on record.

但是,我不必搜索。我想在整个“数据库”上运行gperf,并在O(1)中获得结果。 gperf和我的加载器都输出了完成的C代码,但是我不知道另一个表中的位置就无法解析外键。有没有什么方法可以自动执行外键闭包和完善的哈希表,而无需为C编写成熟的解析器?

0 个答案:

没有答案