/** * Copyright 2013 (c) Anna Schumaker. */ #ifndef OCARINA_CORE_DATABASE_H #define OCARINA_CORE_DATABASE_H extern "C" { #include } #include #include #include /** * The DatabaseEntry class is the base class for storing * generic data inside a Database. */ class DatabaseEntry { public: unsigned int _index; /**< The location of an item in the Database. */ DatabaseEntry(); /**< Initialize _index to 0. */ DatabaseEntry(const std::string); virtual ~DatabaseEntry() = 0; /**< Virtual destructor */ /** * Called to access a DatabaseEntry's index. * * @return DatabaseEntry::_index */ const unsigned int index(); /** * 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. */ virtual const std::string primary_key() const = 0; /** * This function is called by the Database to write a specific * DatabaseEntry instance to disk. * * @param file File to use when writing data. */ virtual void write(file &) = 0; /** * This function is called by the Database to read a single * DatabaseEntry instance from disk. * * @param file File to use when reading data. */ virtual void read(file &) = 0; }; /** * 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 struct database { unsigned int db_size; /* The database's count of valid entries. */ bool db_autosave; /* True if the database saves when changed. */ struct file db_file; /* The database's associated file object. */ std::vector db_entries; std::map db_keys; /** * 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 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); /** * Deletes all remaining entries in a Database to prevent memory leaks. */ ~database(); }; /* Called to write the database to disk. */ template void db_save(struct database *); /* Save the database to disk iff database->db_autosave is set to True */ template void db_autosave(struct database *); /* Called to read the database from disk. */ template void db_load(struct database *); /* Returns the size of the backing std::vector. */ template unsigned int db_actual_size(const struct database *); /* * Called to add a new item to the database. The caller MUST check if the * database already contains a similar item before calling this function. */ template T *db_insert(struct database *, T *); /* Called to remove an item from the database. */ template void db_remove(struct database *, T *); /* Returns the database item at the requested index. */ template T *db_at(struct database *, unsigned int); /* Returns the database item with the specified key. */ template T *db_get(struct database *, const gchar *); /* * Similar to db_get(), but allocate and return a new item if the * database doesn't contain an item with the specified key. */ template T *db_find(struct database *, const gchar *); /* Returns the first valid database item. */ template T *db_first(const struct database *); /* Returns the next valid database item. */ template T *db_next(const struct database *, T *); #define db_for_each(ent, next, db) \ for (ent = db_first(db), next = db_next(db, ent); \ ent != NULL; \ ent = next, next = db_next(db, ent)) #include "database.hpp" #endif /* OCARINA_CORE_DATABASE_H */