From 50a7c3dae686ee033262b13a2b7595a724c017fd Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Sun, 11 Aug 2013 20:18:51 -0400 Subject: [PATCH] database: Add funcions for database iteration A database may have invalid rows. If this is the case, then the next() function needs to return the id of the next valid row. I'm aware that this could get horribly inefficient on large DBs with many invalid rows. I don't expect people to delete large chunks of music all at once, but a defragment tool is on my "todo" list for a future Ocarina version. Signed-off-by: Anna Schumaker --- design/database.txt | 33 +++++++++++++++++++++----- include/database.h | 17 +++++++++++++- include/database.hpp | 47 ++++++++++++++++++++++++++++++++++++- lib/database.cpp | 4 ++++ tests/database/database.cpp | 42 ++++++++++++++++++++++++++------- 5 files changed, 126 insertions(+), 17 deletions(-) diff --git a/design/database.txt b/design/database.txt index cfd8cd19..4ef557a7 100644 --- a/design/database.txt +++ b/design/database.txt @@ -52,9 +52,15 @@ Database: (lib/database.cpp) Database::Database(filename); void load(); void save(); + unsigned int insert(T); void delete(unsigned int); - const unsigned int &size(); + unsigned int size(); + unsigned int num_rows(); + + unsigned int first(); + unsigned int last(); + unsigned int next(); T &operator[](unsigned int); }; @@ -75,14 +81,29 @@ Database: (lib/database.cpp) template unsigned int Database : insert(T &); - Adds a new item to the db, returns the id of the item + Adds a new item to the db, returns the id of the item. void Database : delete(unsigned int index); - Mark db[index] as invalid (quick deletion) + Mark db[index] as invalid (quick deletion). - unsigned Database : size(); - Returns number of valid rows in the database + 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 or return db.size() + if there are no valid rows. + + unsigned int Database : last(); + Return the id of the last valid row or 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 remaining valid rows. template T &Database : operator[unsigned int index] - Return a reference to db[index] + Return a reference to db[index]. diff --git a/include/database.h b/include/database.h index 3b79c977..b2f90fa1 100644 --- a/include/database.h +++ b/include/database.h @@ -8,6 +8,15 @@ #include + +class DatabaseEntry { +public: + bool valid; + + DatabaseEntry(); +}; + + template class Database { private: @@ -20,7 +29,13 @@ public: ~Database(); unsigned int insert(T); - const unsigned int &size(); + unsigned int size(); + unsigned int num_rows(); + + unsigned int first(); + unsigned int last(); + unsigned int next(unsigned int); + T &operator[](unsigned int); }; #include "database.hpp" diff --git a/include/database.hpp b/include/database.hpp index 475236e5..2ff2be36 100644 --- a/include/database.hpp +++ b/include/database.hpp @@ -28,9 +28,54 @@ unsigned int Database :: insert(T val) } template -const unsigned int &Database :: size() +unsigned int Database :: size() { return _size; } +template +unsigned int Database :: num_rows() +{ + return db.size(); +} + +template +unsigned int Database :: first() +{ + for (unsigned int i = 0; i < db.size(); i++) { + if (db[i].valid == true) + return i; + } + + return db.size(); +} + +template +unsigned int Database :: last() +{ + for (unsigned int i = db.size() - 1; i >= 0; i--) { + if (db[i].valid == true) + return i; + } + + return db.size(); +} + +template +unsigned int Database :: 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 +T &Database :: operator[](unsigned int id) +{ + return db[id]; +} + #endif /* OCARINA_DATABASE_HPP */ diff --git a/lib/database.cpp b/lib/database.cpp index 9a4b06ec..05f4f071 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -3,3 +3,7 @@ */ #include +DatabaseEntry :: DatabaseEntry() + : valid(false) +{ +} diff --git a/tests/database/database.cpp b/tests/database/database.cpp index 16c3e6d9..15f18ec8 100644 --- a/tests/database/database.cpp +++ b/tests/database/database.cpp @@ -4,24 +4,48 @@ #include #include -void test_insertion(Database &db) +class DBTest : public DatabaseEntry { +public: + unsigned int value; + DBTest(unsigned int); +}; + +DBTest :: DBTest(unsigned int val) { - unsigned int id; + value = val; + valid = true; +} - print("\n"); - for (unsigned int i = 1; i <= 10; i++) { - id = db.insert(i); - print("db[%u] = %u\n", id, i); - } - print("Database size: %u\n", db.size()); +void print_db(Database &db) +{ + print("\nDatabase size: %u\n", db.size()); + print("Num rows: %u\n", db.num_rows()); + print("First: %u\n", db.first()); + print("Last: %u\n", db.last()); + + for (unsigned int i = db.first(); i != db.num_rows(); i = db.next(i)) + print("db[%u] = %u\n", i, db[i].value); +} + +void test_insertion(Database &db) +{ + for (unsigned int i = 1; i <= 10; i++) + db.insert(DBTest(i)); + + print_db(db); +} + +void test_deletion(Database &db) +{ } int main(int argc, char **argv) { - Database db("test.db"); + Database db("test.db"); test_insertion(db); + test_deletion(db); return 0; }