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
|
|
|
|
2014-06-05 10:19:22 -04:00
|
|
|
#include <core/file.h>
|
2013-08-10 23:38:57 -04:00
|
|
|
|
2013-11-27 16:34:31 -05:00
|
|
|
#include <map>
|
2013-08-11 10:41:22 -04:00
|
|
|
#include <vector>
|
|
|
|
|
2014-11-02 10:02:35 -05:00
|
|
|
template<class T> class Database;
|
2013-08-11 20:18:51 -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
|
|
|
*/
|
2013-08-11 20:18:51 -04:00
|
|
|
class DatabaseEntry {
|
2014-11-02 10:02:35 -05:00
|
|
|
private:
|
|
|
|
template <class T> friend class Database;
|
|
|
|
unsigned int _index; /**< The location of an item in the Database. */
|
2013-08-11 20:18:51 -04:00
|
|
|
|
2014-11-02 10:02:35 -05:00
|
|
|
public:
|
|
|
|
DatabaseEntry(); /**< Initialize _index to 0. */
|
2014-11-02 09:29:13 -05:00
|
|
|
virtual ~DatabaseEntry() = 0; /**< Virtual destructor */
|
2014-10-17 17:15:02 -04:00
|
|
|
|
2014-11-02 10:02:35 -05:00
|
|
|
/**
|
|
|
|
* Called to access a DatabaseEntry's index.
|
|
|
|
*
|
|
|
|
* @return DatabaseEntry::_index
|
|
|
|
*/
|
|
|
|
const unsigned int index();
|
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
/**
|
2014-11-02 09:29:13 -05:00
|
|
|
* The primary key of a DatabaseEntry is a unique string representing
|
|
|
|
* a single DatabaseEntry instance. This is used for preventing
|
|
|
|
* duplicate entries in a Database. The primary key is not expected
|
|
|
|
* to change once a DatabaseEntry has been initialized.
|
|
|
|
*
|
|
|
|
* @return A unique string identifying a DatabaseEntry instance.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-25 17:51:37 -04:00
|
|
|
virtual const std::string primary_key() const = 0;
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-02 09:29:13 -05:00
|
|
|
* This function is called by the Database to write a specific
|
|
|
|
* DatabaseEntry instance to disk.
|
|
|
|
*
|
2014-10-17 17:15:02 -04:00
|
|
|
* @param file File to use when writing data.
|
|
|
|
*/
|
2013-08-14 21:09:11 -04:00
|
|
|
virtual void write(File &) = 0;
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-02 09:29:13 -05:00
|
|
|
* This function is called by the Database to read a single
|
|
|
|
* DatabaseEntry instance from disk.
|
|
|
|
*
|
2014-10-17 17:15:02 -04:00
|
|
|
* @param file File to use when reading data.
|
|
|
|
*/
|
2013-08-14 21:09:11 -04:00
|
|
|
virtual void read(File &) = 0;
|
2013-08-11 20:18:51 -04: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
|
|
|
*/
|
2013-12-30 18:18:23 -05:00
|
|
|
template <class T>
|
2013-08-10 23:38:57 -04:00
|
|
|
class Database {
|
2013-08-11 10:41:22 -04:00
|
|
|
private:
|
2014-11-04 08:12:28 -05:00
|
|
|
/** Databases are backed by a std::vector. */
|
2014-03-25 10:57:09 -04:00
|
|
|
std::vector<T *> _db;
|
2014-11-04 08:12:28 -05:00
|
|
|
|
|
|
|
/** Used for keeping track of primary keys. */
|
2014-03-09 14:58:06 -04:00
|
|
|
std::map<const std::string, unsigned int> _keys;
|
2014-11-04 08:12:28 -05:00
|
|
|
|
|
|
|
/** The number of valid DatabaseEntries in the Database. */
|
2013-08-11 10:41:22 -04:00
|
|
|
unsigned int _size;
|
2014-11-04 08:12:28 -05:00
|
|
|
|
|
|
|
/** Set to True if the Database should be saved when changed. */
|
2014-03-09 14:58:06 -04:00
|
|
|
bool _autosave;
|
2014-11-04 08:12:28 -05:00
|
|
|
|
|
|
|
/** File object for reading and writing a Database. */
|
2014-03-09 14:58:06 -04:00
|
|
|
File _file;
|
|
|
|
|
2013-08-11 10:41:22 -04:00
|
|
|
public:
|
2014-10-17 17:15:02 -04:00
|
|
|
/** Iterator access for our backing std::vector */
|
2014-03-25 10:57:09 -04:00
|
|
|
typedef typename std::vector<T *>::iterator iterator;
|
2014-10-17 17:15:02 -04:00
|
|
|
/** Const iterator access for our backing std::vector */
|
2014-03-25 10:57:09 -04:00
|
|
|
typedef typename std::vector<T *>::const_iterator const_iterator;
|
2014-03-09 14:58:06 -04:00
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Initialize a Database using filepath as a location to store data
|
|
|
|
* on disk.
|
|
|
|
*
|
2014-10-17 17:15:02 -04:00
|
|
|
* @param filepath File on disk that will be written to.
|
2014-11-04 08:12:28 -05:00
|
|
|
* @param autosave Set to True if the Database should be saved upon
|
|
|
|
* every insertion and deletion. If this is set
|
|
|
|
* to False then the Database will have to be saved
|
|
|
|
* manually.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-09 14:58:06 -04:00
|
|
|
Database(std::string, bool);
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Deletes all remaining entries in a Database to prevent memory leaks.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2013-08-11 10:41:22 -04:00
|
|
|
~Database();
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to save the Database to disk.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2013-08-14 21:09:11 -04:00
|
|
|
void save();
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to save the Database to disk ONLY if Database::_autosave
|
|
|
|
* was set to True.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-12 20:23:34 -04:00
|
|
|
void autosave();
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to read the Database from disk.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2013-08-14 21:09:11 -04:00
|
|
|
void load();
|
2013-08-10 23:38:57 -04:00
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to add a new item to the Database. Upon successful insertion,
|
|
|
|
* this function will:
|
|
|
|
* -# Allocate a new DatabaseEntry instance.
|
|
|
|
* -# Set the DatabaseEntry::_index field to the size of Database::_db.
|
|
|
|
* -# Add the new DatabaseEntry to the end of Database::_db.
|
|
|
|
* -# Increment Database::_size.
|
|
|
|
* -# Call Database::autosave() to commit changes.
|
|
|
|
*
|
2014-10-17 17:15:02 -04:00
|
|
|
* @param item The new item to be added.
|
2014-11-04 08:12:28 -05:00
|
|
|
* @return If Database::_keys already contains an instance with the
|
|
|
|
* same DatabaseEntry::primary_key(), then return NULL.
|
|
|
|
* @return Otherwise, return a pointer to the new instance stored
|
|
|
|
* in the Database.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-25 17:51:37 -04:00
|
|
|
T *insert(const T &);
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to remove an item from the Database. This function will:
|
|
|
|
* -# Delete memory allocated for the DatabaseEntry
|
|
|
|
* -# Set Database::_db[index] = NULL
|
|
|
|
* -# Decrement Database::_size
|
|
|
|
* -# Call Database::autosave() to commit changes
|
|
|
|
*
|
2014-10-17 17:15:02 -04:00
|
|
|
* @param index The index of the item that should be removed.
|
|
|
|
*/
|
2013-08-11 21:09:11 -04:00
|
|
|
void remove(unsigned int);
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to find the number of valid items in the Database.
|
|
|
|
*
|
|
|
|
* @return Database::_size
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2013-08-11 20:18:51 -04:00
|
|
|
unsigned int size();
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Called to find the size of the backing std::vector.
|
|
|
|
*
|
|
|
|
* @return The size of Database::_db.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-09 14:58:06 -04:00
|
|
|
unsigned int actual_size();
|
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* @return An iterator pointing to the first valid entry in the Database.
|
|
|
|
* @return Return Database::end() if there are no valid entries.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-09 14:58:06 -04:00
|
|
|
iterator begin();
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* @return An iterator pointing past the end of the database.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-09 14:58:06 -04:00
|
|
|
iterator end();
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* @return An iterator pointing to the next valid item in the database.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-09 14:58:06 -04:00
|
|
|
iterator next(iterator &);
|
|
|
|
|
2014-10-17 17:15:02 -04:00
|
|
|
/**
|
2014-11-04 08:12:28 -05:00
|
|
|
* Returns the database item at the requested index.
|
|
|
|
*
|
|
|
|
* @param index The database index to access.
|
|
|
|
* @return A pointer to the requested DatabaseEntry.
|
|
|
|
* @return NULL if there is no valid DatabaseEntry at the requested index.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-24 19:51:13 -04:00
|
|
|
T *at(unsigned int);
|
2014-10-17 17:15:02 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Find a DatabaseItem with a specific primary key.
|
2014-11-04 08:12:28 -05:00
|
|
|
*
|
2014-10-17 17:15:02 -04:00
|
|
|
* @param key The key to search for.
|
2014-11-04 08:12:28 -05:00
|
|
|
* @return A pointer to the requested DatabaseEntry.
|
|
|
|
* @return NULL if there is no matching DatabaseEntry.
|
2014-10-17 17:15:02 -04:00
|
|
|
*/
|
2014-03-24 19:51:13 -04:00
|
|
|
T *find(const std::string &);
|
2013-08-10 23:38:57 -04:00
|
|
|
};
|
|
|
|
|
2013-08-11 10:41:22 -04:00
|
|
|
#include "database.hpp"
|
|
|
|
|
2014-06-21 09:37:47 -04:00
|
|
|
#endif /* OCARINA_CORE_DATABASE_H */
|