From e281286291176e1dfc286ae2c3c864dc5089d04e Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Tue, 4 Nov 2014 08:12:28 -0500 Subject: [PATCH] Database: Write more detailed documentation I transferred information from my DESIGN file and worked it into Doxygen comments. Signed-off-by: Anna Schumaker --- DESIGN | 134 -------------------------------------- include/core/database.h | 94 ++++++++++++++++++++------ include/core/database.hpp | 24 +++---- 3 files changed, 85 insertions(+), 167 deletions(-) diff --git a/DESIGN b/DESIGN index ac69dbbe..296f939e 100644 --- a/DESIGN +++ b/DESIGN @@ -66,140 +66,6 @@ Callbacks: -Database: - Databases are a generic store for information used by Ocarina. Users - need to inherit from a DatabaseEntry class (above) to properly use a - database. - - The Database class is a templated class, so code could potentially - get messy. Normal class declarations can still exist in the file - include/database.h and member functions are written in the file - include/database.hpp, which will be included by database.h. Any - function not relying on a template can be written in lib/database.cpp. - -- Automatic saving: - Databases can save automatically whenever a new value is inserted or - deleted. This will be more efficient for Databases that do not change - often but will be a huge performance hit for Databases that have many - changes at once. All databases will be loaded automatically from disk. - -- Primary keys: - Databases use the primary_key() function of a DatabaseEntry to enforce - uniqueness. This key is used when inserting a new value into the - Database, and will not be updated after. - -- Id: - The "id" field of a DatabaseEntry is also managed by the entry's - Database container It will be set to the entry's ID when the entry is - inserted into the database. - -- Database: - template - class Database { - private: - std::vector _db; - std::map _keys; - unsigned int _size; /* Number of valid rows */ - bool _autosave; - File _file; - - public: - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; - - Database(std::string, bool); - ~Database(); - void save(); - void load(); - - T *insert(const T &); - void remove(unsigned int); - unsigned int size(); - unsigned int actual_size(); - - iterator begin(); - iterator end(); - iterator next(iterator &); - - T *at(unsigned int); - T *find(const std::string &); - }; - -- File format: - File << db.size() << endl - File << INDEX_0 << db[INDEX_0].valid << db[INDEX_0] << endl; - File << INDEX_1 << db[INDEX_1].valid << db[INDEX_1] << endl; - ... - -- API: - Database :: Database(std::string filepath, bool autosave); - Initialize a database using "filepath" as a location to store - data on disk. If the file already exists, read the data into - the backing vector. - - Database :: ~Database(); - Delete all entries remaining in the database. - - void Database :: save(); - Save the database to disk. - - void Database :: load(); - Load the database from disk. - - T *Database :: insert(const T &item); - Look up the item in the _keys map. - If we find an item with the same key: - - Return NULL. - Otherwise: - - Use new to allocate memory for a new item. - - Add the new item to the end of the _db. - - Add the new item to _keys. - - Set new item.id to the index of the new item. - _ Increment _size. - - If autosave == true: save(). - - Return a pointer to the new item. - - unsigned int Database :: remove(unsigned int id); - - Remove the item from the _keys map. - - Delete _db[id] - - Set _db[id] = NULL - - If autosave == true: save(). - - Decrement _size. - - unsigned int Database :: size(); - return _size; - - unsigned int Database :: actual_size(); - return _db.size(); - - iterator Database :: begin(); - Return _db.end() if there are no valid entries - If the first entry is valid: - - return _db.begin(); - Otherwise: - - return an iterator to the first valid entry. - - iterator Database :: end(); - return _db.end(); - - iterator Database :: next(iterator &cur); - Return the next DatabaseEntry with valid == true or _db.end() - if there are no valid entries left. - - T *Database :: at(unsigned int i); - If i is beyond the end of the container: - Return NULL - Otherwise: - Return _db[i]; - - T *Database :: find(const std::string &key); - If key is in the _keys map: - Return a pointer to the corresponding entry. - Otherwise: - Return NULL; - - - Index: An index is a special database used to map a std::string key to multiple integer values. diff --git a/include/core/database.h b/include/core/database.h index 963d92b0..090351cc 100644 --- a/include/core/database.h +++ b/include/core/database.h @@ -61,15 +61,39 @@ public: /** - * Our custom database class. + * 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 + * + * + * The Database class will add a newline after each DatabaseEntry. */ template class Database { private: + /** Databases are backed by a std::vector. */ std::vector _db; + + /** Used for keeping track of primary keys. */ std::map _keys; + + /** The number of valid DatabaseEntries in the Database. */ unsigned int _size; + + /** Set to True if the Database should be saved when changed. */ bool _autosave; + + /** File object for reading and writing a Database. */ File _file; public: @@ -79,85 +103,113 @@ public: typedef typename std::vector::const_iterator const_iterator; /** - * Database constructor. + * Initialize a Database using filepath as a location to store data + * on disk. + * * @param filepath File on disk that will be written to. - * @param autosave True if database should be saved on every modification. + * @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. */ Database(std::string, bool); /** - * Database destructor. + * Deletes all remaining entries in a Database to prevent memory leaks. */ ~Database(); /** - * Called to write the database to disk. + * Called to save the Database to disk. */ void save(); /** - * Called to save the database after modifications. + * Called to save the Database to disk ONLY if Database::_autosave + * was set to True. */ void autosave(); /** - * Called to load the database from disk. + * Called to read the Database from disk. */ void load(); /** - * Add a new item to the database. + * 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. + * * @param item The new item to be added. - * @return A pointer to the item in the database. + * @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. */ T *insert(const T &); /** - * Remove an item from the database. + * 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 + * * @param index The index of the item that should be removed. */ void remove(unsigned int); /** - * Find the size of the database. - * @return The number of valid items in the database. + * Called to find the number of valid items in the Database. + * + * @return Database::_size */ unsigned int size(); /** - * Find the actual size of the backing vector. - * @return The number valid and invalid items in the database. + * Called to find the size of the backing std::vector. + * + * @return The size of Database::_db. */ unsigned int actual_size(); /** - * Returns an iterator pointing to the first entry in the database. + * @return An iterator pointing to the first valid entry in the Database. + * @return Return Database::end() if there are no valid entries. */ iterator begin(); /** - * Returns an iterator pointing past the end of the database. + * @return An iterator pointing past the end of the database. */ iterator end(); /** - * Returns an iterator pointing to the next valid item in the database. + * @return An iterator pointing to the next valid item in the database. */ iterator next(iterator &); /** - * Returns the database item at index n. - * @param n The database index to access. - * @return A valid DatabaseItem or NULL. + * 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. */ T *at(unsigned int); /** * Find a DatabaseItem with a specific primary key. + * * @param key The key to search for. - * @return A valid DatabaseItem or NULL. + * @return A pointer to the requested DatabaseEntry. + * @return NULL if there is no matching DatabaseEntry. */ T *find(const std::string &); }; diff --git a/include/core/database.hpp b/include/core/database.hpp index bef56d79..472faef4 100644 --- a/include/core/database.hpp +++ b/include/core/database.hpp @@ -79,14 +79,14 @@ void Database :: load() } template -T *Database :: insert(const T &val) +T *Database :: insert(const T &item) { - T *t = find(val.primary_key()); + T *t = find(item.primary_key()); if (t != NULL) return NULL; - t = new T(val); + t = new T(item); t->_index = actual_size(); _db.push_back(t); @@ -97,15 +97,15 @@ T *Database :: insert(const T &val) } template -void Database :: remove(unsigned int id) +void Database :: remove(unsigned int index) { - if (id >= actual_size()) + if (index >= actual_size()) return; - if (_db[id] == NULL) + if (_db[index] == NULL) return; - _keys.erase(_db[id]->primary_key()); - delete _db[id]; - _db[id] = NULL; + _keys.erase(_db[index]->primary_key()); + delete _db[index]; + _db[index] = NULL; _size--; autosave(); } @@ -150,11 +150,11 @@ typename Database::iterator Database :: next(iterator &it) } template -T *Database :: at(unsigned int id) +T *Database :: at(unsigned int index) { - if (id >= actual_size()) + if (index >= actual_size()) return NULL; - return _db[id]; + return _db[index]; } template