1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2024-11-25 00:53:43 +00:00

Implement ls into subdirectories

This commit is contained in:
King_DuckZ 2016-01-29 20:15:16 +01:00
parent 362a5d3128
commit f40600d6e2
6 changed files with 167 additions and 33 deletions

View file

@ -29,6 +29,8 @@
namespace din {
const size_t MAXSZARR_MAX_STACK_ALLOC_SIZE = MAX_STACK_ALLOC_SIZE;
//TODO: add a template parameter to force stack allocation regardless of
//sizeof(T) * S
template <typename T, size_t S, typename A=std::allocator<T> >
class MaxSizedArray :
private std::conditional<

View file

@ -26,6 +26,41 @@
#include <boost/range/algorithm/copy.hpp>
namespace din {
namespace {
const uint32_t g_files_query_limit = 500;
std::ostream& operator<< (std::ostream& parOut, const std::vector<std::string>& parCols) {
parOut << '"';
boost::copy(parCols, infix_ostream_iterator<std::string>(parOut, "\", \""));
parOut << '"';
return parOut;
}
} //unnamed namespace
const DBSource::SetDetailsMap DBSource::m_set_details_map {
{SetDetail_Desc, "desc"},
{SetDetail_Type, "type"},
{SetDetail_CreeationDate, "creation"},
{SetDetail_AppName, "app_name"},
{SetDetail_ID, "id"}
};
const DBSource::FileDetailsMap DBSource::m_file_details_map {
{FileDetail_ID, "id"},
{FileDetail_Path, "path"},
{FileDetail_Level, "level"},
{FileDetail_GroupID, "group_id"},
{FileDetail_IsDir, "is_directory"},
{FileDetail_IsSymLink, "is_symlink"},
{FileDetail_Size, "size"},
{FileDetail_Hash, "hash"},
{FileDetail_IsHashValid, "is_hash_valid"},
{FileDetail_ATime, "access_time"},
{FileDetail_MTime, "modify_time"},
{FileDetail_Unreadable, "unreadable"},
{FileDetail_MimeType, "mimetype"},
{FileDetail_Charset, "charset"}
};
struct DBSource::LocalData {
explicit LocalData ( const dinlib::SettingsDB& parDBSettings ) :
conn(
@ -78,12 +113,13 @@ namespace din {
return std::move(retval);
}
void DBSource::query_push_results (const std::vector<std::string>& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, std::function<void(std::string&&)> parCallback) {
void DBSource::query_no_conditions (const ColumnList& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, std::function<void(std::string&&)> parCallback) {
std::ostringstream oss;
oss << "SELECT \"";
boost::copy(parCols, infix_ostream_iterator<std::string>(oss, "\", \""));
oss << '"';
oss << " FROM \"" << parTable << "\" WHERE \"id\" = ANY($1) ORDER BY \"desc\" ASC LIMIT 500;";
oss << "SELECT " << parCols << ' ' <<
"FROM \"" << parTable << "\" " <<
"WHERE \"id\"=ANY($1) " <<
"ORDER BY \"desc\" ASC " <<
"LIMIT " << g_files_query_limit << ';';
auto& conn = get_conn();
auto result = conn.query(oss.str(), parIDs);
@ -93,4 +129,28 @@ namespace din {
}
}
}
void DBSource::query_files_in_dir (const ColumnList& parCols, boost::string_ref parDir, uint16_t parLevel, uint32_t parGroupID, QueryCallback parCallback) {
std::ostringstream oss;
oss << "SELECT " << parCols << ' ' <<
"FROM \"files\" WHERE " <<
"\"level\"=$1 " <<
"AND \"group_id\"=$2 " <<
"AND str_begins_with(\"path\", COALESCE($3, '')) " <<
"ORDER BY \"path\" ASC " <<
"LIMIT " << g_files_query_limit << ';';
auto& conn = get_conn();
auto result = conn.query(
oss.str(),
parLevel,
parGroupID,
parDir
);
for (auto row : result) {
for (auto val : row) {
parCallback(std::move(val));
}
}
}
} //namespace din

View file

@ -48,6 +48,23 @@ namespace din {
SetDetail_ID = 0x10
};
enum FileDetails {
FileDetail_ID = 0x0001,
FileDetail_Path = 0x0002,
FileDetail_Level = 0x0004,
FileDetail_GroupID = 0x0008,
FileDetail_IsDir = 0x0010,
FileDetail_IsSymLink = 0x0020,
FileDetail_Size = 0x0040,
FileDetail_Hash = 0x0080,
FileDetail_IsHashValid = 0x0100,
FileDetail_ATime = 0x0200,
FileDetail_MTime = 0x0400,
FileDetail_Unreadable = 0x800,
FileDetail_MimeType = 0x1000,
FileDetail_Charset = 0x2000
};
class DBSource {
public:
explicit DBSource ( const dinlib::SettingsDB& parDBSettings );
@ -58,47 +75,72 @@ namespace din {
template <SetDetails... D>
auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
//TODO: replace return value with vector of maxsizedarray
//auto set_details ( const std::vector<uint32_t>& parIDs ) -> std::array<std::string, sizeof...(D)>;
template <FileDetails... D>
auto file_details ( uint32_t parSetID, uint16_t parLevel, boost::string_ref parDir ) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>>;
private:
struct LocalData;
typedef std::map<SetDetails, std::string> SetDetailsMap;
typedef std::map<FileDetails, std::string> FileDetailsMap;
typedef std::vector<std::string> ColumnList;
typedef std::function<void(std::string&&)> QueryCallback;
pq::Connection& get_conn ( void );
void query_push_results ( const std::vector<std::string>& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, std::function<void(std::string&&)> parCallback );
void query_no_conditions ( const ColumnList& parCols, boost::string_ref parTable, const std::vector<uint32_t>& parIDs, QueryCallback parCallback );
void query_files_in_dir ( const ColumnList& parCols, boost::string_ref parDir, uint16_t parLevel, uint32_t parGroupID, QueryCallback parCallback );
static const SetDetailsMap m_set_details_map;
static const FileDetailsMap m_file_details_map;
std::unique_ptr<LocalData> m_local_data;
};
namespace implem {
template <class M, M... Details>
inline
std::vector<std::string> make_columns_vec (const std::map<M, std::string>& parDic) {
std::vector<std::string> columns;
columns.reserve(sizeof...(Details));
const std::array<M, sizeof...(Details)> details { Details... };
//std::generate(details.begin(), details.end(), columns.begin(), std::bind(at_func, &details_dic, std::placeholders::_1));
for (auto detail : details) {
columns.push_back(parDic.at(detail));
}
return std::move(columns);
}
} //namespace implem
template <SetDetails... D>
auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
//auto DBSource::set_details (const std::vector<uint32_t>& parIDs) -> std::array<std::string, sizeof...(D)> {
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
typedef std::map<SetDetails, std::string> DetailsMap;
typedef const std::string&(DetailsMap::*AtFunc)(const SetDetails&) const;
typedef const std::string&(SetDetailsMap::*AtFunc)(const SetDetails&) const;
typedef void(din::FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
const std::array<SetDetails, sizeof...(D)> details { D... };
const DetailsMap details_dic {
{SetDetail_Desc, "desc"},
{SetDetail_Type, "type"},
{SetDetail_CreeationDate, "creation"},
{SetDetail_AppName, "app_name"},
{SetDetail_ID, "id"}
};
std::vector<std::string> columns;
columns.reserve(sizeof...(D));
AtFunc at_func = &DetailsMap::at;
//std::generate(details.begin(), details.end(), columns.begin(), std::bind(at_func, &details_dic, std::placeholders::_1));
for (auto detail : details) {
columns.push_back(details_dic.at(detail));
}
const auto columns = implem::make_columns_vec<SetDetails, D...>(m_set_details_map);
AtFunc at_func = &SetDetailsMap::at;
ReturnType list;
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
this->query_push_results(columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
this->query_no_conditions(columns, "sets", parIDs, std::bind(pback_func, &flat_list, std::placeholders::_1));
return std::move(list);
}
template <FileDetails... D>
auto DBSource::file_details (uint32_t parSetID, uint16_t parLevel, boost::string_ref parDir) -> std::vector<MaxSizedArray<std::string, sizeof...(D)>> {
typedef std::vector<MaxSizedArray<std::string, sizeof...(D)>> ReturnType;
typedef const std::string&(SetDetailsMap::*AtFunc)(const SetDetails&) const;
typedef void(din::FlatInsertIn2DList<ReturnType>::*FlatPushBackFunc)(std::string&&);
const auto columns = implem::make_columns_vec<FileDetails, D...>(m_file_details_map);
AtFunc at_func = &SetDetailsMap::at;
ReturnType list;
FlatInsertIn2DList<ReturnType> flat_list(&list, sizeof...(D));
FlatPushBackFunc pback_func = &FlatInsertIn2DList<ReturnType>::push_back;
this->query_files_in_dir(columns, parDir, parLevel, parSetID, std::bind(pback_func, &flat_list, std::placeholders::_1));
return std::move(list);
}
} //namespace din

View file

@ -22,6 +22,7 @@
#include <sstream>
#include <boost/phoenix/bind/bind_function.hpp>
#include <boost/phoenix/operator.hpp>
#include <cassert>
namespace qi = boost::spirit::qi;
@ -103,4 +104,13 @@ namespace din {
boost::copy(m_stack, infix_ostream_iterator<std::string>(oss, "/"));
return oss.str();
}
uint16_t GenericPath::level() const {
return static_cast<uint16_t>(m_stack.size());
}
const std::string& GenericPath::operator[] (std::size_t parIndex) const {
assert(parIndex < level());
return m_stack[parIndex];
}
} //namespace din

View file

@ -20,6 +20,7 @@
#include <vector>
#include <string>
#include <cstdint>
namespace din {
class GenericPath {
@ -28,6 +29,8 @@ namespace din {
void push_piece ( const std::string& parPiece );
std::string to_string ( void ) const;
uint16_t level ( void ) const;
const std::string& operator[] ( std::size_t parIndex ) const;
private:
using StackType = std::vector<std::string>;

View file

@ -28,10 +28,12 @@
#include <vector>
#include <cassert>
#include <boost/range/algorithm/copy.hpp>
#include <boost/lexical_cast.hpp>
namespace {
void do_navigation ( din::DBSource& parDB );
template <typename V> void print_db_result ( const V& parResult );
bool on_exit ( void );
void on_pwd ( const din::GenericPath& parDirMan );
void on_ls ( const din::GenericPath& parDirMan, din::DBSource& parDB );
@ -67,6 +69,14 @@ int main (int parArgc, char* parArgv[]) {
}
namespace {
template <typename V>
void print_db_result (const V& parResult) {
for (const auto& row : parResult) {
boost::copy(row, infix_ostream_iterator<std::string>(std::cout, "\t"));
std::cout << "\n";
}
}
bool on_exit() {
return true;
}
@ -78,11 +88,18 @@ namespace {
void on_ls (const din::GenericPath& parDirMan, din::DBSource& parDB) {
using namespace din;
auto sets_ids = parDB.sets();
auto sets_info = parDB.set_details<SetDetail_ID, SetDetail_Desc, SetDetail_CreeationDate>(sets_ids);
for (const auto& row : sets_info) {
boost::copy(row, infix_ostream_iterator<std::string>(std::cout, "\t"));
std::cout << "\n";
const auto curr_path = parDirMan.to_string();
if ("/" == curr_path) {
auto sets_ids = parDB.sets();
auto sets_info = parDB.set_details<SetDetail_ID, SetDetail_Desc, SetDetail_CreeationDate>(sets_ids);
print_db_result(sets_info);
}
else {
const auto start_from = curr_path.find('/', 1);
auto path_prefix = boost::string_ref(curr_path).substr(start_from == curr_path.npos ? curr_path.size() : start_from + 1);
const auto set_id = boost::lexical_cast<uint32_t>(parDirMan[0]);
auto files_info = parDB.file_details<FileDetail_Path>(set_id, parDirMan.level(), path_prefix);
print_db_result(files_info);
}
}