Skip to content

Commit

Permalink
Merge pull request #6 from jeffreyhorner/master
Browse files Browse the repository at this point in the history
Initialized Hunspell Spellchecker object with an iconvstr function
  • Loading branch information
jjallaire committed Feb 4, 2012
2 parents b5dd021 + 116ee24 commit ce79138
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 35 deletions.
15 changes: 12 additions & 3 deletions src/cpp/core/include/core/spelling/SpellChecker.hpp
Expand Up @@ -19,6 +19,7 @@

#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>


namespace core {
Expand All @@ -32,13 +33,21 @@ class SpellChecker : boost::noncopyable
{
public:
virtual ~SpellChecker() {}
virtual bool checkSpelling(const std::string& word) = 0;
virtual void suggestionList(const std::string& word, std::vector<std::string>* pSugs) = 0;
virtual Error checkSpelling(const std::string& word, bool *pCorrect) = 0;
virtual Error suggestionList(const std::string& word, std::vector<std::string>* pSugs) = 0;
virtual Error analyzeWord(const std::string& word, std::vector<std::string>* pResult) = 0;
};

typedef boost::function<core::Error(const std::string&,
const std::string&,
const std::string&,
bool,
std::string*)> IconvstrFunction;

core::Error createHunspell(const core::FilePath& affPath,
const core::FilePath& dicPath,
boost::shared_ptr<SpellChecker>* pHunspell);
boost::shared_ptr<SpellChecker>* pHunspell,
const IconvstrFunction& iconvstrFunc);


} // namespace spelling
Expand Down
74 changes: 58 additions & 16 deletions src/cpp/core/spelling/HunspellSpellChecker.cpp
Expand Up @@ -50,58 +50,100 @@ class HunspellSpellChecker : public SpellChecker
}
}

Error initialize(const FilePath& affPath, const FilePath& dicPath)
Error initialize(const FilePath& affPath,
const FilePath& dicPath,
const IconvstrFunction& iconvstrFunc)
{
// validate that dictionaries exist
if (!affPath.exists())
return core::fileNotFoundError(affPath, ERROR_LOCATION);
if (!dicPath.exists())
return core::fileNotFoundError(dicPath, ERROR_LOCATION);

// initialize hunspell and return success
// initialize hunspell, iconvstrFunc_, encoding_, and return success
pHunspell_.reset(new Hunspell(affPath.absolutePath().c_str(),
dicPath.absolutePath().c_str()));
iconvstrFunc_ = iconvstrFunc;
encoding_ = pHunspell_->get_dic_encoding();
return Success();
}

private:

// helpers
void copyAndFreeHunspellVector(std::vector<std::string>* pVec,
char **wlst,
int len)
{
for (int i=0; i < len; i++)
{
pVec->push_back(wlst[i]);
}
pHunspell_->free_list(&wlst, len);
}

public:
bool checkSpelling(const std::string& word)
Error checkSpelling(const std::string& word, bool *pCorrect)
{
std::string encoded;
Error error = iconvstrFunc_(word,"UTF-8",encoding_,false,&encoded);
if (error)
return error;

*pCorrect = pHunspell_->spell(encoded.c_str());
return Success();
}

Error suggestionList(const std::string& word, std::vector<std::string>* pSug)
{
return pHunspell_->spell(word.c_str());
std::string encoded;
Error error = iconvstrFunc_(word,"UTF-8",encoding_,false,&encoded);
if (error)
return error;

char ** wlst;
int ns = pHunspell_->suggest(&wlst,encoded.c_str());
copyAndFreeHunspellVector(pSug,wlst,ns);
return Success();
}

void suggestionList(const std::string& word, std::vector<std::string>* pSug)
Error analyzeWord(const std::string& word, std::vector<std::string>* pResult)
{
char ** wlst;
int ns = pHunspell_->suggest(&wlst,word.c_str());
for (int i=0; i < ns; i++)
{
pSug->push_back(wlst[i]);
}
pHunspell_->free_list(&wlst, ns);
std::string encoded;
Error error = iconvstrFunc_(word,"UTF-8",encoding_,false,&encoded);
if (error)
return error;

char ** wlst;
int ns = pHunspell_->analyze(&wlst,encoded.c_str());
copyAndFreeHunspellVector(pResult,wlst,ns);
return Success();
}


private:
boost::scoped_ptr<Hunspell> pHunspell_;
IconvstrFunction iconvstrFunc_;
std::string encoding_;
};

} // anonymous namespace


core::Error createHunspell(const FilePath& affPath,
const FilePath& dicPath,
boost::shared_ptr<SpellChecker>* pHunspell)
boost::shared_ptr<SpellChecker>* ppHunspell,
const IconvstrFunction& iconvstrFunc)
{
// create the hunspell engine
boost::shared_ptr<HunspellSpellChecker> pNew(new HunspellSpellChecker());

// initialize it
Error error = pNew->initialize(affPath, dicPath);
Error error = pNew->initialize(affPath, dicPath, iconvstrFunc);
if (error)
return error;

// return
*pHunspell = boost::shared_static_cast<SpellChecker>(pNew);
*ppHunspell = boost::shared_static_cast<SpellChecker>(pNew);
return Success();
}

Expand Down
62 changes: 46 additions & 16 deletions src/cpp/session/modules/SessionSpelling.cpp
Expand Up @@ -21,6 +21,7 @@

#include <r/RSexp.hpp>
#include <r/RRoutines.hpp>
#include <r/RUtil.hpp>

#include <session/SessionModuleContext.hpp>

Expand All @@ -38,23 +39,46 @@ boost::shared_ptr<core::spelling::SpellChecker> s_pSpellChecker;
// R function for testing & debugging
SEXP rs_checkSpelling(SEXP wordSEXP)
{
bool isCorrect;
std::string word = r::sexp::asString(wordSEXP);

bool isCorrect = s_pSpellChecker->checkSpelling(word);
Error error = s_pSpellChecker->checkSpelling(word,&isCorrect);

// We'll return true here so as not to tie up the front end.
if (error)
{
LOG_ERROR(error);
isCorrect = true;
}

r::sexp::Protect rProtect;
return r::sexp::create(isCorrect, &rProtect);
}

SEXP rs_suggestionList(SEXP wordSEXP)
{
std::string word = r::sexp::asString(wordSEXP);
std::vector<std::string> sugs;
std::string word = r::sexp::asString(wordSEXP);
std::vector<std::string> sugs;

s_pSpellChecker->suggestionList(word,&sugs);
Error error = s_pSpellChecker->suggestionList(word,&sugs);
if (error)
LOG_ERROR(error);

r::sexp::Protect rProtect;
return r::sexp::create(sugs,&rProtect);
r::sexp::Protect rProtect;
return r::sexp::create(sugs,&rProtect);
}

SEXP rs_analyzeWord(SEXP wordSEXP)
{
std::string word = r::sexp::asString(wordSEXP);
std::vector<std::string> res;

Error error = s_pSpellChecker->analyzeWord(word,&res);
if (error)
LOG_ERROR(error);

r::sexp::Protect rProtect;
return r::sexp::create(res,&rProtect);
}


Expand All @@ -64,25 +88,31 @@ SEXP rs_suggestionList(SEXP wordSEXP)
Error initialize()
{
// register rs_ensureFileHidden with R
R_CallMethodDef checkSpellingMethodDef;
R_CallMethodDef methodDef;

methodDef.name = "rs_checkSpelling" ;
methodDef.fun = (DL_FUNC) rs_checkSpelling ;
methodDef.numArgs = 1;
r::routines::addCallMethod(methodDef);

checkSpellingMethodDef.name = "rs_checkSpelling" ;
checkSpellingMethodDef.fun = (DL_FUNC) rs_checkSpelling ;
checkSpellingMethodDef.numArgs = 1;
r::routines::addCallMethod(checkSpellingMethodDef);
methodDef.name = "rs_suggestionList" ;
methodDef.fun = (DL_FUNC) rs_suggestionList ;
methodDef.numArgs = 1;
r::routines::addCallMethod(methodDef);

checkSpellingMethodDef.name = "rs_suggestionList" ;
checkSpellingMethodDef.fun = (DL_FUNC) rs_suggestionList ;
checkSpellingMethodDef.numArgs = 1;
r::routines::addCallMethod(checkSpellingMethodDef);
methodDef.name = "rs_analyzeWord" ;
methodDef.fun = (DL_FUNC) rs_analyzeWord ;
methodDef.numArgs = 1;
r::routines::addCallMethod(methodDef);

// initialize the spell checker
using namespace core::spelling;
session::Options& options = session::options();
FilePath enUSPath = options.hunspellDictionariesPath().childPath("en_US");
return createHunspell(enUSPath.childPath("en_US.aff"),
enUSPath.childPath("en_US.dic"),
&s_pSpellChecker);
&s_pSpellChecker,
&r::util::iconvstr);
}


Expand Down

0 comments on commit ce79138

Please sign in to comment.