ocarina/include/core/database.hpp

172 lines
3.2 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>
database<T> :: database(std::string filepath, bool autosave)
: db_size(0), db_autosave(autosave)
{
file_init(&db_file, filepath.c_str(), 0);
}
template <class T>
database<T> :: ~database()
{
iterator it;
for (it = begin(); it != end(); it = next(it))
delete (*it);
}
template <class T>
void database<T> :: save()
{
if (file_open(&db_file, OPEN_WRITE) == false)
return;
file_writef(&db_file, "%u\n", actual_size());
for (unsigned int i = 0; i < db_entries.size(); i++) {
if (db_entries[i] == NULL)
file_writef(&db_file, "%d\n", false);
else {
file_writef(&db_file, "%d ", true);
db_entries[i]->write(db_file);
file_writef(&db_file, "\n");
}
}
file_close(&db_file);
}
template <class T>
void database<T> :: autosave()
{
if (db_autosave == true)
save();
}
template <class T>
void database<T> :: load()
{
unsigned int size;
std::string str;
int valid;
if (file_exists(&db_file) == false)
return;
else if (file_open(&db_file, OPEN_READ) == false)
return;
file_readf(&db_file, "%u", &size);
db_entries.resize(size);
for (unsigned int i = 0; i < size; i++) {
file_readf(&db_file, "%d", &valid);
if (valid == false) {
db_entries[i] = NULL;
} else {
db_entries[i] = new T;
db_entries[i]->_index = i;
db_entries[i]->read(db_file);
str = db_entries[i]->primary_key();
db_keys[str] = i;
db_size++;
}
}
file_close(&db_file);
}
template <class T>
T *database<T> :: insert(const T &item)
{
T *t = find(item.primary_key());
if (t != NULL)
return NULL;
t = new T(item);
t->_index = actual_size();
db_entries.push_back(t);
db_keys[t->primary_key()] = t->index();
db_size++;
autosave();
return t;
}
template <class T>
void database<T> :: remove(unsigned int index)
{
if (index >= actual_size())
return;
if (db_entries[index] == NULL)
return;
db_keys.erase(db_entries[index]->primary_key());
delete db_entries[index];
db_entries[index] = NULL;
db_size--;
autosave();
}
template <class T>
unsigned int database<T> :: size()
{
return db_size;
}
template <class T>
unsigned int database<T> :: actual_size()
{
return db_entries.size();
}
template <class T>
typename database<T>::iterator database<T> :: begin()
{
if (size() == 0)
return end();
iterator it = db_entries.begin();
if ( (*it) != NULL )
return it;
return next(it);
}
template <class T>
typename database<T>::iterator database<T> :: end()
{
return db_entries.end();
}
template <class T>
typename database<T>::iterator database<T> :: next(iterator &it)
{
do {
it++;
} while ((it != end()) && (*it) == NULL);
return it;
}
template <class T>
T *database<T> :: at(unsigned int index)
{
if (index >= actual_size())
return NULL;
return db_entries[index];
}
template <class T>
T *database<T> :: find(const std::string &key)
{
std::map<const std::string, unsigned int>::iterator it;
it = db_keys.find(key);
if (it == db_keys.end())
return NULL;
return db_entries[it->second];
}
#endif /* OCARINA_DATABASE_HPP */