diff --git a/wordref/src/HttpReader.cpp b/wordref/src/HttpReader.cpp index c3fb30e..5a7f2a5 100644 --- a/wordref/src/HttpReader.cpp +++ b/wordref/src/HttpReader.cpp @@ -20,6 +20,8 @@ along with this program. If not, see . #include "HttpReader.hpp" #include #include +#include +#include namespace { ///------------------------------------------------------------------------ @@ -32,6 +34,30 @@ namespace { that->append(parData, effectiveWrite); return effectiveWrite; } + + std::string GetCleanWord (CURL* parCurl, std::wstring parWord) __attribute__((pure)); + + ///------------------------------------------------------------------------- + ///------------------------------------------------------------------------- + std::string GetCleanWord (CURL* parCurl, std::wstring parWord) { + class CurlFree { + public: + CurlFree ( void ) noexcept = default; + void operator() ( char* parDele ) const { curl_free(parDele); } + }; + + boost::algorithm::trim_all(parWord); + const size_t maxMultibSize = parWord.size() * 4 + 1; + const std::unique_ptr memForMultib(new char[maxMultibSize]); + + const size_t wctombsRet = std::wcstombs(memForMultib.get(), parWord.c_str(), maxMultibSize); + if (EILSEQ == wctombsRet) + throw std::runtime_error("Can't convert received string to multibyte, wcstombs() failed"); + + const std::unique_ptr urlEncoded(curl_easy_escape(parCurl, memForMultib.get(), static_cast(wctombsRet))); + std::string retVal(urlEncoded.get()); + return retVal; + } } //unnamed namespace struct HttpReader::LocalData { @@ -84,3 +110,15 @@ std::string HttpReader::GetPage (const std::string& parAddress) const { } return localString; } + +///----------------------------------------------------------------------------- +///----------------------------------------------------------------------------- +std::string HttpReader::UrlEncode (const wchar_t* parWord) { + return GetCleanWord(m_localData->curl, parWord); +} + +///----------------------------------------------------------------------------- +///----------------------------------------------------------------------------- +std::string HttpReader::UrlEncode (const std::wstring& parWord) { + return GetCleanWord(m_localData->curl, parWord); +} diff --git a/wordref/src/HttpReader.hpp b/wordref/src/HttpReader.hpp index 53f06e0..41b1057 100644 --- a/wordref/src/HttpReader.hpp +++ b/wordref/src/HttpReader.hpp @@ -7,6 +7,8 @@ public: ~HttpReader ( void ) noexcept; std::string GetPage ( const std::string& parAddress ) const; + std::string UrlEncode ( const wchar_t* parWord ) __attribute__((pure)); + std::string UrlEncode ( const std::wstring& parWord ) __attribute__((pure)); private: struct LocalData; diff --git a/wordref/src/WordReference.cpp b/wordref/src/WordReference.cpp index 9131cd9..bb52388 100644 --- a/wordref/src/WordReference.cpp +++ b/wordref/src/WordReference.cpp @@ -21,7 +21,6 @@ along with this program. If not, see . #include "HttpReader.hpp" #include "libjson.h" #include -#include namespace { const char* ApiVersion = "0.8"; @@ -44,25 +43,14 @@ namespace { std::pair("tr", "Turkish") }; - std::string GetCleanWord (std::string parWord) __attribute__((pure)); - ///------------------------------------------------------------------------- ///------------------------------------------------------------------------- - std::string GetCleanWord (std::string parWord) { - boost::algorithm::trim_all(parWord); - std::replace(parWord.begin(), parWord.end(), ' ', '+'); - return parWord; - } - - ///------------------------------------------------------------------------- - ///------------------------------------------------------------------------- - JSONNode QueryJSon (const std::string& parFrom, const std::string& parTo, const std::string& parKey, const std::string& parWord) { + JSONNode QueryJSon (HttpReader& parHttp, const std::string& parFrom, const std::string& parTo, const std::string& parKey, const std::wstring& parWord) { std::ostringstream oss; oss << "http://api.wordreference.com/" << ApiVersion << "/" - << parKey << "/json/" << parFrom << parTo << "/" << GetCleanWord(parWord); + << parKey << "/json/" << parFrom << parTo << "/" << parHttp.UrlEncode(parWord); - HttpReader http; - std::string jsonResponse(http.GetPage(oss.str())); + std::string jsonResponse(parHttp.GetPage(oss.str())); return libjson::parse(libjson::to_json_string(jsonResponse)); } @@ -112,6 +100,7 @@ ErrBadLanguage::ErrBadLanguage (std::string&& parMessage) : ///----------------------------------------------------------------------------- ///----------------------------------------------------------------------------- WordReference::WordReference (const char* parFrom, const char* parTo, const char* parApiKey) : + m_httpReader(new HttpReader), m_langFrom(parFrom), m_langTo(parTo), m_apiKey(parApiKey) @@ -128,6 +117,11 @@ WordReference::WordReference (const char* parFrom, const char* parTo, const char } } +///----------------------------------------------------------------------------- +///----------------------------------------------------------------------------- +WordReference::~WordReference() { +} + ///----------------------------------------------------------------------------- ///----------------------------------------------------------------------------- const std::string& WordReference::GetLanguageCode (WordReferenceLangDirection parDir) const { @@ -143,24 +137,6 @@ const std::string& WordReference::GetLanguageName (WordReferenceLangDirection pa return SupportedLanguages.at(GetLanguageCode(parDir)); } -///----------------------------------------------------------------------------- -///----------------------------------------------------------------------------- -std::string WordReference::GetHttpLink (const char* parWord) { - std::ostringstream oss; - oss << "http://www.wordreference.com/redirect/translation.aspx?w="; - oss << GetCleanWord(parWord) << "&dict=" << m_langFrom << m_langTo; - return oss.str(); -} - -///----------------------------------------------------------------------------- -///----------------------------------------------------------------------------- -std::string WordReference::GetHttpLink (const std::string& parWord) { - std::ostringstream oss; - oss << "http://www.wordreference.com/redirect/translation.aspx?w="; - oss << GetCleanWord(parWord) << "&dict=" << m_langFrom << m_langTo; - return oss.str(); -} - ///----------------------------------------------------------------------------- ///----------------------------------------------------------------------------- std::string WordReference::GetApiVersion() { @@ -169,8 +145,8 @@ std::string WordReference::GetApiVersion() { ///----------------------------------------------------------------------------- ///----------------------------------------------------------------------------- -void WordReference::Translate (const std::string& parWord, std::wostream& parStream) { - JSONNode root = QueryJSon(m_langFrom, m_langTo, m_apiKey, parWord); +void WordReference::Translate (const std::wstring& parWord, std::wostream& parStream) { + JSONNode root = QueryJSon(*m_httpReader, m_langFrom, m_langTo, m_apiKey, parWord); for (JSONNode::const_iterator itCur = root.begin(), itCurEND = root.end(); itCur != itCurEND; ++itCur) { const std::wstring nodeName(libjson::to_std_wstring(itCur->name())); if (itCur->type() == JSON_NODE and nodeName.compare(0, 4, L"term") == 0) { @@ -181,3 +157,21 @@ void WordReference::Translate (const std::string& parWord, std::wostream& parStr } } } + +///----------------------------------------------------------------------------- +///----------------------------------------------------------------------------- +std::string WordReference::GetHttpLink (const wchar_t* parWord) { + std::ostringstream oss; + oss << "http://www.wordreference.com/redirect/translation.aspx?w="; + oss << m_httpReader->UrlEncode(parWord) << "&dict=" << m_langFrom << m_langTo; + return oss.str(); +} + +///----------------------------------------------------------------------------- +///----------------------------------------------------------------------------- +std::string WordReference::GetHttpLink (const std::wstring& parWord) { + std::ostringstream oss; + oss << "http://www.wordreference.com/redirect/translation.aspx?w="; + oss << m_httpReader->UrlEncode(parWord) << "&dict=" << m_langFrom << m_langTo; + return oss.str(); +} diff --git a/wordref/src/WordReference.hpp b/wordref/src/WordReference.hpp index 71c131a..3ac396e 100644 --- a/wordref/src/WordReference.hpp +++ b/wordref/src/WordReference.hpp @@ -19,6 +19,8 @@ along with this program. If not, see . #ifndef id75A4E59ADE4649F7A4A56F91C5886405 #define id75A4E59ADE4649F7A4A56F91C5886405 +class HttpReader; + enum WordReferenceLangDirection { WordRefLangFrom, WordRefLangTo @@ -34,17 +36,19 @@ public: class WordReference { public: + WordReference ( void ) = delete; WordReference ( const char* parFrom, const char* parTo, const char* parApiKey ); - ~WordReference ( void ) = default; + ~WordReference ( void ); const std::string& GetLanguageCode ( WordReferenceLangDirection parDir ) const; const std::string& GetLanguageName ( WordReferenceLangDirection parDir ) const; - std::string GetHttpLink ( const char* parWord ); - std::string GetHttpLink ( const std::string& parWord ); static std::string GetApiVersion ( void ); - void Translate ( const std::string& parWord, std::wostream& parStream ); + std::string GetHttpLink ( const wchar_t* parWord ); + std::string GetHttpLink ( const std::wstring& parWord ); + void Translate ( const std::wstring& parWord, std::wostream& parStream ); private: + const std::unique_ptr m_httpReader; std::string m_langFrom; std::string m_langTo; std::string m_apiKey; diff --git a/wordref/src/main.cpp b/wordref/src/main.cpp index 8b0408b..4c6924a 100644 --- a/wordref/src/main.cpp +++ b/wordref/src/main.cpp @@ -102,8 +102,9 @@ int main (int parArgc, const char* const parArgv[]) { } WordReference wref("en", "it", DefApiKey); - wref.Translate("house", std::wcout); + wref.Translate(L"house", std::wcout); - std::wcout << wref.GetHttpLink("north face") << L"\nWritten by King_DuckZ; © WordReference.com" << std::endl; + std::cout << wref.GetHttpLink(L"north face") << "\n"; + std::wcout << L"Written by King_DuckZ; © WordReference.com" << std::endl; return 0; }