Character conversion code put into a file on its own.
Character conversion relies on the setlocale(LC_TYPE, "") in main(), but maybe there are better ways of doing this.
This commit is contained in:
parent
2299247e77
commit
21476e0a5d
9 changed files with 144 additions and 17 deletions
|
@ -11,6 +11,7 @@ project (WordReference CXX)
|
|||
|
||||
message(STATUS "Configuring ${PROJECT_NAME} for ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
add_definitions("-DUNICODE")
|
||||
set (${PROJECT_NAME}_Version_Major 0)
|
||||
set (${PROJECT_NAME}_Version_Minor 1)
|
||||
set (${PROJECT_NAME}_App_Name "\"${PROJECT_NAME}\"")
|
||||
|
|
|
@ -22,6 +22,7 @@ add_executable(${PROJECT_NAME}
|
|||
src/main.cpp
|
||||
src/WordReference.cpp
|
||||
src/HttpReader.cpp
|
||||
src/CharConv.cpp
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${Boost_LIBRARIES}
|
||||
|
|
98
wordref/src/CharConv.cpp
Normal file
98
wordref/src/CharConv.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "main.hpp"
|
||||
#include "CharConv.hpp"
|
||||
#include <cstdlib>
|
||||
#include <cwchar>
|
||||
#include <cstring>
|
||||
#include <iconv.h>
|
||||
#include <clocale>
|
||||
|
||||
namespace cconv {
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
ErrCantConvert::ErrCantConvert (const std::string& parFrom, const std::string& parTo) :
|
||||
std::domain_error(std::string("Can't convert from \"") + parFrom + "\" to \"" + parTo + "\"")
|
||||
{
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
ErrCantConvert::ErrCantConvert (const char* parFrom, const char* parTo) :
|
||||
std::domain_error(std::string("Can't convert from \"") + parFrom + "\" to \"" + parTo + "\"")
|
||||
{
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
std::wstring MultibyteToWide (const std::string& parMultiByte) {
|
||||
return MultibyteToWide(parMultiByte.c_str(), parMultiByte.size());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
std::wstring MultibyteToWide (const char* parMultiByte) {
|
||||
return MultibyteToWide(parMultiByte, std::strlen(parMultiByte));
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///See: http://www.lemoda.net/c/iconv-example/iconv-example.html
|
||||
///-------------------------------------------------------------------------
|
||||
std::wstring MultibyteToWide (const char* parMultiByte, size_t parLen) {
|
||||
const size_t maxCount = parLen + 1;
|
||||
|
||||
//const std::unique_ptr<char[]> iconvMem(new char[maxCount * sizeof(wchar_t)]);
|
||||
//{
|
||||
// const char* const localeFrom = "UTF-8"; //std::setlocale(LC_CTYPE, nullptr);
|
||||
// static const char* const localeTo = "WCHAR_T";
|
||||
// const iconv_t iconvHandle = iconv_open(localeFrom, localeTo);
|
||||
// if (reinterpret_cast<iconv_t>(-1) == iconvHandle) {
|
||||
// if (EINVAL == errno)
|
||||
// throw ErrCantConvert(localeFrom, localeTo);
|
||||
// else
|
||||
// std::runtime_error("Error initializing iconv");
|
||||
// }
|
||||
|
||||
// const std::unique_ptr<char[]> multibyteCopy(new char[parLen + 1]);
|
||||
// std::copy(parMultiByte, parMultiByte + parLen + 1, multibyteCopy.get());
|
||||
// size_t srcLen = parLen;
|
||||
// size_t dstLen = maxCount;
|
||||
// char* dstMem = iconvMem.get();
|
||||
// char* srcMem = multibyteCopy.get();
|
||||
// const size_t iconvRetVal = iconv(iconvHandle, &srcMem, &srcLen, &dstMem, &dstLen);
|
||||
|
||||
// const int closeRetVal = iconv_close(iconvHandle);
|
||||
// if (0 != closeRetVal)
|
||||
// throw std::runtime_error("iconv_close() failed");
|
||||
//}
|
||||
const std::unique_ptr<wchar_t[]> buff(new wchar_t[maxCount]);
|
||||
const size_t charCount = std::mbstowcs(buff.get(), parMultiByte, maxCount);
|
||||
if (charCount == maxCount)
|
||||
buff[maxCount - 1] = L'\0';
|
||||
else if (static_cast<size_t>(-1) == charCount)
|
||||
throw std::runtime_error("Can't convert received string, mbstowcs() returned an error");
|
||||
return std::wstring(buff.get());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
std::string WideToMultibyte (const std::wstring& parWide) {
|
||||
return WideToMultibyte(parWide.c_str(), parWide.size());
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
std::string WideToMultibyte (const wchar_t* parWide) {
|
||||
return WideToMultibyte(parWide, std::wcslen(parWide));
|
||||
}
|
||||
|
||||
///-------------------------------------------------------------------------
|
||||
///-------------------------------------------------------------------------
|
||||
std::string WideToMultibyte (const wchar_t* parWide, size_t parLen) {
|
||||
const size_t maxMultibSize = parLen * 4 + 1;
|
||||
const std::unique_ptr<char[]> memForMultib(new char[maxMultibSize]);
|
||||
|
||||
const size_t wctombsRet = std::wcstombs(memForMultib.get(), parWide, maxMultibSize);
|
||||
if (EILSEQ == wctombsRet or static_cast<size_t>(-1) == wctombsRet)
|
||||
throw std::runtime_error("Can't convert received string to multibyte, wcstombs() failed");
|
||||
return std::string(memForMultib.get(), wctombsRet);
|
||||
}
|
||||
} //namespace cconv
|
21
wordref/src/CharConv.hpp
Normal file
21
wordref/src/CharConv.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef idA800F41881384E6980F1D79AFCCA0338
|
||||
#define idA800F41881384E6980F1D79AFCCA0338
|
||||
|
||||
namespace cconv {
|
||||
class ErrCantConvert : public std::domain_error {
|
||||
public:
|
||||
ErrCantConvert ( const std::string& parFrom, const std::string& parTo );
|
||||
ErrCantConvert ( const char* parFrom, const char* parTo );
|
||||
~ErrCantConvert ( void ) noexcept = default;
|
||||
};
|
||||
|
||||
std::wstring MultibyteToWide ( const std::string& parMultiByte ) pure_function;
|
||||
std::wstring MultibyteToWide ( const char* parMultiByte ) pure_function;
|
||||
std::wstring MultibyteToWide ( const char* parMultiByte, size_t parLen ) pure_function;
|
||||
|
||||
std::string WideToMultibyte ( const std::wstring& parWide ) pure_function;
|
||||
std::string WideToMultibyte ( const wchar_t* parWide ) pure_function;
|
||||
std::string WideToMultibyte ( const wchar_t* parWide, size_t parLen ) pure_function;
|
||||
} //namespace cconv
|
||||
|
||||
#endif
|
|
@ -18,10 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include "main.hpp"
|
||||
#include "HttpReader.hpp"
|
||||
#include "CharConv.hpp"
|
||||
#include <curl/curl.h>
|
||||
#include <sstream>
|
||||
#include <boost/algorithm/string/trim_all.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace {
|
||||
///------------------------------------------------------------------------
|
||||
|
@ -47,14 +47,8 @@ namespace {
|
|||
};
|
||||
|
||||
boost::algorithm::trim_all(parWord);
|
||||
const size_t maxMultibSize = parWord.size() * 4 + 1;
|
||||
const std::unique_ptr<char[]> 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<char, CurlFree> urlEncoded(curl_easy_escape(parCurl, memForMultib.get(), static_cast<int>(wctombsRet)));
|
||||
const std::string wordMultibyte(cconv::WideToMultibyte(parWord));
|
||||
const std::unique_ptr<char, CurlFree> urlEncoded(curl_easy_escape(parCurl, wordMultibyte.c_str(), static_cast<int>(wordMultibyte.size())));
|
||||
std::string retVal(urlEncoded.get());
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ ErrBadLanguage::ErrBadLanguage (std::string&& parMessage) :
|
|||
|
||||
///-----------------------------------------------------------------------------
|
||||
///-----------------------------------------------------------------------------
|
||||
WordReference::WordReference (const char* parFrom, const char* parTo, const char* parApiKey) :
|
||||
WordReference::WordReference (const std::string& parFrom, const std::string& parTo, const char* parApiKey) :
|
||||
m_httpReader(new HttpReader),
|
||||
m_langFrom(parFrom),
|
||||
m_langTo(parTo),
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
class WordReference {
|
||||
public:
|
||||
WordReference ( void ) = delete;
|
||||
WordReference ( const char* parFrom, const char* parTo, const char* parApiKey );
|
||||
WordReference ( const std::string& parFrom, const std::string& parTo, const char* parApiKey );
|
||||
~WordReference ( void );
|
||||
|
||||
const std::string& GetLanguageCode ( WordReferenceLangDirection parDir ) const;
|
||||
|
|
|
@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include "main.hpp"
|
||||
#include "WordReference.hpp"
|
||||
#include "CharConv.hpp"
|
||||
#include <iostream>
|
||||
#include <boost/program_options/cmdline.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
@ -51,9 +52,9 @@ namespace {
|
|||
oss << "Usage is " << GetBaseName(parArgv[0]) << " [options] <from language> <to language> <search term>; parameters";
|
||||
boost::program_options::options_description desc(oss.str());
|
||||
boost::program_options::positional_options_description positionals;
|
||||
positionals.add("source-lang", 0);
|
||||
positionals.add("source-lang", 1);
|
||||
positionals.add("dest-lang", 1);
|
||||
positionals.add("word", 2);
|
||||
positionals.add("word", -1);
|
||||
|
||||
boost::program_options::options_description hidden("hidden options");
|
||||
hidden.add_options()
|
||||
|
@ -72,7 +73,8 @@ namespace {
|
|||
boost::program_options::store(boost::program_options::command_line_parser(parArgc, parArgv).options(commandLine).positional(positionals).run(), parVarMap);
|
||||
boost::program_options::notify(parVarMap);
|
||||
bool shownSomething = false;
|
||||
if (parVarMap.count("help")) {
|
||||
if (parVarMap.count("help") or parVarMap.count("source-lang") != 1 or
|
||||
parVarMap.count("dest-lang") != 1 or parVarMap.count("word") == 0) {
|
||||
std::cout << desc << "\n";
|
||||
shownSomething = true;
|
||||
}
|
||||
|
@ -83,6 +85,8 @@ namespace {
|
|||
///-----------------------------------------------------------------------------
|
||||
///-----------------------------------------------------------------------------
|
||||
int main (int parArgc, const char* const parArgv[]) {
|
||||
//std::setlocale(LC_CTYPE, "UTF-8");
|
||||
std::setlocale(LC_CTYPE, "");
|
||||
boost::program_options::variables_map vm;
|
||||
if (GetCommandLine(vm, parArgc, parArgv))
|
||||
return 0;
|
||||
|
@ -101,10 +105,16 @@ int main (int parArgc, const char* const parArgv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
WordReference wref("en", "it", DefApiKey);
|
||||
wref.Translate(L"house", std::wcout);
|
||||
{
|
||||
const std::string langFrom(vm["source-lang"].as<std::string>());
|
||||
const std::string langTo(vm["dest-lang"].as<std::string>());
|
||||
const std::wstring searchWord(cconv::MultibyteToWide(vm["word"].as<std::string>()));
|
||||
|
||||
std::cout << wref.GetHttpLink(L"north face") << "\n";
|
||||
WordReference wref(langFrom, langTo, DefApiKey);
|
||||
wref.Translate(searchWord, std::wcout);
|
||||
|
||||
std::cout << wref.GetHttpLink(searchWord) << "\n";
|
||||
}
|
||||
std::wcout << L"Written by King_DuckZ; © WordReference.com" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,4 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
#define pure_function __attribute__((pure))
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue