ocarina/include/core/database.hpp

171 lines
3.4 KiB
C++

/**
* Copyright 2013 (c) Anna Schumaker.
*
* DO NOT INCLUDE THIS FILE DIRECTLY. THIS IS A TEMPLATE DEFINITION FILE
* AND ONLY MEANT TO BE INCLUDED BY include/database.h!
*/
#ifndef OCARINA_DATABASE_HPP
#define OCARINA_DATABASE_HPP
template <class T>
void db_init(struct database<T> *db, const char *filepath, bool autosave)
{
db->db_size = 0;
db->db_autosave = autosave;
file_init(&db->db_file, filepath, 0);
}
template <class T>
void db_deinit(struct database<T> *db)
{
T *t, *u;
db_for_each(t, u, db) {
db->db_entries[t->index()] = NULL;
delete t;
db->db_size--;
}
}
template <class T>
void db_save(struct database<T> *db)
{
if (file_open(&db->db_file, OPEN_WRITE) == false)
return;
file_writef(&db->db_file, "%u\n", db_actual_size(db));
for (unsigned int i = 0; i < db_actual_size(db); i++) {
if (db->db_entries[i] == NULL)
file_writef(&db->db_file, "%d\n", false);
else {
file_writef(&db->db_file, "%d ", true);
db->db_entries[i]->write(db->db_file);
file_writef(&db->db_file, "\n");
}
}
file_close(&db->db_file);
}
template <class T>
void db_autosave(struct database<T> *db)
{
if (db->db_autosave == true)
db_save(db);
}
template <class T>
void db_load(struct database<T> *db)
{
unsigned int size;
std::string str;
int valid;
if (file_open(&db->db_file, OPEN_READ) == false)
return;
file_readf(&db->db_file, "%u", &size);
db->db_entries.resize(size);
for (unsigned int i = 0; i < size; i++) {
file_readf(&db->db_file, "%d", &valid);
if (valid == false) {
db->db_entries[i] = NULL;
} else {
db->db_entries[i] = new T;
db->db_entries[i]->_index = i;
db->db_entries[i]->read(db->db_file);
str = db->db_entries[i]->primary_key();
db->db_keys[str] = i;
db->db_size++;
}
}
file_close(&db->db_file);
}
template <class T>
T *db_insert(struct database<T> *db, T *item)
{
if (!item)
return NULL;
item->_index = db_actual_size(db);
db->db_entries.push_back(item);
db->db_keys[item->primary_key()] = item->index();
db->db_size++;
db_autosave(db);
return db->db_entries[item->_index];
}
template <class T>
void db_remove(struct database<T> *db, T *item)
{
if (item == NULL)
return;
if (db_at(db, item->index()) != item)
return;
db->db_entries[item->index()] = NULL;
db->db_keys.erase(item->primary_key());
delete item;
db->db_size--;
db_autosave(db);
}
template <class T>
unsigned int db_actual_size(const struct database<T> *db)
{
return db->db_entries.size();
}
template <class T>
T *__db_next(const struct database<T> *db, unsigned int index)
{
for (; index < db->db_entries.size(); index++) {
if (db->db_entries[index])
return db->db_entries[index];
}
return NULL;
}
template <class T>
T *db_first(const struct database<T> *db)
{
return __db_next(db, 0);
}
template <class T>
T *db_next(const struct database<T> *db, T *ent)
{
if (ent)
return __db_next(db, ent->index() + 1);
return NULL;
}
template <class T>
T *db_at(struct database<T> *db, unsigned int index)
{
if (index >= db_actual_size(db))
return NULL;
return db->db_entries[index];
}
template <class T>
T *db_get(struct database<T> *db, const gchar *key)
{
std::map<const std::string, unsigned int>::iterator it;
it = db->db_keys.find(key);
if (it == db->db_keys.end())
return NULL;
return db->db_entries[it->second];
}
template <class T>
T *db_find(struct database<T> *db, const gchar *key)
{
T *dbe = db_get(db, key);
if (dbe)
return dbe;
return db_insert(db, new T(key));
}
#endif /* OCARINA_DATABASE_HPP */