ocarina/core/filter.cpp

130 lines
2.5 KiB
C++

/*
* Copyright 2013 (c) Anna Schumaker.
*/
#include <core/filter.h>
#include <core/index.h>
#include <algorithm>
#include <list>
static Index filter_index("", false);
static void parse_text(const std::string &text, std::list<std::string> &ret)
{
std::string word;
char c;
for (unsigned int i = 0; i < text.size(); i++) {
c = text[i];
if ( (c >= 'a') && (c <= 'z') ) {
word += c;
continue;
} else if ( (c >= 'A') && (c <= 'Z') ) {
word += (c + ('a' - 'A'));
continue;
} else if ( (c >= '0') && (c <= '9') ) {
word += c;
continue;
}
switch (c) {
case '\\':
case '/':
case ',':
case ';':
case '(':
case ')':
case '_':
case '-':
case '~':
case '+':
case '"':
case ' ':
case ' ':
if (word != "") {
ret.push_back(word);
word = "";
}
default:
break;
};
}
if (word != "")
ret.push_back(word);
}
static void add_substrings(const std::string &text, unsigned int track_id)
{
std::string substr;
for (unsigned int i = 1; i <= text.size(); i++) {
substr = text.substr(0, i);
filter_index.insert(substr, track_id);
}
}
static std::string reassemble_text(std::list<std::string> text)
{
std::string res;
std::list<std::string>::iterator it = text.begin();
if (it == text.end())
return res;
res += *it;
for (it++; it != text.end(); it++)
res += " " + *it;
return res;
}
std::string filter :: add(const std::string &text, unsigned int track_id)
{
std::list<std::string> parsed;
std::list<std::string>::iterator it;
parse_text(text, parsed);
for (it = parsed.begin(); it != parsed.end(); it++)
add_substrings(*it, track_id);
return reassemble_text(parsed);
}
static void find_intersection(std::string &text, std::set<unsigned int> &res)
{
IndexEntry *it = filter_index.find(text);
std::set<unsigned int> tmp;
set_intersection(it->values.begin(), it->values.end(),
res.begin(), res.end(),
std::inserter<std::set<unsigned int> >(tmp, tmp.begin()));
res.swap(tmp);
}
void filter :: search(const std::string &text, std::set<unsigned int> &res)
{
std::list<std::string> parsed;
std::list<std::string>::iterator it;
IndexEntry *found;
parse_text(text, parsed);
if (parsed.size() == 0)
return;
it = parsed.begin();
found = filter_index.find(*it);
if (!found)
return;
res = found->values;
for (it++; it != parsed.end(); it++)
find_intersection(*it, res);
}
std::string filter :: lowercase(const std::string &text)
{
std::list<std::string> parsed;
parse_text(text, parsed);
return reassemble_text(parsed);
}