core/database: Replace constructors with a backwards pointer
This lets me use the struct db_entry without needing an inheritance system. Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
parent
4a4529b158
commit
8dfe818a7a
|
@ -7,13 +7,6 @@
|
|||
(struct db_entry *)g_ptr_array_index(db->db_entries, index)
|
||||
|
||||
|
||||
db_entry :: db_entry()
|
||||
: dbe_index(0), dbe_key(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
db_entry :: ~db_entry() {}
|
||||
|
||||
static void __dbe_free(struct database *db, struct db_entry *dbe)
|
||||
{
|
||||
if (dbe) {
|
||||
|
|
|
@ -15,11 +15,23 @@ extern "C" {
|
|||
struct db_entry {
|
||||
unsigned int dbe_index; /* The db_entry's position in the database. */
|
||||
gchar *dbe_key; /* The db_entry's hash key. */
|
||||
|
||||
db_entry(); /**< Initialize _index to 0. */
|
||||
virtual ~db_entry() = 0; /**< Virtual destructor */
|
||||
void *dbe_data; /* The db_entry's private data. */
|
||||
};
|
||||
|
||||
static inline void dbe_init(struct db_entry *dbe, void *data)
|
||||
{
|
||||
dbe->dbe_index = 0;
|
||||
dbe->dbe_key = NULL;
|
||||
dbe->dbe_data = data;
|
||||
}
|
||||
|
||||
static inline void *DBE_DATA(struct db_entry *dbe)
|
||||
{
|
||||
if (dbe)
|
||||
return dbe->dbe_data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct db_ops {
|
||||
/* Allocate a new struct db_entry from a given key. */
|
||||
|
|
|
@ -11,41 +11,46 @@
|
|||
/*
|
||||
* Derive a db_entry for storing integerss
|
||||
*/
|
||||
struct int_entry : public db_entry {
|
||||
unsigned int ie_val;
|
||||
|
||||
int_entry() : ie_val(0) {};
|
||||
int_entry(unsigned int v) : ie_val(v) {};
|
||||
struct int_entry {
|
||||
unsigned int ie_val;
|
||||
struct db_entry ie_dbe;
|
||||
};
|
||||
|
||||
#define INT_ENTRY(dbe) ((struct int_entry *)dbe)
|
||||
#define INT_ENTRY(dbe) ((struct int_entry *)DBE_DATA(dbe))
|
||||
static unsigned int test_free_count = 0;
|
||||
static unsigned int test_setup_count = 0;
|
||||
|
||||
static struct db_entry *int_alloc(const gchar *key)
|
||||
static struct int_entry *__int_alloc(unsigned int val)
|
||||
{
|
||||
struct int_entry *ent = new int_entry;
|
||||
sscanf(key, "%u", &ent->ie_val);
|
||||
ent->ie_val = val;
|
||||
dbe_init(&ent->ie_dbe, ent);
|
||||
return ent;
|
||||
}
|
||||
|
||||
static struct db_entry *int_alloc(const gchar *key)
|
||||
{
|
||||
unsigned int val;
|
||||
sscanf(key, "%u",&val);
|
||||
return &__int_alloc(val)->ie_dbe;
|
||||
}
|
||||
|
||||
static void int_free(struct db_entry *dbe)
|
||||
{
|
||||
test_free_count++;
|
||||
delete (struct int_entry *)dbe;
|
||||
delete INT_ENTRY(dbe);
|
||||
}
|
||||
|
||||
static gchar *int_key(struct db_entry *dbe)
|
||||
{
|
||||
struct int_entry *ent = (struct int_entry *)dbe;
|
||||
return g_strdup_printf("%u", ent->ie_val);
|
||||
return g_strdup_printf("%u", INT_ENTRY(dbe)->ie_val);
|
||||
}
|
||||
|
||||
static struct db_entry *int_read(struct file *f)
|
||||
{
|
||||
struct int_entry *ent = new int_entry;
|
||||
file_readf(f, "%u", &ent->ie_val);
|
||||
return ent;
|
||||
unsigned int val;
|
||||
file_readf(f, "%u", &val);
|
||||
return &__int_alloc(val)->ie_dbe;
|
||||
}
|
||||
|
||||
static void int_setup(struct db_entry *dbe)
|
||||
|
@ -55,8 +60,7 @@ static void int_setup(struct db_entry *dbe)
|
|||
|
||||
static void int_write(struct file *file, struct db_entry *dbe)
|
||||
{
|
||||
struct int_entry *ent = (struct int_entry *)dbe;
|
||||
file_writef(file, "%u", ent->ie_val);
|
||||
file_writef(file, "%u", INT_ENTRY(dbe)->ie_val);
|
||||
}
|
||||
|
||||
static const struct db_ops int_ops = {
|
||||
|
@ -74,29 +78,31 @@ static void test_db_entry()
|
|||
struct int_entry *ent;
|
||||
struct file f;
|
||||
|
||||
ent = (struct int_entry *)int_ops.dbe_alloc("1");
|
||||
test_equal(ent->dbe_index, 0);
|
||||
test_equal(ent->ie_val, 1);
|
||||
test_str_equal(int_ops.dbe_key(ent), "1");
|
||||
ent = INT_ENTRY(int_ops.dbe_alloc("1"));
|
||||
test_equal(ent->ie_dbe.dbe_index, 0);
|
||||
test_equal(ent->ie_dbe.dbe_data, ent);
|
||||
test_equal(ent->ie_val, 1);
|
||||
test_str_equal(int_ops.dbe_key(&ent->ie_dbe), "1");
|
||||
|
||||
file_init(&f, "test_db_entry", 0);
|
||||
file_open(&f, OPEN_WRITE);
|
||||
int_ops.dbe_write(&f, ent);
|
||||
int_ops.dbe_write(&f, &ent->ie_dbe);
|
||||
file_close(&f);
|
||||
|
||||
int_ops.dbe_free(ent);
|
||||
int_ops.dbe_free(&ent->ie_dbe);
|
||||
test_equal(test_free_count, 1);
|
||||
|
||||
file_open(&f, OPEN_READ);
|
||||
ent = (struct int_entry *)int_ops.dbe_read(&f);
|
||||
ent = INT_ENTRY(int_ops.dbe_read(&f));
|
||||
file_close(&f);
|
||||
|
||||
int_ops.dbe_setup(ent);
|
||||
int_ops.dbe_setup(&ent->ie_dbe);
|
||||
test_equal(ent->ie_dbe.dbe_data, ent);
|
||||
test_equal(ent->ie_val, 1);
|
||||
test_str_equal(int_ops.dbe_key(ent), "1");
|
||||
test_str_equal(int_ops.dbe_key(&ent->ie_dbe), "1");
|
||||
test_equal(test_setup_count, 1);
|
||||
|
||||
int_ops.dbe_free(ent);
|
||||
int_ops.dbe_free(&ent->ie_dbe);
|
||||
test_equal(test_free_count, 2);
|
||||
}
|
||||
|
||||
|
@ -121,11 +127,13 @@ static void test_stress(unsigned int N)
|
|||
{
|
||||
std::vector<struct int_entry *> ptrs;
|
||||
struct db_entry *dbe, *next;
|
||||
struct int_entry rmv(42);
|
||||
struct int_entry rmv;
|
||||
struct database db;
|
||||
unsigned int i;
|
||||
gchar *key;
|
||||
|
||||
rmv.ie_val = 42;
|
||||
rmv.ie_dbe.dbe_index = 0;
|
||||
test_free_count = 0;
|
||||
test_setup_count = 0;
|
||||
db_init(&db, "stress.db", false, &int_ops);
|
||||
|
@ -133,7 +141,7 @@ static void test_stress(unsigned int N)
|
|||
/* db_insert() */
|
||||
for (i = 0; i < N; i++) {
|
||||
key = g_strdup_printf("%u", i);
|
||||
dbe = db_insert(&db, new int_entry(i));
|
||||
dbe = db_insert(&db, &__int_alloc(i)->ie_dbe);
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_equal(dbe->dbe_index, i, i);
|
||||
test_loop_equal(dbe->dbe_key, key, i);
|
||||
|
@ -142,7 +150,7 @@ static void test_stress(unsigned int N)
|
|||
g_free(key);
|
||||
} test_loop_passed();
|
||||
|
||||
dbe = db_insert(&db, (struct int_entry *)NULL);
|
||||
dbe = db_insert(&db, NULL);
|
||||
test_equal(dbe, NULL);
|
||||
test_equal(db.db_size, N);
|
||||
test_equal(db_actual_size(&db), N);
|
||||
|
@ -152,7 +160,7 @@ static void test_stress(unsigned int N)
|
|||
for (i = 0; i < N; i++) {
|
||||
dbe = db_at(&db, i);
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_equal(dbe, ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe), ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe)->ie_val, i, i);
|
||||
} test_loop_passed();
|
||||
test_equal(db_at(&db, N), NULL);
|
||||
|
@ -163,7 +171,7 @@ static void test_stress(unsigned int N)
|
|||
dbe = db_get(&db, key);
|
||||
test_loop_not_equal(dbe, NULL, i);
|
||||
test_loop_str_equal(int_ops.dbe_key(dbe), key, i);
|
||||
test_loop_equal(dbe, ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe), ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe)->ie_val, i, i);
|
||||
g_free(key);
|
||||
} test_loop_passed();
|
||||
|
@ -179,7 +187,7 @@ static void test_stress(unsigned int N)
|
|||
test_loop_str_equal(int_ops.dbe_key(dbe), key, i);
|
||||
test_loop_equal(INT_ENTRY(dbe)->ie_val, i, i);
|
||||
if (i < N)
|
||||
test_loop_equal(dbe, ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe), ptrs.at(i), i);
|
||||
g_free(key);
|
||||
} test_loop_passed();
|
||||
test_equal(db.db_size, N + 1);
|
||||
|
@ -190,11 +198,11 @@ static void test_stress(unsigned int N)
|
|||
key = g_strdup_printf("%u", i);
|
||||
dbe = db_get(&db, key);
|
||||
db_remove(&db, dbe);
|
||||
test_loop_equal(db_at(&db, i), NULL, i);
|
||||
test_loop_equal(db_get(&db, key), NULL, i);
|
||||
test_loop_equal(INT_ENTRY(db_at(&db, i)), NULL, i);
|
||||
test_loop_equal(INT_ENTRY(db_get(&db, key)), NULL, i);
|
||||
g_free(key);
|
||||
} test_loop_passed();
|
||||
db_remove(&db, &rmv);
|
||||
db_remove(&db, &rmv.ie_dbe);
|
||||
test_equal(db.db_size, N / 2);
|
||||
test_equal(db_actual_size(&db), N + 1);
|
||||
test_equal(test_free_count, (N / 2) + 1);
|
||||
|
@ -209,7 +217,7 @@ static void test_stress(unsigned int N)
|
|||
test_loop_not_equal(next, NULL, i);
|
||||
test_loop_equal(INT_ENTRY(next)->ie_val, i + 2, i);
|
||||
}
|
||||
test_loop_equal(dbe, ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe), ptrs.at(i), i);
|
||||
test_loop_equal(INT_ENTRY(dbe)->ie_val, i, i);
|
||||
test_loop_equal(db_next(&db, dbe), next, i);
|
||||
i += 2;
|
||||
|
@ -239,7 +247,7 @@ static void test_save_load()
|
|||
|
||||
/* 10 items should "autosave" when inserted */
|
||||
for (i = 0; i < N; i++)
|
||||
db_insert(&db1, new int_entry(i));
|
||||
db_insert(&db1, &__int_alloc(i)->ie_dbe);
|
||||
|
||||
i = 0;
|
||||
db_load(&db2);
|
||||
|
@ -271,7 +279,7 @@ static void test_save_load()
|
|||
/* Manually turn autosave off. */
|
||||
db1.db_autosave = false;
|
||||
for (i = N; i < (2 * N); i++)
|
||||
db_insert(&db1, new int_entry(i));
|
||||
db_insert(&db1, &__int_alloc(i)->ie_dbe);
|
||||
for (i = N; i < (2 * N); i += 2)
|
||||
db_remove(&db1, db_at(&db1, i));
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ static void test_track()
|
|||
library = library_find("tests/Music");
|
||||
|
||||
track = new struct track("0/Hyrule Symphony/01 - Title Theme.ogg");
|
||||
track->dbe_index = 0;
|
||||
track_ops->dbe_setup(track);
|
||||
test_verify_track(track);
|
||||
test_equal(library->li_size, 1);
|
||||
|
@ -112,12 +113,14 @@ static void test_track()
|
|||
|
||||
file_open(&f, OPEN_READ);
|
||||
track = (struct track *)track_ops->dbe_read(&f);
|
||||
track->dbe_index = 0;
|
||||
track_ops->dbe_setup(track);
|
||||
test_verify_notrack(track);
|
||||
test_equal(library->li_size, 1);
|
||||
track_ops->dbe_free(track);
|
||||
|
||||
track = (struct track *)track_ops->dbe_read(&f);
|
||||
track->dbe_index = 0;
|
||||
track_ops->dbe_setup(track);
|
||||
test_verify_track(track);
|
||||
test_equal(library->li_size, 1);
|
||||
|
|
Loading…
Reference in New Issue