ocarina/include/database.hpp

220 lines
3.9 KiB
C++
Raw Normal View History

/*
* 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
#include <error.h>
template <class T>
Database<T> :: Database(std::string filepath)
: _size(0), file(filepath, FILE_TYPE_DATA)
{
}
template <class T>
Database<T> :: ~Database()
{
}
template <class T>
void Database<T> :: save()
{
try {
file.open(OPEN_WRITE);
} catch (int error) {
return;
}
file << db.size() << std::endl;
for (unsigned int i = 0; i < db.size(); i++) {
file << db[i].valid << " ";
if (db[i].valid == true)
db[i].write(file);
file << std::endl;
}
file.close();
}
template <class T>
void Database<T> :: load()
{
unsigned int db_size;
if (file.exists() == false)
return;
try {
file.open(OPEN_READ);
} catch (int error) {
return;
}
file >> db_size;
db.resize(db_size);
for (unsigned int i = 0; i < db_size; i++) {
file >> db[i].valid;
if (db[i].valid == true) {
db[i].read(file);
keys.insert(std::pair<std::string, unsigned int>(db[i].primary_key(), i));
_size++;
}
}
file.close();
}
#ifdef CONFIG_TEST
template <class T>
void Database<T> :: clear()
{
db.clear();
keys.clear();
_size = 0;
}
template <class T>
void Database<T> :: print()
{
:: print("Allocated rows: %u\n", db.size());
:: print("Valid rows: %u\n", _size);
for (unsigned int i = 0; i < db.size(); i++) {
if (db[i].valid == true) {
:: print("db[%u] = ", i);
db[i].print();
:: print("\n");
}
}
}
template <class T>
void Database<T> :: print_keys()
{
std::map<const std::string, unsigned int>::iterator it;
:: print("Found keys:");
for (it = keys.begin(); it != keys.end(); it++)
:: print(" %s", it->first.c_str());
:: print("\n");
}
#endif /* CONFIG_TEST */
template <class T>
unsigned int Database<T> :: insert(T val)
{
unsigned int id;
typename std::map<const std::string, unsigned int>::iterator it;
it = keys.find(val.primary_key());
if (it != keys.end())
return it->second;
/*
* Check primary key stuff here
*/
id = db.size();
db.push_back(val);
keys.insert(std::pair<const std::string, unsigned int>(val.primary_key(), id));
db[id].valid = true;
_size++;
return id;
}
template <class T>
void Database<T> :: remove(unsigned int id)
{
keys.erase(db[id].primary_key());
db[id].valid = false;
_size--;
}
template <class T>
unsigned int Database<T> :: size()
{
return _size;
}
template <class T>
unsigned int Database<T> :: num_rows()
{
return db.size();
}
template <class T>
unsigned int Database<T> :: first()
{
for (unsigned int i = 0; i < db.size(); i++) {
if (db[i].valid == true)
return i;
}
return db.size();
}
template <class T>
unsigned int Database<T> :: last()
{
if (_size == 0)
return db.size();
for (unsigned int i = db.size() - 1; i >= 0; i--) {
if (db[i].valid == true)
return i;
}
return db.size();
}
template <class T>
unsigned int Database<T> :: next(unsigned int id)
{
for (unsigned int i = id + 1; i < db.size(); i++) {
if (db[i].valid == true)
return i;
}
return db.size();
}
template <class T>
bool Database<T> :: has_key(const std::string &key)
{
std::map<const std::string, unsigned int>::iterator it;
it = keys.find(key);
return it != keys.end();
}
template <class T>
unsigned int Database<T> :: find_index(const std::string &key)
{
std::map<const std::string, unsigned int>::iterator it;
it = keys.find(key);
if (it == keys.end())
throw -E_EXIST;
return it->second;
}
template <class T>
T &Database<T> :: find(const std::string &key)
{
unsigned int index = find_index(key);
if (db[index].valid == false)
throw -E_INVAL;
return db[index];
}
template <class T>
T &Database<T> :: operator[](unsigned int id)
{
if (id >= db.size())
throw -E_EXIST;
else if (db[id].valid == false)
throw -E_INVAL;
return db[id];
}
#endif /* OCARINA_DATABASE_HPP */