database: Allow templated keys to the database index

This allows me to have a std::pair<> as a key if needed.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2013-12-10 17:38:42 -05:00 committed by Anna Schumaker
parent eaafaeb7d4
commit a50d8f6e0a
11 changed files with 103 additions and 117 deletions

View File

@ -12,12 +12,13 @@
#include <vector>
template <class T>
class DatabaseEntry {
public:
bool valid;
DatabaseEntry();
virtual const std::string &primary_key() = 0;
virtual T &primary_key() = 0;
virtual void write(File &) = 0;
virtual void read(File &) = 0;
#ifdef CONFIG_DEBUG
@ -26,7 +27,7 @@ public:
};
class IndexEntry : public DatabaseEntry {
class IndexEntry : public DatabaseEntry<const std::string> {
public:
std::string key;
std::set<unsigned int> values;
@ -43,11 +44,11 @@ public:
};
template <class T>
template <class T, class U>
class Database {
private:
std::vector<T> db;
std::map<const std::string, unsigned int> keys;
std::map<U, unsigned int> keys;
unsigned int _size;
File file;
@ -75,7 +76,8 @@ public:
T &operator[](unsigned int);
};
static inline void index_insert(Database<IndexEntry> &db,
template <class T>
static inline void index_insert(Database<IndexEntry, T> &db,
const std::string &key,
unsigned int val)
{
@ -86,7 +88,8 @@ static inline void index_insert(Database<IndexEntry> &db,
}
}
static inline void index_remove(Database<IndexEntry> &db,
template <class T>
static inline void index_remove(Database<IndexEntry, T> &db,
const std::string &key,
unsigned int val)
{

View File

@ -8,18 +8,26 @@
#define OCARINA_DATABASE_HPP
template <class T>
Database<T> :: Database(std::string filepath)
DatabaseEntry<T> :: DatabaseEntry()
: valid(false)
{
}
template <class T, class U>
Database<T, U> :: Database(std::string filepath)
: _size(0), file(filepath, FILE_TYPE_DATA)
{
}
template <class T>
Database<T> :: ~Database()
template <class T, class U>
Database<T, U> :: ~Database()
{
}
template <class T>
void Database<T> :: save()
template <class T, class U>
void Database<T, U> :: save()
{
if (file.open(OPEN_WRITE) == false)
return;
@ -35,8 +43,8 @@ void Database<T> :: save()
file.close();
}
template <class T>
void Database<T> :: load()
template <class T, class U>
void Database<T, U> :: load()
{
unsigned int db_size;
if (file.open(OPEN_READ) == false)
@ -57,16 +65,16 @@ void Database<T> :: load()
}
#ifdef CONFIG_DEBUG
template <class T>
void Database<T> :: clear()
template <class T, class U>
void Database<T, U> :: clear()
{
db.clear();
keys.clear();
_size = 0;
}
template <class T>
void Database<T> :: print()
template <class T, class U>
void Database<T, U> :: print()
{
:: print("Allocated rows: %u\n", db.size());
:: print("Valid rows: %u\n", _size);
@ -79,8 +87,8 @@ void Database<T> :: print()
}
}
template <class T>
void Database<T> :: print_keys()
template <class T, class U>
void Database<T, U> :: print_keys()
{
std::map<const std::string, unsigned int>::iterator it;
:: print("Found keys:");
@ -90,11 +98,11 @@ void Database<T> :: print_keys()
}
#endif /* CONFIG_DEBUG */
template <class T>
unsigned int Database<T> :: insert(T val)
template <class T, class U>
unsigned int Database<T, U> :: insert(T val)
{
unsigned int id;
std::map<std::string, unsigned int>::iterator it;
typename std::map<U, unsigned int>::iterator it;
it = keys.find(val.primary_key());
if (it != keys.end())
@ -105,34 +113,34 @@ unsigned int Database<T> :: insert(T val)
*/
id = db.size();
db.push_back(val);
keys.insert(std::pair<std::string, unsigned int>(val.primary_key(), id));
keys.insert(std::pair<U, unsigned int>(val.primary_key(), id));
db[_size].valid = true;
_size++;
return id;
}
template <class T>
void Database<T> :: remove(unsigned int id)
template <class T, class U>
void Database<T, U> :: remove(unsigned int id)
{
keys.erase(db[id].primary_key());
db[id].valid = false;
_size--;
}
template <class T>
unsigned int Database<T> :: size()
template <class T, class U>
unsigned int Database<T, U> :: size()
{
return _size;
}
template <class T>
unsigned int Database<T> :: num_rows()
template <class T, class U>
unsigned int Database<T, U> :: num_rows()
{
return db.size();
}
template <class T>
unsigned int Database<T> :: first()
template <class T, class U>
unsigned int Database<T, U> :: first()
{
for (unsigned int i = 0; i < db.size(); i++) {
if (db[i].valid == true)
@ -142,8 +150,8 @@ unsigned int Database<T> :: first()
return db.size();
}
template <class T>
unsigned int Database<T> :: last()
template <class T, class U>
unsigned int Database<T, U> :: last()
{
if (_size == 0)
return db.size();
@ -156,8 +164,8 @@ unsigned int Database<T> :: last()
return db.size();
}
template <class T>
unsigned int Database<T> :: next(unsigned int id)
template <class T, class U>
unsigned int Database<T, U> :: next(unsigned int id)
{
for (unsigned int i = id + 1; i < db.size(); i++) {
if (db[i].valid == true)
@ -167,24 +175,24 @@ unsigned int Database<T> :: next(unsigned int id)
return db.size();
}
template <class T>
unsigned int Database<T> :: find_index(const std::string &key)
template <class T, class U>
unsigned int Database<T, U> :: find_index(const std::string &key)
{
std::map<std::string, unsigned int>::iterator it;
typename std::map<U, unsigned int>::iterator it;
it = keys.find(key);
if (it == keys.end())
throw 0;
return it->second;
}
template <class T>
T &Database<T> :: find(const std::string &key)
template <class T, class U>
T &Database<T, U> :: find(const std::string &key)
{
return db[find_index(key)];
}
template <class T>
T &Database<T> :: operator[](unsigned int id)
template <class T, class U>
T &Database<T, U> :: operator[](unsigned int id)
{
return db[id];
}

View File

@ -15,7 +15,7 @@ namespace filter {
void print_cache_stats();
#ifdef CONFIG_TEST
Database<IndexEntry> &get_index();
Database<IndexEntry, const std::string> &get_index();
#endif /* CONFIG_TEST */
};

View File

@ -22,7 +22,7 @@ namespace library
};
class Artist : public DatabaseEntry {
class Artist : public DatabaseEntry<const std::string> {
public:
std :: string name;
@ -37,15 +37,16 @@ namespace library
};
class Album : public DatabaseEntry {
class Album : public DatabaseEntry<std::pair<std::string, unsigned int> >{
public:
std:: string name;
std :: pair<std::string, unsigned int> key;
std :: string name;
unsigned int year;
unsigned int artist_id;
Album();
Album(TagLib :: Tag *, unsigned int);
const std::string &primary_key();
std::pair<std::string, unsigned int> &primary_key();
void read(File &);
void write(File &);
#ifdef CONFIG_DEBUG
@ -54,7 +55,7 @@ namespace library
};
class Genre : public DatabaseEntry {
class Genre : public DatabaseEntry<const std::string> {
public:
std:: string name;
@ -66,11 +67,10 @@ namespace library
#ifdef CONFIG_DEBUG
void print();
#endif /* CONFIG_DEBUG */
bool operator==(const Genre &);
};
class Library : public DatabaseEntry {
class Library : public DatabaseEntry<const std::string> {
public:
std::string root_path;
bool enabled;
@ -83,11 +83,10 @@ namespace library
#ifdef CONFIG_DEBUG
void print();
#endif /* CONFIG_DEBUG */
bool operator==(Library &);
};
class Track : public DatabaseEntry {
class Track : public DatabaseEntry<const std::string> {
public:
unsigned int library_id;
unsigned int artist_id;
@ -116,7 +115,6 @@ namespace library
#ifdef CONFIG_DEBUG
void print();
#endif /* CONFIG_DEBUG */
bool operator==(const Track &);
};

View File

@ -3,13 +3,6 @@
*/
#include <database.h>
DatabaseEntry :: DatabaseEntry()
: valid(false)
{
}
IndexEntry :: IndexEntry()
{
}

View File

@ -10,7 +10,7 @@
#include <map>
#include <set>
static Database<IndexEntry> filter_index("");
static Database<IndexEntry, const std::string> filter_index("");
static std::map<std::string, std::string> lowercase_cache;
static unsigned int lowercase_cache_hits = 0;
@ -143,7 +143,7 @@ void filter :: print_cache_stats()
}
#ifdef CONFIG_TEST
Database<IndexEntry> &filter :: get_index()
Database<IndexEntry, const std::string> &filter :: get_index()
{
return filter_index;
}

View File

@ -5,7 +5,7 @@
#include <group.h>
static std::set<unsigned int> empty_set;
Database<IndexEntry> group_index("");
Database<IndexEntry, const std::string> group_index("");
void group :: add(const std::string &name, unsigned int track_id)
{

View File

@ -5,11 +5,11 @@
#include <glib.h>
static Database<library :: Artist> artist_db("artist.db");
static Database<library :: Album> album_db("album.db");
static Database<library :: Genre> genre_db("genre.db");
static Database<library :: Library> library_db("library.db");
static Database<library :: Track> track_db("track.db");
static Database<library :: Artist, const std::string> artist_db("artist.db");
static Database<library :: Album, std::pair<const std::string, unsigned int> > album_db("album.db");
static Database<library :: Genre, const std::string> genre_db("genre.db");
static Database<library :: Library, const std::string> library_db("library.db");
static Database<library :: Track, const std::string> track_db("track.db");
@ -64,11 +64,12 @@ library :: Album :: Album(TagLib :: Tag *tag, unsigned int artist)
: name(tag->album().stripWhiteSpace().to8Bit(true)),
year(tag->year()), artist_id(artist)
{
key = make_pair(name, artist_id);
}
const std::string &library :: Album :: primary_key()
std :: pair<std::string, unsigned int> &library :: Album :: primary_key()
{
return name;
return key;
}
void library :: Album :: read(File &f)
@ -127,11 +128,6 @@ void library :: Genre :: print()
}
#endif /* CONFIG_DEBUG */
bool library :: Genre :: operator==(const library :: Genre &rhs)
{
return name == rhs.name;
}
/*
@ -175,11 +171,6 @@ void library :: Library :: print()
}
#endif /* CONFIG_DEBUG */
bool library :: Library :: operator==(library :: Library &rhs)
{
return root_path == rhs.root_path;
}
/*
@ -239,13 +230,6 @@ void library :: Track :: print()
}
#endif /* CONFIG_DEBUG */
bool library :: Track :: operator==(const library :: Track &rhs)
{
if (library_id == rhs.library_id)
return filepath == rhs.filepath;
return false;
}
/*
@ -256,9 +240,9 @@ static void do_update(unsigned int, const std :: string &);
static void read_tags(unsigned int lib_id, const std :: string &path)
{
TagLib :: Tag *tag;
//TagLib :: AudioProperties *audio;
TagLib :: AudioProperties *audio;
TagLib :: FileRef ref(path.c_str(), true, TagLib :: AudioProperties :: Fast);
unsigned int artist_id; //, album_id, genre_id;
unsigned int artist_id, album_id, genre_id;
if (ref.isNull()) {
print("ERROR: Could not read tags for file %s", path.c_str());
@ -267,13 +251,13 @@ static void read_tags(unsigned int lib_id, const std :: string &path)
tag = ref.tag();
//audio = ref.audioProperties();
audio = ref.audioProperties();
artist_id = artist_db.insert(library :: Artist(tag));
/*album_id =*/ album_db.insert(library :: Album(tag, artist_id));
/*genre_id = genre_db.insert(library :: Genre(tag));*/
/*track_db.insert(library :: Track(tag, audio, lib_id, artist_id,
album_id, genre_id, path));*/
album_id = album_db.insert(library :: Album(tag, artist_id));
genre_id = genre_db.insert(library :: Genre(tag));
track_db.insert(library :: Track(tag, audio, lib_id, artist_id,
album_id, genre_id, path));
}
static void process_path(unsigned int lib_id, const std :: string &dir,

View File

@ -6,7 +6,7 @@
#include <sstream>
class DBTest : public DatabaseEntry {
class DBTest : public DatabaseEntry<const std::string> {
public:
unsigned int value;
std::string key;
@ -54,7 +54,7 @@ const std::string &DBTest :: primary_key()
void print_db(Database<DBTest> &db)
void print_db(Database<DBTest, const std::string> &db)
{
print("Database size: %u\n", db.size());
print("Num rows: %u\n", db.num_rows());
@ -65,14 +65,14 @@ void print_db(Database<DBTest> &db)
print("db[%u] = %u\n", i, db[i].value);
}
void test_insertion(Database<DBTest> &db)
void test_insertion(Database<DBTest, const std::string> &db)
{
for (unsigned int i = 1; i <= 100000; i++)
db.insert(DBTest(i));
print_db(db);
}
void test_deletion(Database<DBTest> &db)
void test_deletion(Database<DBTest, const std::string> &db)
{
for (unsigned int i = db.first(); i < db.num_rows(); i = db.next(i)) {
db.remove(i);
@ -87,7 +87,7 @@ void test_deletion(Database<DBTest> &db)
void test_0()
{
print("Test 0\n");
Database<DBTest> db("test.db");
Database<DBTest, const std::string> db("test.db");
test_insertion(db);
test_deletion(db);
@ -102,7 +102,7 @@ void test_0()
void test_1()
{
print("\nTest 1\n");
Database<DBTest> db("test.db");
Database<DBTest, const std::string> db("test.db");
db.load();
print_db(db);
}
@ -113,7 +113,7 @@ void test_1()
void test_2()
{
print("\nTest 2\n");
Database<DBTest> db("");
Database<DBTest, const std::string> db("");
test_insertion(db);
db.save();
@ -125,7 +125,7 @@ void test_2()
void test_3()
{
print("\nTest 3\n");
Database<DBTest> db("");
Database<DBTest, const std::string> db("");
db.load();
}
@ -135,7 +135,7 @@ void test_3()
void test_4()
{
print("\nTest 4\n");
Database<DBTest> db("");
Database<DBTest, const std::string> db("");
for (unsigned int i = 0; i < 100; i++)
db.insert(DBTest(i % 5));
@ -149,7 +149,7 @@ void test_4()
void test_5()
{
print("\nTest 5\n");
Database<DBTest> db("");
Database<DBTest, const std::string> db("");
for (unsigned int i = 0; i < 10; i++)
db.insert(DBTest(i));
db.print();
@ -161,7 +161,7 @@ void test_5()
void test_6()
{
print("\nTest 6\n");
Database<DBTest> db("");
Database<DBTest, const std::string> db("");
for (unsigned int i = 0; i < 10; i++)
db.insert(DBTest(i));
print_db(db);
@ -175,7 +175,7 @@ void test_6()
void test_7()
{
print("\nTest 7\n");
Database<DBTest> db("");
Database<DBTest, const std::string> db("");
print_db(db);
for (unsigned int i = 0; i < 10; i++)

View File

@ -48,7 +48,7 @@ std::string quotes [] = {
static const unsigned int num_quotes = sizeof(quotes) / sizeof(std::string);
void print_index(Database<IndexEntry> &db)
void print_index(Database<IndexEntry, const std::string> &db)
{
db.print_keys();
for (unsigned int i = db.first(); i <= db.last(); i = db.next(i)) {

View File

@ -4,7 +4,7 @@
#include <database.h>
#include <print.h>
void print_index(Database<IndexEntry> &index)
void print_index(Database<IndexEntry, const std::string> &index)
{
std::set<std::string>::iterator s_it;
std::set<unsigned int>::iterator u_it;
@ -21,7 +21,7 @@ void print_index(Database<IndexEntry> &index)
print("\n");
}
void populate_index(Database<IndexEntry> &index)
void populate_index(Database<IndexEntry, const std::string> &index)
{
std::string key_str;
@ -32,7 +32,7 @@ void populate_index(Database<IndexEntry> &index)
}
}
void remove_keys(Database<IndexEntry> &index)
void remove_keys(Database<IndexEntry, const std::string> &index)
{
std::string key_str;
@ -42,7 +42,7 @@ void remove_keys(Database<IndexEntry> &index)
}
}
void remove_values(Database<IndexEntry> &index)
void remove_values(Database<IndexEntry, const std::string> &index)
{
std::string key_str;
unsigned int limit = 0;
@ -63,7 +63,7 @@ void remove_values(Database<IndexEntry> &index)
void test_0()
{
print("Test 0\n");
Database<IndexEntry> index("");
Database<IndexEntry, const std::string> index("");
populate_index(index);
print_index(index);
@ -75,7 +75,7 @@ void test_0()
void test_1()
{
print("Test 1\n");
Database<IndexEntry> index("");
Database<IndexEntry, const std::string> index("");
populate_index(index);
remove_keys(index);
@ -88,7 +88,7 @@ void test_1()
void test_2()
{
print("Test 2\n");
Database<IndexEntry> index("");
Database<IndexEntry, const std::string> index("");
populate_index(index);
remove_values(index);
@ -101,7 +101,7 @@ void test_2()
void test_3()
{
print("Test 3\n");
Database<IndexEntry> index("test.idx");
Database<IndexEntry, const std::string> index("test.idx");
populate_index(index);
remove_values(index);
@ -114,7 +114,7 @@ void test_3()
void test_4()
{
print("Test 4\n");
Database<IndexEntry> index("test.idx");
Database<IndexEntry, const std::string> index("test.idx");
index.load();
print_index(index);
@ -126,7 +126,7 @@ void test_4()
void test_5()
{
print("Test 5\n");
Database<IndexEntry> index("");
Database<IndexEntry, const std::string> index("");
print("index[nokey].size() = ");
try {
print("%u\n", index.find("nokey").values.size());