index: Implement most of the index

I have everything except for save() and load() written.  My unittest is
fairly comprehensive and tests everything implemented so far, so with
any luck putting in save() and load() features will go quickly.

Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
Anna Schumaker 2013-08-21 22:12:15 -04:00 committed by Anna Schumaker
parent f124501c39
commit be0d3f3da4
9 changed files with 324 additions and 23 deletions

2
config
View File

@ -26,6 +26,7 @@ class Config:
self.ENV = CONFIG_ENV
self.DATABASE = False
self.FILE = False
self.INDEX = False
self.TEST = False
def package(self, name):
@ -40,6 +41,7 @@ class Config:
def reset(self):
self.DATABASE = False
self.FILE = False
self.INDEX = False
self.TEST = False
self.reconfigure()

View File

@ -9,47 +9,58 @@ idle file
Index: (lib/index.cpp)
An inverted index allows me to map multiple values to a single key.
Keys are tracked separately from the rest of the map so they can be
found and iterated over without writing ugly code.
- Index:
class Index {
private:
map<string, set<int>>
File filename;
map<string, set<unsigned int>> index;
set<string> keys;
File file;
public:
Index::Index(filename);
void load();
void save();
void insert(key, int);
void delete(key, int);
void replace(key, int);
const set<string> &keys();
const set<int> &operator[](string);
void insert(key, unsigned int);
void remove(key);
void remove(key, unsigned int);
const set<string>::iterator keys_begin();
const set<string>::iterator keys_end();
const set<unsigned int> &operator[](string);
};
File << key << endl;
File << map[key].size() << int_0 << int_1 << ... << int_n << endl;
- API:
Index.Index(filename);
Index : Index(filename);
Initializes an index using ~/.ocarina{-debug}K/filename. Pass
an empty string if you do not want this index to be saved.
Index.load();
void Index : load();
Reads data from a file. Call after static initialization of
Ocarina to ensure idle tasks are configured
Index.save();
void Index : save();
Saves data to file
Index.insert(key, int);
void Index : insert(key, unsigned int);
1) If key does not exist, create it.
2) Add int to the list
3) Index.save()
Index.delete(key, int);
2) Add int to the set for the given key
void Index : remove(key);
Remove a key from the index;
Index : remove(key, unsigned int);
1) Remove int from the set of values associated with key
2) Do not delete key if set is empty
3) Index.save()
Index.replace(key, int)
1) map[key].clear()
2) insert(key, int)
Index.keys();
Return a set of index keys
Index.operator[](string key);
2) If the set is empty, remove the key
const set<string>::iterator void Index : keys_begin()
Return an iterator pointing to the beginning of the keys set.
const set<string>::iterator void Index : keys_end()
Return an iterator pointing to the end of the keys set.
Index : operator[](string key);
Return the set associated with key

31
include/index.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright 2013 (c) Anna Schumaker.
*/
#ifndef OCARINA_INDEX_H
#define OCARINA_INDEX_H
#include <file.h>
#include <map>
#include <set>
#include <string>
class Index {
private:
std::map<std::string, std::set<unsigned int> > index;
std::set<std::string> keys;
File file;
public:
Index(std::string);
void insert(std::string, unsigned int);
void remove(std::string);
void remove(std::string, unsigned int);
const std::set<std::string>::iterator keys_begin();
const std::set<std::string>::iterator keys_end();
const std::set<unsigned int> &operator[](std::string &);
};
#endif /* OCARINA_INDEX_H */

View File

@ -7,10 +7,16 @@ if CONFIG.DATABASE:
CONFIG.FILE = True
build += [ env.Object("database.cpp") ]
if CONFIG.INDEX:
CONFIG.FILE = True
build += [ env.Object("index.cpp") ]
if CONFIG.FILE:
CONFIG.package("glib-2.0")
build += [ env.Object("file.cpp") ]
if CONFIG.TEST:
build += [ env.Object("test.cpp") ]

48
lib/index.cpp Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright 2013 (c) Anna Schumaker.
*/
#include <index.h>
Index :: Index(std::string filepath)
: file(filepath, FILE_TYPE_DATA)
{
}
void Index :: insert(std::string key, unsigned int value)
{
if (index.find(key) == index.end()) {
index[key] = std::set<unsigned int>();
keys.insert(key);
}
index[key].insert(value);
}
void Index :: remove(std::string key)
{
index.erase(key);
keys.erase(key);
}
void Index :: remove(std::string key, unsigned int value)
{
index[key].erase(value);
if (index[key].size() == 0)
remove(key);
}
const std::set<std::string>::iterator Index :: keys_begin()
{
return keys.begin();
}
const std::set<std::string>::iterator Index :: keys_end()
{
return keys.end();
}
const std::set<unsigned int> &Index :: operator[](std::string &key)
{
return index[key];
}

View File

@ -43,7 +43,7 @@ Export("Test")
# Read SConscript files
scripts = [ "basic", "file", "database" ]
scripts = [ "basic", "database", "file", "index" ]
for s in scripts:
CONFIG.reset()
CONFIG.TEST = True

6
tests/index/Sconscript Normal file
View File

@ -0,0 +1,6 @@
#!/usr/bin/python
Import("Test", "CONFIG")
CONFIG.INDEX = True
Test("index", "index.cpp")

122
tests/index/index.cpp Normal file
View File

