commit
3f69e0243e
4 changed files with 307 additions and 0 deletions
@ -0,0 +1,25 @@ |
|||||
|
#ifndef DICTCC_DESV_INCLUDED |
||||
|
#define DICTCC_DESV_INCLUDED |
||||
|
|
||||
|
// Dictcc API
|
||||
|
#include "dict.h" |
||||
|
|
||||
|
namespace dictcc |
||||
|
{ |
||||
|
class desv : public dict |
||||
|
{ |
||||
|
// TODO: Implement specifics of the language here.
|
||||
|
public: |
||||
|
desv(); |
||||
|
~desv() |
||||
|
{} |
||||
|
}; |
||||
|
|
||||
|
desv::desv() |
||||
|
{ |
||||
|
d_suburl = "desv"; |
||||
|
} |
||||
|
|
||||
|
} // namespace dictcc
|
||||
|
|
||||
|
#endif // DICTCC_DESV_INCLUDED
|
@ -0,0 +1,179 @@ |
|||||
|
// STD
|
||||
|
#include <string> |
||||
|
#include <sstream> |
||||
|
#include <iostream> |
||||
|
#include <utility> |
||||
|
#include <functional> |
||||
|
#include <vector> |
||||
|
// Curl
|
||||
|
#include <curlpp/cURLpp.hpp> |
||||
|
#include <curlpp/Easy.hpp> |
||||
|
#include <curlpp/Options.hpp> |
||||
|
// Boost
|
||||
|
#include <boost/algorithm/string.hpp> |
||||
|
// Dictcc API
|
||||
|
#include "types.h" |
||||
|
#include "exceptions.h" |
||||
|
|
||||
|
#ifndef DICTCC_DICT_INCLUDED |
||||
|
#define DICTCC_DICT_INCLUDED |
||||
|
|
||||
|
namespace dictcc |
||||
|
{ |
||||
|
/*! \brief Base dictionary class.
|
||||
|
*/ |
||||
|
class dict |
||||
|
{ |
||||
|
protected: |
||||
|
static const std::string URL_HTTPS; |
||||
|
static const std::string URL_REST; |
||||
|
static const std::string QUERYA; |
||||
|
static const std::string QUERYB; |
||||
|
static const std::string QUERYC; |
||||
|
static const std::string SEPERATOR; |
||||
|
|
||||
|
protected: |
||||
|
/*! \brief Word list corresponding to one language.
|
||||
|
*/ |
||||
|
word_list_t d_wordsl0; |
||||
|
/*! \brief Word list corresponding to one language.
|
||||
|
*/ |
||||
|
word_list_t d_wordsl1; |
||||
|
curlpp::Easy d_request; |
||||
|
curlpp::Cleanup d_cleaner; |
||||
|
lang_t d_langs; |
||||
|
std::string d_suburl; |
||||
|
|
||||
|
protected: |
||||
|
void parse_answer(const std::ostringstream& os, const std::string& query, word_list_t& vec); |
||||
|
|
||||
|
protected: |
||||
|
dict(){} |
||||
|
|
||||
|
public: |
||||
|
static dict* create(const std::string langs); |
||||
|
virtual ~dict(){} |
||||
|
|
||||
|
public: |
||||
|
search_t search(std::string word); |
||||
|
static std::string langs2str(const lang_t& lt); |
||||
|
static lang_t str2langs(const std::string& str); |
||||
|
}; |
||||
|
|
||||
|
const std::string dict::URL_HTTPS = "https://"; |
||||
|
const std::string dict::URL_REST = ".dict.cc/?s="; |
||||
|
const std::string dict::QUERYA = "c1Arr = new Array"; |
||||
|
const std::string dict::QUERYB = "c2Arr = new Array"; |
||||
|
const std::string dict::QUERYC = ");"; |
||||
|
const std::string dict::SEPERATOR = "\",\""; |
||||
|
|
||||
|
void dict::parse_answer(const std::ostringstream& os, const std::string& query, word_list_t& vec) |
||||
|
{ |
||||
|
std::string page = os.str(); |
||||
|
auto lstart = page.find(query); |
||||
|
auto lend = page.find(QUERYC, lstart); |
||||
|
// No results found -> throw an exception
|
||||
|
if(lstart == -1) |
||||
|
throw(dict_no_results(__FILE__, __LINE__)); |
||||
|
lstart += query.size(); |
||||
|
// Scroll to the first character
|
||||
|
while( (page[lstart] == '\"') || (page[lstart] == ',') || (page[lstart] == '(') ) |
||||
|
lstart++; |
||||
|
// Scroll to the last character
|
||||
|
while( (page[lstart] == '\"') || (page[lstart] == ',') || (page[lstart] == '(') ) |
||||
|
lend--; |
||||
|
// Get the line.
|
||||
|
std::string line = page.substr(lstart, lend-lstart); |
||||
|
// Split it.
|
||||
|
boost::split(vec, line, boost::is_any_of(SEPERATOR), boost::token_compress_on); |
||||
|
// Last element is always empty.
|
||||
|
vec.pop_back(); |
||||
|
// Make sure, that the string termination is present.
|
||||
|
for (std::string& str : vec) { |
||||
|
if (str[str.size()-1] != '\0' ) { |
||||
|
str.append("\0"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
search_t dict::search(std::string word) |
||||
|
{ |
||||
|
std::ostringstream answer; |
||||
|
// Perform HTTP request with SSL below.
|
||||
|
try { |
||||
|
std::string dict_req = URL_HTTPS + d_suburl + URL_REST + word; |
||||
|
curlpp::options::Url url(dict_req); |
||||
|
d_request.setOpt(url); |
||||
|
answer << d_request; |
||||
|
} catch(curlpp::RuntimeError &e) { |
||||
|
std::ostringstream ss; |
||||
|
ss << e.what() << "(curlpp::RuntimeError)."; |
||||
|
throw(dict_libcurl_error(__FILE__, __LINE__, ss.str())); |
||||
|
} catch(curlpp::LogicError &e) { |
||||
|
std::ostringstream ss; |
||||
|
ss << e.what() << "(curlpp::LogicError)."; |
||||
|
throw(dict_libcurl_error(__FILE__, __LINE__, ss.str())); |
||||
|
} |
||||
|
// Convert request into word lists language one and language two respectively.
|
||||
|
try { |
||||
|
parse_answer(answer, QUERYA, d_wordsl0); |
||||
|
parse_answer(answer, QUERYB, d_wordsl1); |
||||
|
} catch (dict_no_results& e) { |
||||
|
// The parsing might go wrong.
|
||||
|
e << std::string("Could not find ") + std::string("\"") + word + std::string("\"."); |
||||
|
throw; |
||||
|
} |
||||
|
// Return a pair of references
|
||||
|
return std::make_pair(&d_wordsl0, &d_wordsl1); |
||||
|
} |
||||
|
|
||||
|
inline std::string dict::langs2str(const lang_t& lt) |
||||
|
{ |
||||
|
// TODO: Add new languages here.
|
||||
|
std::vector<std::string> str = {"DESV", "DEEN"}; |
||||
|
if (lt >= str.size()) { |
||||
|
throw(dict_lang_error(__FILE__, __LINE__)); |
||||
|
} |
||||
|
return str[lt]; |
||||
|
} |
||||
|
|
||||
|
inline lang_t dict::str2langs(const std::string& str) |
||||
|
{ |
||||
|
if (str == "DESV") { |
||||
|
return DESV; |
||||
|
} else if ( str == "DEEN") { |
||||
|
return DEEN; |
||||
|
} else { |
||||
|
throw(dict_lang_error(__FILE__, __LINE__)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class desv : public dict |
||||
|
{ |
||||
|
// TODO: Implement specifics of the language here.
|
||||
|
public: |
||||
|
desv(); |
||||
|
~desv() |
||||
|
{} |
||||
|
}; |
||||
|
|
||||
|
desv::desv() |
||||
|
{ |
||||
|
d_suburl = "desv"; |
||||
|
} |
||||
|
|
||||
|
dict* dict::create(const std::string langs) |
||||
|
{ |
||||
|
lang_t l = str2langs(langs); |
||||
|
// TODO: Add new languages here
|
||||
|
switch (l) { |
||||
|
case DESV: |
||||
|
return new desv; |
||||
|
break; |
||||
|
default: |
||||
|
throw(dict_lang_error(__FILE__, __LINE__)); |
||||
|
} |
||||
|
} |
||||
|
} // namespace dictcc
|
||||
|
|
||||
|
#endif // DICTCC_DICT_INCLUDED
|
@ -0,0 +1,77 @@ |
|||||
|
#include <string> |
||||
|
#include <sstream> |
||||
|
|
||||
|
#ifndef DICTCC_EXCEPTIONS_INCLUDED |
||||
|
#define DICTCC_EXCEPTIONS_INCLUDED |
||||
|
|
||||
|
namespace dictcc |
||||
|
{ |
||||
|
/*! \brief Exception class to be thrown if there is a general problem with the dictionary.
|
||||
|
*/ |
||||
|
class dict_exception : public std::exception |
||||
|
{ |
||||
|
private: |
||||
|
std::string d_file; |
||||
|
int d_line; |
||||
|
|
||||
|
protected: |
||||
|
std::string d_msg; |
||||
|
|
||||
|
public: |
||||
|
dict_exception(const std::string file, const int line, const std::string msg) |
||||
|
: d_msg(msg), d_file(file), d_line(line) |
||||
|
{ |
||||
|
std::ostringstream os; |
||||
|
os << d_file << ": " << d_line << ": " << d_msg; |
||||
|
d_msg = os.str(); |
||||
|
} |
||||
|
/*! \brief Get the exception identifier.
|
||||
|
*/ |
||||
|
const char* what() const noexcept |
||||
|
{ |
||||
|
return d_msg.c_str(); |
||||
|
}; |
||||
|
/*! \brief Get the naked file where the exception happened.
|
||||
|
*/ |
||||
|
std::string file() const noexcept {return d_file;} |
||||
|
/*! \brief Get line where the exception happened.
|
||||
|
*/ |
||||
|
int line() const noexcept {return d_line;} |
||||
|
}; |
||||
|
|
||||
|
/*! \brief Exception class to be thrown if no results have been found for a search.
|
||||
|
*/ |
||||
|
class dict_no_results : public dict_exception |
||||
|
{ |
||||
|
public: |
||||
|
dict_no_results(const std::string file, const int line, const std::string msg = "") |
||||
|
: dict_exception(file, line, msg) {} |
||||
|
/*! \brief Change message content of a exception, that has been thrown.
|
||||
|
*/ |
||||
|
void operator<<(const std::string& new_msg) noexcept |
||||
|
{ |
||||
|
this->d_msg += new_msg; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
/*! \brief Exception class to be thrown if there is a libcurl issue.
|
||||
|
*/ |
||||
|
class dict_libcurl_error : public dict_exception |
||||
|
{ |
||||
|
public: |
||||
|
dict_libcurl_error(const std::string file, const int line, const std::string msg) |
||||
|
: dict_exception(file, line, msg) {} |
||||
|
}; |
||||
|
|
||||
|
/*! \brief Exception class to be thrown if there is a libcurl issue.
|
||||
|
*/ |
||||
|
class dict_lang_error : public dict_exception |
||||
|
{ |
||||
|
public: |
||||
|
dict_lang_error(const std::string file, const int line, const std::string msg = "Language is not supported.") |
||||
|
: dict_exception(file, line, msg) {} |
||||
|
}; |
||||
|
|
||||
|
} // namespace dictcc
|
||||
|
|
||||
|
#endif // DICTCC_EXCEPTIONS_INCLUDED
|
@ -0,0 +1,26 @@ |
|||||
|
#include <string> |
||||
|
#include <utility> |
||||
|
#include <functional> |
||||
|
#include <vector> |
||||
|
|
||||
|
#ifndef DICTCC_TYPES_INCLUDED |
||||
|
#define DICTCC_TYPES_INCLUDED |
||||
|
|
||||
|
namespace dictcc |
||||
|
{ |
||||
|
/*! \brief List of words in one language.
|
||||
|
*/ |
||||
|
typedef std::vector<std::string> word_list_t; |
||||
|
/*! \brief Pair of two word lists with corresponding word/sentence pairs (translations) resulting from a search string.
|
||||
|
*/ |
||||
|
typedef std::pair<word_list_t*, word_list_t*> search_t; |
||||
|
/*! \brief Supported language pairs.
|
||||
|
*/ |
||||
|
typedef enum |
||||
|
{ |
||||
|
DESV, |
||||
|
DEEN |
||||
|
} lang_t; |
||||
|
} // namespace dictcc
|
||||
|
|
||||
|
#endif // DICTCC_TYPES_INCLUDED
|
Loading…
Reference in new issue