2014-10-17 17:15:02 -04:00
|
|
|
/**
|
2013-08-10 23:38:57 -04:00
|
|
|
* Copyright 2013 (c) Anna Schumaker.
|
|
|
|
*/
|
2014-06-21 09:37:47 -04:00
|
|
|
#ifndef OCARINA_CORE_DATABASE_H
|
|
|
|
#define OCARINA_CORE_DATABASE_H
|
2013-08-10 23:38:57 -04:00
|
|
|
|
2015-10-09 13:55:34 -04:00
|
|
|
extern "C" {
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/file.h>
|
2015-10-09 13:55:34 -04:00
|
|
|
}
|
2013-08-10 23:38:57 -04:00
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
/**
|
2014-11-02 09:29:13 -05:00
|
|
|
* The DatabaseEntry class is the base class for storing
|
|
|
|
* generic data inside a Database.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2015-10-31 11:44:29 -04:00
|
|
|
struct db_entry {
|
|
|
|
unsigned int dbe_index; /* The db_entry's position in the database. */
|
2015-09-23 09:33:55 -04:00
|
|
|
gchar *dbe_key; /* The db_entry's hash key. */
|
2015-11-05 15:39:17 -05:00
|
|
|
void *dbe_data; /* The db_entry's private data. */
|
2013-08-11 20:18:51 -04:00
|
|
|
};
|
|
|
|
|
2015-11-05 15:39:17 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-11 20:18:51 -04:00
|
|
|
|
2015-11-03 10:39:06 -05:00
|
|
|
struct db_ops {
|
2015-11-02 16:59:55 -05:00
|
|
|
/* Allocate a new struct db_entry from a given key. */
|
|
|
|
struct db_entry *(*dbe_alloc)(const gchar *);
|
2015-09-30 09:15:15 -04:00
|
|
|
|
|
|
|
/* Free a struct db_entry. */
|
|
|
|
void (*dbe_free)(struct db_entry *);
|
2015-10-05 20:12:32 -04:00
|
|
|
|
2015-09-23 09:33:55 -04:00
|
|
|
/* Return a unique string representing a single struct db_entry. */
|
|
|
|
gchar *(*dbe_key)(struct db_entry *);
|
|
|
|
|
2015-09-22 09:24:19 -04:00
|
|
|
/* Read a single struct db_entry from disk. */
|
|
|
|
struct db_entry *(*dbe_read)(struct file *);
|
|
|
|
|
2015-10-05 20:12:32 -04:00
|
|
|
/* Set up a struct db_entry after adding to the database. */
|
|
|
|
void (*dbe_setup)(struct db_entry *);
|
2015-09-22 15:54:21 -04:00
|
|
|
|
|
|
|
/* Write a single struct db_entry to disk. */
|
|
|
|
void (*dbe_write)(struct file *, struct db_entry *);
|
2015-11-03 10:39:06 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Databases are a generic store for information used by Ocarina. Users
|
|
|
|
* need to inherit from a DatabaseEntry class to properly use a Database.
|
|
|
|
*
|
|
|
|
* When writing a Database to disk, Databases need to store their size in
|
|
|
|
* addition to values and valid bits at each index. For example, let's say
|
|
|
|
* we have a Database with the following values: { 1, 2, NULL, 4 }. On
|
|
|
|
* disk this would look like:
|
|
|
|
*
|
|
|
|
* 4
|
|
|
|
* 0 true 1
|
|
|
|
* 1 true 2
|
|
|
|
* 2 false
|
|
|
|
* 3 true 4
|
|
|
|
* <index> <valid> <data>
|
|
|
|
*
|
|
|
|
* The Database class will add a newline after each DatabaseEntry.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2015-10-17 10:07:58 -04:00
|
|
|
struct database {
|
|
|
|
unsigned int db_size; /* The database's count of valid entries. */
|
|
|
|
bool db_autosave; /* True if the database saves when changed. */
|
|
|
|
struct file db_file; /* The database's associated file object. */
|
2015-11-05 11:56:47 -05:00
|
|
|
GPtrArray *db_entries; /* The database's backing array. */
|
2015-11-05 14:19:33 -05:00
|
|
|
GHashTable *db_keys; /* The database's mapping of key -> value. */
|
2014-11-04 08:12:28 -05:00
|
|
|
|
2015-11-03 10:39:06 -05:00
|
|
|
const struct db_ops *db_ops; /* The database's operations vector. */
|
2015-09-21 09:02:13 -04:00
|
|
|
};
|
2014-11-04 08:12:28 -05:00
|
|
|
|
2014-03-09 14:58:06 -04:00
|
|
|
|
2015-09-21 09:02:13 -04:00
|
|
|
/*
|
|
|
|
* Initialize a database using filepath as a location on disk to store data
|
|
|
|
* and autosave as a hint for if this database should be automatically saved.
|
|
|
|
*/
|
2015-11-04 12:23:00 -05:00
|
|
|
void db_init(struct database *, const char *, bool, const struct db_ops *);
|
2014-10-17 17:15:02 -04:00
|
|
|
|
2015-09-21 09:02:13 -04:00
|
|
|
/* Called to prevent memory leaks by freeing all remaining database entries. */
|
2015-11-04 12:23:00 -05:00
|
|
|
void db_deinit(struct database *);
|
2013-08-10 23:38:57 -04:00
|
|
|
|
2015-10-18 10:11:24 -04:00
|
|
|
/* Called to write the database to disk. */
|
2015-11-04 12:23:00 -05:00
|
|
|
void db_save(struct database *);
|
2015-10-18 10:11:24 -04:00
|
|
|
|
|
|
|
/* Save the database to disk iff database->db_autosave is set to True */
|
2015-11-04 12:23:00 -05:00
|
|
|
void db_autosave(struct database *);
|
2015-10-18 10:11:24 -04:00
|
|
|
|
2015-09-17 08:12:25 -04:00
|
|
|
/* Called to read the database from disk. */
|
2015-11-04 12:23:00 -05:00
|
|
|
void db_load(struct database *);
|
2015-09-17 08:12:25 -04:00
|
|
|
|
2015-10-17 15:12:40 -04:00
|
|
|
/* Returns the size of the backing std::vector. */
|
2015-11-04 12:23:00 -05:00
|
|
|
unsigned int db_actual_size(const struct database *);
|
2015-10-17 15:12:40 -04:00
|
|
|
|
2015-10-18 10:59:20 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Called to add a new item to the database. The caller MUST check if the
|
|
|
|
* database already contains a similar item before calling this function.
|
|
|
|
*/
|
2015-11-04 12:23:00 -05:00
|
|
|
struct db_entry *db_insert(struct database *, struct db_entry *);
|
2015-10-18 10:59:20 -04:00
|
|
|
|
2015-10-20 08:05:13 -04:00
|
|
|
/* Called to remove an item from the database. */
|
2015-11-04 12:23:00 -05:00
|
|
|
void db_remove(struct database *, struct db_entry *);
|
2015-10-18 10:59:20 -04:00
|
|
|
|
2015-10-20 08:19:47 -04:00
|
|
|
|
|
|
|
/* Returns the database item at the requested index. */
|
2015-11-04 12:23:00 -05:00
|
|
|
struct db_entry *db_at(struct database *, unsigned int);
|
2015-10-20 08:19:47 -04:00
|
|
|
|
2015-10-20 10:10:26 -04:00
|
|
|
/* Returns the database item with the specified key. */
|
2015-11-04 12:23:00 -05:00
|
|
|
struct db_entry *db_get(struct database *, const gchar *);
|
2015-10-20 10:10:26 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Similar to db_get(), but allocate and return a new item if the
|
|
|
|
* database doesn't contain an item with the specified key.
|
|
|
|
*/
|
2015-11-04 12:23:00 -05:00
|
|
|
struct db_entry *db_find(struct database *, const gchar *);
|
2015-10-20 10:10:26 -04:00
|
|
|
|
2015-09-18 09:37:48 -04:00
|
|
|
/* Returns the first valid database item. */
|
2015-11-04 12:23:00 -05:00
|
|
|
struct db_entry *db_first(const struct database *);
|
2015-09-18 09:37:48 -04:00
|
|
|
|
|
|
|
/* Returns the next valid database item. */
|
2015-11-04 12:23:00 -05:00
|
|
|
struct db_entry *db_next(const struct database *, struct db_entry *);
|
2015-09-18 09:37:48 -04:00
|
|
|
|
|
|
|
|
|
|
|
#define db_for_each(ent, next, db) \
|
|
|
|
for (ent = db_first(db), next = db_next(db, ent); \
|
|
|
|
ent != NULL; \
|
|
|
|
ent = next, next = db_next(db, ent))
|
|
|
|
|
2014-06-21 09:37:47 -04:00
|
|
|
#endif /* OCARINA_CORE_DATABASE_H */
|