@ -0,0 +1,122 @@
/*
* Copyright 2013 (c) Anna Schumaker.
*/
#include <index.h>
#include <print.h>
void print_keys(Index &index)
{
std::set<std::string>::iterator it;
print("Found keys:");
for (it = index.keys_begin(); it != index.keys_end(); it++)
print(" %s", it->c_str());
print("\n");
}
void print_index(Index &index)
{
std::set<std::string>::iterator s_it;
std::set<unsigned int>::iterator u_it;
print("=== Printing index ===\n");
print_keys(index);
for (s_it = index.keys_begin(); s_it != index.keys_end(); s_it++) {
std::string key = *s_it;
print("index[%s] = {", key.c_str());
for (u_it = index[key].begin(); u_it != index[key].end(); u_it++) {
if (u_it != index[key].begin())
print(" ");
print("%d", *u_it);
}
print("}\n");
}
print("\n");
}
void populate_index(Index &index)
{
std::string key_str;
for (char key = 'a'; key <= 'z'; key++) {
key_str = key;
for (unsigned int value = 0; value < 10; value++) {
index.insert(key_str, value);
}
}
}
void remove_keys(Index &index)
{
std::string key_str;
for (char key = 'a'; key <= 'z'; key+=2) {
key_str = key;
index.remove(key_str);
}
}
void remove_values(Index &index)
{
std::string key_str;
unsigned int limit = 0;
for (char key = 'a'; key <= 'z'; key++) {
key_str = key;
for (unsigned int i = 0; i < limit; i++) {
index.remove(key_str, i);
}
limit++;
if (limit == 11)
limit = 0;
}
}
/*
* Test index creation, print key access
*/
void test_0()
{
print("Test 0\n");
Index index("");
populate_index(index);
print_index(index);
}
/*
* Test removing keys from an index
*/
void test_1()
{
print("Test 1\n");
Index index("");
populate_index(index);
remove_keys(index);
print_index(index);
}
/*
* Test removing values from an index
*/
void test_2()
{
print("Test 2\n");
Index index("");
populate_index(index);
remove_values(index);
print_index(index);
}
int main(int argc, char **argv)
{
test_0();
test_1();
test_2();
return 0;
}

75
tests/index/index.good Normal file
View File

@ -0,0 +1,75 @@
Test 0
=== Printing index ===
Found keys: a b c d e f g h i j k l m n o p q r s t u v w x y z
index[a] = {0 1 2 3 4 5 6 7 8 9}
index[b] = {0 1 2 3 4 5 6 7 8 9}
index[c] = {0 1 2 3 4 5 6 7 8 9}
index[d] = {0 1 2 3 4 5 6 7 8 9}
index[e] = {0 1 2 3 4 5 6 7 8 9}
index[f] = {0 1 2 3 4 5 6 7 8 9}
index[g] = {0 1 2 3 4 5 6 7 8 9}
index[h] = {0 1 2 3 4 5 6 7 8 9}
index[i] = {0 1 2 3 4 5 6 7 8 9}
index[j] = {0 1 2 3 4 5 6 7 8 9}
index[k] = {0 1 2 3 4 5 6 7 8 9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[m] = {0 1 2 3 4 5 6 7 8 9}
index[n] = {0 1 2 3 4 5 6 7 8 9}
index[o] = {0 1 2 3 4 5 6 7 8 9}
index[p] = {0 1 2 3 4 5 6 7 8 9}
index[q] = {0 1 2 3 4 5 6 7 8 9}
index[r] = {0 1 2 3 4 5 6 7 8 9}
index[s] = {0 1 2 3 4 5 6 7 8 9}
index[t] = {0 1 2 3 4 5 6 7 8 9}
index[u] = {0 1 2 3 4 5 6 7 8 9}
index[v] = {0 1 2 3 4 5 6 7 8 9}
index[w] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {0 1 2 3 4 5 6 7 8 9}
index[y] = {0 1 2 3 4 5 6 7 8 9}
index[z] = {0 1 2 3 4 5 6 7 8 9}
Test 1
=== Printing index ===
Found keys: b d f h j l n p r t v x z
index[b] = {0 1 2 3 4 5 6 7 8 9}
index[d] = {0 1 2 3 4 5 6 7 8 9}
index[f] = {0 1 2 3 4 5 6 7 8 9}
index[h] = {0 1 2 3 4 5 6 7 8 9}
index[j] = {0 1 2 3 4 5 6 7 8 9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[n] = {0 1 2 3 4 5 6 7 8 9}
index[p] = {0 1 2 3 4 5 6 7 8 9}
index[r] = {0 1 2 3 4 5 6 7 8 9}
index[t] = {0 1 2 3 4 5 6 7 8 9}
index[v] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {0 1 2 3 4 5 6 7 8 9}
index[z] = {0 1 2 3 4 5 6 7 8 9}
Test 2
=== Printing index ===
Found keys: a b c d e f g h i j l m n o p q r s t u w x y z
index[a] = {0 1 2 3 4 5 6 7 8 9}
index[b] = {1 2 3 4 5 6 7 8 9}
index[c] = {2 3 4 5 6 7 8 9}
index[d] = {3 4 5 6 7 8 9}
index[e] = {4 5 6 7 8 9}
index[f] = {5 6 7 8 9}
index[g] = {6 7 8 9}
index[h] = {7 8 9}
index[i] = {8 9}
index[j] = {9}
index[l] = {0 1 2 3 4 5 6 7 8 9}
index[m] = {1 2 3 4 5 6 7 8 9}
index[n] = {2 3 4 5 6 7 8 9}
index[o] = {3 4 5 6 7 8 9}
index[p] = {4 5 6 7 8 9}
index[q] = {5 6 7 8 9}
index[r] = {6 7 8 9}
index[s] = {7 8 9}
index[t] = {8 9}
index[u] = {9}
index[w] = {0 1 2 3 4 5 6 7 8 9}
index[x] = {1 2 3 4 5 6 7 8 9}
index[y] = {2 3 4 5 6 7 8 9}
index[z] = {3 4 5 6 7 8 9}