c++11 for readline + libwrapper

This commit is contained in:
Evgeniy Dushistov
2013-07-06 22:44:11 +00:00
parent 7274a61efa
commit 3812fad586
4 changed files with 116 additions and 122 deletions

View File

@@ -67,7 +67,7 @@ static std::string xdxf2text(const char *p)
res+=""; res+="";
else if (name=="k") { else if (name=="k") {
const char *begin=next; const char *begin=next;
if ((next=strstr(begin, "</k>"))!=NULL) if ((next=strstr(begin, "</k>"))!=nullptr)
next+=sizeof("</k>")-1-1; next+=sizeof("</k>")-1-1;
else else
next=begin; next=begin;
@@ -171,7 +171,7 @@ void Library::SimpleLookup(const string &str, TSearchResultList& res_list)
{ {
glong ind; glong ind;
res_list.reserve(ndicts()); res_list.reserve(ndicts());
for (gint idict=0; idict<ndicts(); ++idict) for (gint idict = 0; idict < ndicts(); ++idict)
if (SimpleLookupWord(str.c_str(), ind, idict)) if (SimpleLookupWord(str.c_str(), ind, idict))
res_list.push_back( res_list.push_back(
TSearchResult(dict_name(idict), TSearchResult(dict_name(idict),
@@ -199,11 +199,11 @@ void Library::LookupWithRule(const string &str, TSearchResultList& res_list)
{ {
std::vector<gchar *> match_res((MAX_MATCH_ITEM_PER_LIB) * ndicts()); std::vector<gchar *> match_res((MAX_MATCH_ITEM_PER_LIB) * ndicts());
gint nfound=Libs::LookupWithRule(str.c_str(), &match_res[0]); const gint nfound = Libs::LookupWithRule(str.c_str(), &match_res[0]);
if (!nfound) if (!nfound)
return; return;
for (gint i=0; i<nfound; ++i) { for (gint i = 0; i < nfound; ++i) {
SimpleLookup(match_res[i], res_list); SimpleLookup(match_res[i], res_list);
g_free(match_res[i]); g_free(match_res[i]);
} }
@@ -214,8 +214,8 @@ void Library::LookupData(const string &str, TSearchResultList& res_list)
std::vector<std::vector<gchar *> > drl(ndicts()); std::vector<std::vector<gchar *> > drl(ndicts());
if (!Libs::LookupData(str.c_str(), &drl[0])) if (!Libs::LookupData(str.c_str(), &drl[0]))
return; return;
for (int idict=0; idict<ndicts(); ++idict) for (int idict = 0; idict < ndicts(); ++idict)
for (std::vector<gchar *>::size_type j=0; j<drl[idict].size(); ++j) { for (std::vector<gchar *>::size_type j=0; j < drl[idict].size(); ++j) {
SimpleLookup(drl[idict][j], res_list); SimpleLookup(drl[idict][j], res_list);
g_free(drl[idict][j]); g_free(drl[idict][j]);
} }
@@ -237,51 +237,52 @@ void Library::print_search_result(FILE *out, const TSearchResult & res)
utf8_output ? res.exp.c_str() : loc_exp.c_str()); utf8_output ? res.exp.c_str() : loc_exp.c_str());
} }
class sdcv_pager { namespace {
public: class sdcv_pager {
sdcv_pager(bool ignore_env=false) { public:
output=stdout; sdcv_pager(bool ignore_env=false) {
if (ignore_env) output = stdout;
return; if (ignore_env)
const gchar *pager=g_getenv("SDCV_PAGER"); return;
if (pager && (output=popen(pager, "w"))==NULL) { const gchar *pager = g_getenv("SDCV_PAGER");
perror(_("popen failed")); if (pager && (output = popen(pager, "w")) == nullptr) {
output=stdout; perror(_("popen failed"));
} output = stdout;
} }
~sdcv_pager() { }
if (output!=stdout) sdcv_pager(const sdcv_pager&) = delete;
fclose(output); sdcv_pager& operator=(const sdcv_pager&) = delete;
} ~sdcv_pager() {
FILE *get_stream() { return output; } if (output != stdout)
private: fclose(output);
FILE *output; }
}; FILE *get_stream() { return output; }
private:
FILE *output;
};
}
bool Library::process_phrase(const char *loc_str, read_line &io, bool force) bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force)
{ {
if (NULL==loc_str) if (nullptr==loc_str)
return true; return true;
std::string query; std::string query;
analyze_query(loc_str, query); analyze_query(loc_str, query);
if (!query.empty()) if (!query.empty())
io.add_to_history(query.c_str()); io.add_to_history(query.c_str());
gsize bytes_read; gsize bytes_read;
gsize bytes_written; gsize bytes_written;
GError *err=NULL; GError *err = nullptr;
char *str=NULL; char *str = nullptr;
if (!utf8_input) if (!utf8_input)
str=g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err); str = g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, &err);
else else
str=g_strdup(loc_str); str = g_strdup(loc_str);
if (NULL==str) { if (nullptr==str) {
fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str); fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str);
fprintf(stderr, "%s\n", err->message); fprintf(stderr, "%s\n", err->message);
g_error_free(err); g_error_free(err);
@@ -290,11 +291,9 @@ bool Library::process_phrase(const char *loc_str, read_line &io, bool force)
if (str[0]=='\0') if (str[0]=='\0')
return true; return true;
TSearchResultList res_list; TSearchResultList res_list;
switch (analyze_query(str, query)) { switch (analyze_query(str, query)) {
case qtFUZZY: case qtFUZZY:
LookupWithFuzzy(query, res_list); LookupWithFuzzy(query, res_list);
@@ -318,20 +317,19 @@ bool Library::process_phrase(const char *loc_str, read_line &io, bool force)
/* try to be more clever, if there are /* try to be more clever, if there are
one or zero results per dictionary show all one or zero results per dictionary show all
*/ */
bool show_all_results=true; bool show_all_results = true;
typedef std::map< string, int, std::less<string> > DictResMap; typedef std::map< string, int, std::less<string> > DictResMap;
if (!force) { if (!force) {
DictResMap res_per_dict; DictResMap res_per_dict;
for(TSearchResultList::iterator ptr=res_list.begin(); ptr!=res_list.end(); ++ptr){ for (const TSearchResult& search_res : res_list) {
std::pair<DictResMap::iterator, DictResMap::iterator> r = auto r = res_per_dict.equal_range(search_res.bookname);
res_per_dict.equal_range(ptr->bookname);
DictResMap tmp(r.first, r.second); DictResMap tmp(r.first, r.second);
if (tmp.empty()) //there are no yet such bookname in map if (tmp.empty()) //there are no yet such bookname in map
res_per_dict.insert(DictResMap::value_type(ptr->bookname, 1)); res_per_dict.insert(DictResMap::value_type(search_res.bookname, 1));
else { else {
++((tmp.begin())->second); ++((tmp.begin())->second);
if (tmp.begin()->second>1) { if (tmp.begin()->second > 1) {
show_all_results=false; show_all_results = false;
break; break;
} }
} }
@@ -341,25 +339,24 @@ bool Library::process_phrase(const char *loc_str, read_line &io, bool force)
if (!show_all_results && !force) { if (!show_all_results && !force) {
printf(_("Found %zu items, similar to %s.\n"), res_list.size(), printf(_("Found %zu items, similar to %s.\n"), res_list.size(),
utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); utf8_output ? str : utf8_to_locale_ign_err(str).c_str());
for (size_t i=0; i<res_list.size(); ++i) { for (size_t i = 0; i < res_list.size(); ++i) {
string loc_bookname, loc_def; const std::string loc_bookname = utf8_to_locale_ign_err(res_list[i].bookname);
loc_bookname=utf8_to_locale_ign_err(res_list[i].bookname); const std::string loc_def = utf8_to_locale_ign_err(res_list[i].def);
loc_def=utf8_to_locale_ign_err(res_list[i].def);
printf("%zu)%s-->%s\n", i, printf("%zu)%s-->%s\n", i,
utf8_output ? res_list[i].bookname.c_str() : loc_bookname.c_str(), utf8_output ? res_list[i].bookname.c_str() : loc_bookname.c_str(),
utf8_output ? res_list[i].def.c_str() : loc_def.c_str()); utf8_output ? res_list[i].def.c_str() : loc_def.c_str());
} }
int choise; int choise;
std::auto_ptr<read_line> choice_readline(create_readline_object()); std::unique_ptr<IReadLine> choice_readline(create_readline_object());
for (;;) { for (;;) {
string str_choise; std::string str_choise;
choice_readline->read(_("Your choice[-1 to abort]: "), str_choise); choice_readline->read(_("Your choice[-1 to abort]: "), str_choise);
sscanf(str_choise.c_str(), "%d", &choise); sscanf(str_choise.c_str(), "%d", &choise);
if (choise>=0 && choise<int(res_list.size())) { if (choise >= 0 && choise < int(res_list.size())) {
sdcv_pager pager; sdcv_pager pager;
print_search_result(pager.get_stream(), res_list[choise]); print_search_result(pager.get_stream(), res_list[choise]);
break; break;
} else if (choise==-1){ } else if (choise == -1){
break; break;
} else } else
printf(_("Invalid choice.\nIt must be from 0 to %zu or -1.\n"), printf(_("Invalid choice.\nIt must be from 0 to %zu or -1.\n"),
@@ -369,8 +366,8 @@ bool Library::process_phrase(const char *loc_str, read_line &io, bool force)
sdcv_pager pager(force); sdcv_pager pager(force);
fprintf(pager.get_stream(), _("Found %zu items, similar to %s.\n"), fprintf(pager.get_stream(), _("Found %zu items, similar to %s.\n"),
res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str()); res_list.size(), utf8_output ? str : utf8_to_locale_ign_err(str).c_str());
for (PSearchResult ptr=res_list.begin(); ptr!=res_list.end(); ++ptr) for (const TSearchResult& search_res : res_list)
print_search_result(pager.get_stream(), *ptr); print_search_result(pager.get_stream(), search_res);
} }
} else { } else {

View File

@@ -1,11 +1,10 @@
#ifndef _LIBWRAPPER_HPP_ #pragma once
#define _LIBWRAPPER_HPP_
#include <string> #include <string>
#include <vector> #include <vector>
#include "file.hpp" #include "file.hpp"
#include "lib.h" #include "lib.hpp"
#include "readline.hpp" #include "readline.hpp"
using std::string; using std::string;
@@ -24,8 +23,7 @@ struct TSearchResult {
} }
}; };
typedef vector<TSearchResult> TSearchResultList; typedef std::vector<TSearchResult> TSearchResultList;
typedef TSearchResultList::iterator PSearchResult;
//this class is wrapper around Dicts class for easy use //this class is wrapper around Dicts class for easy use
//of it //of it
@@ -34,7 +32,7 @@ public:
Library(bool uinput, bool uoutput) : Library(bool uinput, bool uoutput) :
utf8_input(uinput), utf8_output(uoutput) {} utf8_input(uinput), utf8_output(uoutput) {}
bool process_phrase(const char *loc_str, read_line &io, bool force=false); bool process_phrase(const char *loc_str, IReadLine &io, bool force=false);
private: private:
bool utf8_input, utf8_output; bool utf8_input, utf8_output;
@@ -45,4 +43,3 @@ private:
void print_search_result(FILE *out, const TSearchResult & res); void print_search_result(FILE *out, const TSearchResult & res);
}; };
#endif//!_LIBWRAPPER_HPP_

View File

@@ -35,65 +35,67 @@
#include "readline.hpp" #include "readline.hpp"
#ifndef WITH_READLINE #ifndef WITH_READLINE
namespace {
static bool stdio_getline(FILE *in, std::string & str)
{
str.clear();
int ch;
while ((ch=fgetc(in)) != EOF && ch != '\n')
str += ch;
static bool stdio_getline(FILE *in, std::string & str) return EOF != ch;
{ }
str.clear();
int ch; class dummy_readline : public IReadLine {
while ((ch=fgetc(in))!=EOF && ch!='\n') public:
str+=ch; bool read(const string& banner, string& line) override {
if (EOF==ch) printf("%s", banner.c_str());
return false; return stdio_getline(stdin, line);
return true; }
};
} }
class dummy_readline : public read_line {
public:
bool read(const string& banner, string& line) {
printf("%s", banner.c_str());
return stdio_getline(stdin, line);
}
};
#else #else
class real_readline : public read_line { namespace {
class real_readline : public IReadLine {
public: public:
real_readline() real_readline() {
{ rl_readline_name = "sdcv";
rl_readline_name = "sdcv"; using_history();
using_history(); const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
string histname=(string(g_get_home_dir())+G_DIR_SEPARATOR+".sdcv_history"); read_history(histname.c_str());
read_history(histname.c_str());; }
}
~real_readline()
{
string histname=(string(g_get_home_dir())+G_DIR_SEPARATOR+".sdcv_history");
write_history(histname.c_str());
const gchar *hist_size_str=g_getenv("SDCV_HISTSIZE");
int hist_size;
if (!hist_size_str || sscanf(hist_size_str, "%d", &hist_size)<1)
hist_size=2000;
history_truncate_file(histname.c_str(), hist_size);
}
bool read(const string &banner, string& line)
{
char *phrase=NULL;
phrase=readline(banner.c_str());
if (phrase) {
line=phrase;
free(phrase);
return true;
}
return false;
}
void add_to_history(const std::string& phrase) { add_history(phrase.c_str()); }
};
~real_readline() {
const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
write_history(histname.c_str());
const gchar *hist_size_str=g_getenv("SDCV_HISTSIZE");
int hist_size;
if (!hist_size_str || sscanf(hist_size_str, "%d", &hist_size)<1)
hist_size = 2000;
history_truncate_file(histname.c_str(), hist_size);
}
bool read(const std::string &banner, std::string& line) override {
char *phrase = nullptr;
phrase = readline(banner.c_str());
if (phrase) {
line = phrase;
free(phrase);
return true;
}
return false;
}
void add_to_history(const std::string& phrase) override {
add_history(phrase.c_str());
}
};
}
#endif//WITH_READLINE #endif//WITH_READLINE
read_line *create_readline_object() IReadLine *create_readline_object()
{ {
#ifdef WITH_READLINE #ifdef WITH_READLINE
return new real_readline; return new real_readline;

View File

@@ -1,16 +1,14 @@
#ifndef _READLINE_HPP_ #pragma once
#define _READLINE_HPP_
#include <string> #include <string>
using std::string;
class read_line { class IReadLine {
public: public:
virtual ~read_line() {} virtual ~IReadLine() {}
virtual bool read(const string &banner, string& line)=0; virtual bool read(const std::string &banner, std::string& line) = 0;
virtual void add_to_history(const std::string& phrase) {} virtual void add_to_history(const std::string& phrase) {}
}; };
extern string sdcv_readline; extern std::string sdcv_readline;
extern read_line *create_readline_object(); extern IReadLine *create_readline_object();
#endif//!_READLINE_HPP_