acd8bd7b23
- Force the primary key to be a string - Throw error codes rather than 0 Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
170 lines
5.0 KiB
Plaintext
170 lines
5.0 KiB
Plaintext
== Files ==
|
|
ocarina/include/
|
|
database.h
|
|
database.hpp
|
|
ocarina/lib/
|
|
database.cpp
|
|
|
|
== Depends ==
|
|
file
|
|
|
|
Database: (lib/database.cpp)
|
|
Ocarina 5.x created a different save file format for each type of
|
|
data that needed to be stored (preferences, library paths, playlists).
|
|
I intend to unify everything into a generic file format that can be
|
|
accessed through a generic database interface. The database code will
|
|
be in charge of printing the "valid" bit for each DatabaseEntry so that
|
|
child classes do not need to call into the parent class. If valid ==
|
|
true, the DatabaseEntry will be streamed out followed by a newline. If
|
|
valid == false the database will print the next entry in the vector.
|
|
|
|
Modules should inherit from the DatabasEntry class and implement their
|
|
own read() and write() functions. The "valid" field will be stored
|
|
before these functions are called, and the entry will be skipped if
|
|
valid is set to false.
|
|
|
|
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 can be 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.
|
|
|
|
- DatabaseEntry:
|
|
class DatabaseEntry { /* let database modify valid flag */
|
|
public:
|
|
const std::string primary_key;
|
|
bool valid;
|
|
|
|
DatabaseEntry(const std::string &);
|
|
virtual void write(File &) = 0;
|
|
virtual void read(File &) = 0;
|
|
virtual void print() = 0;
|
|
};
|
|
|
|
File << <CHILD_CLASS_DATA>
|
|
|
|
- IndexEntry:
|
|
class IndexEntry : public DatabaseEntry {
|
|
public:
|
|
set<unsigned int> values;
|
|
|
|
void write(File &);
|
|
void read(File &);
|
|
void print();
|
|
void insert(unsigned int);
|
|
void remove(unsigned int);
|
|
};
|
|
|
|
File << key << endl;
|
|
File << values.size() << values[0] << .. << values[N] << endl;
|
|
|
|
- Database:
|
|
template <class T>
|
|
class Database {
|
|
private:
|
|
vector<T> db;
|
|
map<std::string, unsigned int> keys;
|
|
unsigned int _size; /* Number of valid rows */
|
|
File file;
|
|
|
|
public:
|
|
Database::Database(filename, flags);
|
|
void load();
|
|
void save();
|
|
void clear();
|
|
void print();
|
|
void print_keys();
|
|
|
|
unsigned int insert(T);
|
|
void remove(unsigned int);
|
|
unsigned int size();
|
|
unsigned int num_rows();
|
|
|
|
unsigned int first();
|
|
unsigned int last();
|
|
unsigned int next(unsigned int &);
|
|
bool has_key(const std :: string &);
|
|
unsigned int find_index(const std::string &);
|
|
T &find(const std::string &);
|
|
T &operator[](unsigned int);
|
|
};
|
|
|
|
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(filename, flags);
|
|
Initializes database to use ~/.ocarina{-debug}/filename.
|
|
Set up flags.
|
|
|
|
void Database :: load();
|
|
Reads a saved database from disk.
|
|
|
|
void Database :: save();
|
|
Saves the database to disk.
|
|
|
|
void Database :: clear();
|
|
This function exists only if CONFIG_TEST is enabled.
|
|
Clear the database contents in-memory, but do NOT write
|
|
to disk.
|
|
|
|
void Database :: print();
|
|
This function exists only If CONFIG_TEST is enabled.
|
|
Following a similar format for writing to disk, print the
|
|
database to the console in a human-readable format.
|
|
|
|
void Database :: print_keys();
|
|
This function exists only if CONFIG_TEST is enabled.
|
|
Print out the collected primary keys in the database.
|
|
|
|
template <class T>
|
|
unsigned int Database :: insert(T &);
|
|
Adds a new item to the db and marks it as valid. A reverse
|
|
mapping is also created into the keys map to map the primary
|
|
key back to the id of the newly added item.
|
|
|
|
void Database :: remove(unsigned int index);
|
|
Mark db[index] as invalid (quick deletion).
|
|
|
|
unsigned int Database :: size();
|
|
Returns number of valid rows in the database.
|
|
|
|
unsigned int Database :: num_rows();
|
|
Return db.size().
|
|
|
|
unsigned int Database :: first();
|
|
Return the id to the first valid row. Return db.size() if
|
|
there are no valid rows.
|
|
|
|
unsigned int Database :: last();
|
|
Return the id of the last valid row. Return db.size() if
|
|
there are no valid rows.
|
|
|
|
unsigned int Database :: next(unsigned int &id);
|
|
Return the id of the next valid row or return db.size() if
|
|
there are no valid rows.
|
|
|
|
bool Database :: has_key(const std::string &key);
|
|
Return true if an item with primary key "key" exists in the
|
|
database, and false otherwise.
|
|
|
|
unsigned int Database :: find_index(const std::string key);
|
|
If the key exists in the database, return the index of the
|
|
database item with that key. Throw -EEXIST if the key is not
|
|
in the database.
|
|
|
|
template <class T>
|
|
T &Database :: find(const std::string &key);
|
|
Search for primary key "key" in the database. The reverse
|
|
mapping should be used to make this operation faster.
|
|
Throw -EEXIST if the key is not found in the mapping.
|
|
Throw -EINVAL if the key points to an invalid entry.
|
|
|
|
template <class T>
|
|
T &Database :: operator[](unsigned int index);
|
|
Return a reference to db[index].
|
|
Throw -EEXIST if index is out of range.
|
|
Throw -EINVAL if index is invalid.
|