--- a/extensions/spellcheck/hunspell/glue/moz.build
+++ b/extensions/spellcheck/hunspell/glue/moz.build
@@ -1,15 +1,15 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-SOURCES += [
+UNIFIED_SOURCES += [
'mozHunspell.cpp',
'mozHunspellDirProvider.cpp',
'RemoteSpellCheckEngineChild.cpp',
'RemoteSpellCheckEngineParent.cpp',
]
FINAL_LIBRARY = 'xul'
--- a/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/glue/mozHunspell.cpp
@@ -195,17 +195,17 @@ NS_IMETHODIMP mozHunspell::SetDictionary
mDictionary = aDictionary;
mAffixFileName = affFileName;
mHunspell = new Hunspell(affFileName.get(),
dictFileName.get());
if (!mHunspell)
return NS_ERROR_OUT_OF_MEMORY;
- nsDependentCString label(mHunspell->get_dic_encoding());
+ nsAutoCString label(mHunspell->get_dict_encoding().c_str());
nsAutoCString encoding;
if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
return NS_ERROR_UCONV_NOCONV;
}
mEncoder = EncodingUtils::EncoderForEncoding(encoding);
mDecoder = EncodingUtils::DecoderForEncoding(encoding);
if (mEncoder)
@@ -475,32 +475,34 @@ mozHunspell::LoadDictionariesFromDir(nsI
dict.ReplaceChar("_", '-');
mDictionaries.Put(dict, file);
}
return NS_OK;
}
-nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst)
+nsresult
+mozHunspell::ConvertCharset(const char16_t* aStr, std::string* aDst)
{
NS_ENSURE_ARG_POINTER(aDst);
NS_ENSURE_TRUE(mEncoder, NS_ERROR_NULL_POINTER);
int32_t outLength;
int32_t inLength = NS_strlen(aStr);
nsresult rv = mEncoder->GetMaxLength(aStr, inLength, &outLength);
NS_ENSURE_SUCCESS(rv, rv);
- *aDst = (char *) moz_xmalloc(sizeof(char) * (outLength+1));
- NS_ENSURE_TRUE(*aDst, NS_ERROR_OUT_OF_MEMORY);
+ aDst->resize(outLength);
- rv = mEncoder->Convert(aStr, &inLength, *aDst, &outLength);
- if (NS_SUCCEEDED(rv))
- (*aDst)[outLength] = '\0';
+ char* dst = &aDst->operator[](0);
+ rv = mEncoder->Convert(aStr, &inLength, dst, &outLength);
+ if (NS_SUCCEEDED(rv)) {
+ aDst->resize(outLength);
+ }
return rv;
}
NS_IMETHODIMP
mozHunspell::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
@@ -513,76 +515,74 @@ mozHunspell::CollectReports(nsIHandleRep
}
NS_IMETHODIMP mozHunspell::Check(const char16_t *aWord, bool *aResult)
{
NS_ENSURE_ARG_POINTER(aWord);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
- nsXPIDLCString charsetWord;
- nsresult rv = ConvertCharset(aWord, getter_Copies(charsetWord));
+ std::string charsetWord;
+ nsresult rv = ConvertCharset(aWord, &charsetWord);
NS_ENSURE_SUCCESS(rv, rv);
- *aResult = !!mHunspell->spell(charsetWord);
-
+ *aResult = mHunspell->spell(charsetWord);
if (!*aResult && mPersonalDictionary)
rv = mPersonalDictionary->Check(aWord, mLanguage.get(), aResult);
return rv;
}
NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestions, uint32_t *aSuggestionCount)
{
NS_ENSURE_ARG_POINTER(aSuggestions);
NS_ENSURE_ARG_POINTER(aSuggestionCount);
NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
nsresult rv;
*aSuggestionCount = 0;
- nsXPIDLCString charsetWord;
- rv = ConvertCharset(aWord, getter_Copies(charsetWord));
+ std::string charsetWord;
+ rv = ConvertCharset(aWord, &charsetWord);
NS_ENSURE_SUCCESS(rv, rv);
- char ** wlst;
- *aSuggestionCount = mHunspell->suggest(&wlst, charsetWord);
+ std::vector<std::string> suggestions = mHunspell->suggest(charsetWord);
+ *aSuggestionCount = static_cast<uint32_t>(suggestions.size());
if (*aSuggestionCount) {
*aSuggestions = (char16_t **)moz_xmalloc(*aSuggestionCount * sizeof(char16_t *));
if (*aSuggestions) {
uint32_t index = 0;
for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
// Convert the suggestion to utf16
- int32_t inLength = strlen(wlst[index]);
+ int32_t inLength = suggestions[index].size();
int32_t outLength;
- rv = mDecoder->GetMaxLength(wlst[index], inLength, &outLength);
+ rv = mDecoder->GetMaxLength(suggestions[index].c_str(), inLength, &outLength);
if (NS_SUCCEEDED(rv))
{
(*aSuggestions)[index] = (char16_t *) moz_xmalloc(sizeof(char16_t) * (outLength+1));
if ((*aSuggestions)[index])
{
- rv = mDecoder->Convert(wlst[index], &inLength, (*aSuggestions)[index], &outLength);
+ rv = mDecoder->Convert(suggestions[index].c_str(), &inLength, (*aSuggestions)[index], &outLength);
if (NS_SUCCEEDED(rv))
(*aSuggestions)[index][outLength] = 0;
}
else
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
if (NS_FAILED(rv))
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, *aSuggestions); // free the char16_t strings up to the point at which the error occurred
}
else // if (*aSuggestions)
rv = NS_ERROR_OUT_OF_MEMORY;
}
- NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aSuggestionCount, wlst);
return rv;
}
NS_IMETHODIMP
mozHunspell::Observe(nsISupports* aSubj, const char *aTopic,
const char16_t *aData)
{
NS_ASSERTION(!strcmp(aTopic, "profile-do-change")
--- a/extensions/spellcheck/hunspell/glue/mozHunspell.h
+++ b/extensions/spellcheck/hunspell/glue/mozHunspell.h
@@ -94,17 +94,17 @@ public:
mozHunspell();
nsresult Init();
void LoadDictionaryList(bool aNotifyChildProcesses);
// helper method for converting a word to the charset of the dictionary
- nsresult ConvertCharset(const char16_t* aStr, char ** aDst);
+ nsresult ConvertCharset(const char16_t* aStr, std::string* aDst);
NS_DECL_NSIMEMORYREPORTER
protected:
virtual ~mozHunspell();
nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
nsCOMPtr<nsIUnicodeEncoder> mEncoder;
--- a/extensions/spellcheck/hunspell/src/README.mozilla
+++ b/extensions/spellcheck/hunspell/src/README.mozilla
@@ -1,2 +1,2 @@
-Hunspell Version: 1.4.1
+Hunspell Version: 1.5.4
Additional Patches: See patches directory.
--- a/extensions/spellcheck/hunspell/src/affentry.cxx
+++ b/extensions/spellcheck/hunspell/src/affentry.cxx
@@ -74,62 +74,45 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "affentry.hxx"
#include "csutil.hxx"
-PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp)
- // register affix manager
- : pmyMgr(pmgr),
- next(NULL),
- nexteq(NULL),
- nextne(NULL),
- flgnxt(NULL) {
- // set up its initial values
- aflag = dp->aflag; // flag
- strip = dp->strip; // string to strip
- appnd = dp->appnd; // string to append
- numconds = dp->numconds; // length of the condition
- opts = dp->opts; // cross product flag
- // then copy over all of the conditions
- if (opts & aeLONGCOND) {
- memcpy(c.conds, dp->c.l.conds1, MAXCONDLEN_1);
- c.l.conds2 = dp->c.l.conds2;
- } else
- memcpy(c.conds, dp->c.conds, MAXCONDLEN);
- morphcode = dp->morphcode;
- contclass = dp->contclass;
- contclasslen = dp->contclasslen;
-}
-
-PfxEntry::~PfxEntry() {
- aflag = 0;
- pmyMgr = NULL;
+AffEntry::~AffEntry() {
if (opts & aeLONGCOND)
free(c.l.conds2);
if (morphcode && !(opts & aeALIASM))
free(morphcode);
if (contclass && !(opts & aeALIASF))
free(contclass);
}
+PfxEntry::PfxEntry(AffixMgr* pmgr)
+ // register affix manager
+ : pmyMgr(pmgr),
+ next(NULL),
+ nexteq(NULL),
+ nextne(NULL),
+ flgnxt(NULL) {
+}
+
// add prefix to this word assuming conditions hold
-char* PfxEntry::add(const char* word, size_t len) {
+std::string PfxEntry::add(const char* word, size_t len) {
+ std::string result;
if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
(len >= numconds) && test_condition(word) &&
(!strip.size() || (strncmp(word, strip.c_str(), strip.size()) == 0))) {
/* we have a match so add prefix */
- std::string tword(appnd);
- tword.append(word + strip.size());
- return mystrdup(tword.c_str());
+ result.assign(appnd);
+ result.append(word + strip.size());
}
- return NULL;
+ return result;
}
inline char* PfxEntry::nextchar(char* p) {
if (p) {
p++;
if (opts & aeLONGCOND) {
// jump to the 2nd part of the condition
if (p == c.conds + MAXCONDLEN_1)
@@ -271,33 +254,30 @@ struct hentry* PfxEntry::checkword(const
// prefix matched but no root word was found
// if aeXPRODUCT is allowed, try again but now
// ross checked combined with a suffix
// if ((opts & aeXPRODUCT) && in_compound) {
if ((opts & aeXPRODUCT)) {
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, aeXPRODUCT, this,
- NULL, 0, NULL, FLAG_NULL, needflag,
- in_compound);
+ FLAG_NULL, needflag, in_compound);
if (he)
return he;
}
}
}
return NULL;
}
// check if this prefix entry matches
struct hentry* PfxEntry::check_twosfx(const char* word,
int len,
char in_compound,
const FLAG needflag) {
- struct hentry* he; // hash entry of root word or NULL
-
// on entry prefix is 0 length or already matches the beginning of the word.
// So if the remaining root word has positive length
// and if there are enough chars in root word and added back strip chars
// to meet the number of characters conditions, then test it
int tmpl = len - appnd.size(); // length of tmpword
if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
@@ -319,36 +299,37 @@ struct hentry* PfxEntry::check_twosfx(co
if (test_condition(tmpword.c_str())) {
tmpl += strip.size();
// prefix matched but no root word was found
// if aeXPRODUCT is allowed, try again but now
// cross checked combined with a suffix
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
- he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this,
- needflag);
+ // hash entry of root word or NULL
+ struct hentry* he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this,
+ needflag);
if (he)
return he;
}
}
}
return NULL;
}
// check if this prefix entry matches
-char* PfxEntry::check_twosfx_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag) {
+std::string PfxEntry::check_twosfx_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag) {
+ std::string result;
// on entry prefix is 0 length or already matches the beginning of the word.
// So if the remaining root word has positive length
// and if there are enough chars in root word and added back strip chars
// to meet the number of characters conditions, then test it
-
int tmpl = len - appnd.size(); // length of tmpword
if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
(tmpl + strip.size() >= numconds)) {
// generate new root word by removing prefix and adding
// back any characters that would have been stripped
std::string tmpword(strip);
@@ -365,32 +346,31 @@ char* PfxEntry::check_twosfx_morph(const
if (test_condition(tmpword.c_str())) {
tmpl += strip.size();
// prefix matched but no root word was found
// if aeXPRODUCT is allowed, try again but now
// ross checked combined with a suffix
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
- return pmyMgr->suffix_check_twosfx_morph(tmpword.c_str(), tmpl,
- aeXPRODUCT,
- this, needflag);
+ result = pmyMgr->suffix_check_twosfx_morph(tmpword.c_str(), tmpl,
+ aeXPRODUCT,
+ this, needflag);
}
}
}
- return NULL;
+ return result;
}
// check if this prefix entry matches
-char* PfxEntry::check_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag) {
- struct hentry* he; // hash entry of root word or NULL
- char* st;
+std::string PfxEntry::check_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag) {
+ std::string result;
// on entry prefix is 0 length or already matches the beginning of the word.
// So if the remaining root word has positive length
// and if there are enough chars in root word and added back strip chars
// to meet the number of characters conditions, then test it
int tmpl = len - appnd.size(); // length of tmpword
@@ -406,19 +386,18 @@ char* PfxEntry::check_morph(const char*
// are met. Please see the appendix at the end of
// this file for more info on exactly what is being
// tested
// if all conditions are met then check if resulting
// root word in the dictionary
if (test_condition(tmpword.c_str())) {
- std::string result;
-
tmpl += strip.size();
+ struct hentry* he; // hash entry of root word or NULL
if ((he = pmyMgr->lookup(tmpword.c_str())) != NULL) {
do {
if (TESTAFF(he->astr, aflag, he->alen) &&
// forbid single prefixes with needaffix flag
!TESTAFF(contclass, pmyMgr->get_needaffix(), contclasslen) &&
// needflag
((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
(contclass && TESTAFF(contclass, needflag, contclasslen)))) {
@@ -450,86 +429,53 @@ char* PfxEntry::check_morph(const char*
} while (he);
}
// prefix matched but no root word was found
// if aeXPRODUCT is allowed, try again but now
// ross checked combined with a suffix
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
- st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, aeXPRODUCT, this,
- FLAG_NULL, needflag);
- if (st) {
+ std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, aeXPRODUCT, this,
+ FLAG_NULL, needflag);
+ if (!st.empty()) {
result.append(st);
- free(st);
}
}
-
- if (!result.empty())
- return mystrdup(result.c_str());
}
}
- return NULL;
+ return result;
}
-SfxEntry::SfxEntry(AffixMgr* pmgr, affentry* dp)
+SfxEntry::SfxEntry(AffixMgr* pmgr)
: pmyMgr(pmgr) // register affix manager
,
next(NULL),
nexteq(NULL),
nextne(NULL),
flgnxt(NULL),
l_morph(NULL),
r_morph(NULL),
eq_morph(NULL) {
- // set up its initial values
- aflag = dp->aflag; // char flag
- strip = dp->strip; // string to strip
- appnd = dp->appnd; // string to append
- numconds = dp->numconds; // length of the condition
- opts = dp->opts; // cross product flag
-
- // then copy over all of the conditions
- if (opts & aeLONGCOND) {
- memcpy(c.l.conds1, dp->c.l.conds1, MAXCONDLEN_1);
- c.l.conds2 = dp->c.l.conds2;
- } else
- memcpy(c.conds, dp->c.conds, MAXCONDLEN);
- rappnd = appnd;
- reverseword(rappnd);
- morphcode = dp->morphcode;
- contclass = dp->contclass;
- contclasslen = dp->contclasslen;
-}
-
-SfxEntry::~SfxEntry() {
- aflag = 0;
- pmyMgr = NULL;
- if (opts & aeLONGCOND)
- free(c.l.conds2);
- if (morphcode && !(opts & aeALIASM))
- free(morphcode);
- if (contclass && !(opts & aeALIASF))
- free(contclass);
}
// add suffix to this word assuming conditions hold
-char* SfxEntry::add(const char* word, size_t len) {
+std::string SfxEntry::add(const char* word, size_t len) {
+ std::string result;
/* make sure all conditions match */
if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
(len >= numconds) && test_condition(word + len, word) &&
(!strip.size() ||
(strcmp(word + len - strip.size(), strip.c_str()) == 0))) {
- std::string tword(word);
+ result.assign(word);
/* we have a match so add suffix */
- tword.replace(len - strip.size(), std::string::npos, appnd);
- return mystrdup(tword.c_str());
+ result.replace(len - strip.size(), std::string::npos, appnd);
}
- return NULL;
+ return result;
}
inline char* SfxEntry::nextchar(char* p) {
if (p) {
p++;
if (opts & aeLONGCOND) {
// jump to the 2nd part of the condition
if (p == c.l.conds1 + MAXCONDLEN_1)
@@ -664,19 +610,16 @@ inline int SfxEntry::test_condition(cons
}
}
// see if this suffix is present in the word
struct hentry* SfxEntry::checkword(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
- char** wlst,
- int maxSug,
- int* ns,
const FLAG cclass,
const FLAG needflag,
const FLAG badflag) {
struct hentry* he; // hash entry pointer
PfxEntry* ep = ppfx;
// if this suffix is being cross checked with a prefix
// but it does not support cross products skip it
@@ -737,50 +680,28 @@ struct hentry* SfxEntry::checkword(const
(!badflag || !TESTAFF(he->astr, badflag, he->alen)) &&
// handle required flag
((!needflag) ||
(TESTAFF(he->astr, needflag, he->alen) ||
((contclass) && TESTAFF(contclass, needflag, contclasslen)))))
return he;
he = he->next_homonym; // check homonyms
} while (he);
-
- // obsolote stemming code (used only by the
- // experimental SuffixMgr:suggest_pos_stems)
- // store resulting root in wlst
- } else if (wlst && (*ns < maxSug)) {
- int cwrd = 1;
- for (int k = 0; k < *ns; k++)
- if (strcmp(tmpword, wlst[k]) == 0) {
- cwrd = 0;
- break;
- }
- if (cwrd) {
- wlst[*ns] = mystrdup(tmpword);
- if (wlst[*ns] == NULL) {
- for (int j = 0; j < *ns; j++)
- free(wlst[j]);
- *ns = -1;
- return NULL;
- }
- (*ns)++;
- }
}
}
}
return NULL;
}
// see if two-level suffix is present in the word
struct hentry* SfxEntry::check_twosfx(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
const FLAG needflag) {
- struct hentry* he; // hash entry pointer
PfxEntry* ep = ppfx;
// if this suffix is being cross checked with a prefix
// but it does not support cross products skip it
if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0)
return NULL;
@@ -808,53 +729,51 @@ struct hentry* SfxEntry::check_twosfx(co
// now make sure all of the conditions on characters
// are met. Please see the appendix at the end of
// this file for more info on exactly what is being
// tested
// if all conditions are met then recall suffix_check
if (test_condition(end, beg)) {
+ struct hentry* he; // hash entry pointer
if (ppfx) {
// handle conditional suffix
if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen))
- he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL, NULL, 0, NULL,
- (FLAG)aflag, needflag);
+ he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL,
+ (FLAG)aflag, needflag, IN_CPD_NOT);
else
- he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, optflags, ppfx, NULL, 0,
- NULL, (FLAG)aflag, needflag);
+ he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, optflags, ppfx,
+ (FLAG)aflag, needflag, IN_CPD_NOT);
} else {
- he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL, NULL, 0, NULL,
- (FLAG)aflag, needflag);
+ he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL,
+ (FLAG)aflag, needflag, IN_CPD_NOT);
}
if (he)
return he;
}
}
return NULL;
}
// see if two-level suffix is present in the word
-char* SfxEntry::check_twosfx_morph(const char* word,
- int len,
- int optflags,
- PfxEntry* ppfx,
- const FLAG needflag) {
+std::string SfxEntry::check_twosfx_morph(const char* word,
+ int len,
+ int optflags,
+ PfxEntry* ppfx,
+ const FLAG needflag) {
PfxEntry* ep = ppfx;
- char* st;
- char result[MAXLNLEN];
-
- *result = '\0';
+ std::string result;
// if this suffix is being cross checked with a prefix
// but it does not support cross products skip it
if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0)
- return NULL;
+ return result;
// upon entry suffix is 0 length or already matches the end of the word.
// So if the remaining root word has positive length
// and if there are enough chars in root word and added back strip chars
// to meet the number of characters conditions, then test it
int tmpl = len - appnd.size(); // length of tmpword
@@ -878,50 +797,44 @@ char* SfxEntry::check_twosfx_morph(const
// tested
// if all conditions are met then recall suffix_check
if (test_condition(end, beg)) {
if (ppfx) {
// handle conditional suffix
if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) {
- st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag,
- needflag);
- if (st) {
+ std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag,
+ needflag);
+ if (!st.empty()) {
if (ppfx->getMorph()) {
- mystrcat(result, ppfx->getMorph(), MAXLNLEN);
- mystrcat(result, " ", MAXLNLEN);
+ result.append(ppfx->getMorph());
+ result.append(" ");
}
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ result.append(st);
mychomp(result);
}
} else {
- st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, optflags, ppfx, aflag,
- needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, optflags, ppfx, aflag,
+ needflag);
+ if (!st.empty()) {
+ result.append(st);
mychomp(result);
}
}
} else {
- st =
- pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag, needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag, needflag);
+ if (!st.empty()) {
+ result.append(st);
mychomp(result);
}
}
- if (*result)
- return mystrdup(result);
}
}
- return NULL;
+ return result;
}
// get next homonym with same affix
struct hentry* SfxEntry::get_next_homonym(struct hentry* he,
int optflags,
PfxEntry* ppfx,
const FLAG cclass,
const FLAG needflag) {
@@ -943,16 +856,21 @@ struct hentry* SfxEntry::get_next_homony
((!needflag) ||
(TESTAFF(he->astr, needflag, he->alen) ||
((contclass) && TESTAFF(contclass, needflag, contclasslen)))))
return he;
}
return NULL;
}
+void SfxEntry::initReverseWord() {
+ rappnd = appnd;
+ reverseword(rappnd);
+}
+
#if 0
Appendix: Understanding Affix Code
An affix is either a prefix or a suffix attached to root words to make
other words.
--- a/extensions/spellcheck/hunspell/src/affentry.hxx
+++ b/extensions/spellcheck/hunspell/src/affentry.hxx
@@ -66,68 +66,65 @@
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _AFFIX_HXX_
-#define _AFFIX_HXX_
-
-#include "hunvisapi.h"
+#ifndef AFFIX_HXX_
+#define AFFIX_HXX_
#include "atypes.hxx"
#include "baseaffix.hxx"
#include "affixmgr.hxx"
/* A Prefix Entry */
-class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
+class PfxEntry : public AffEntry {
private:
PfxEntry(const PfxEntry&);
PfxEntry& operator=(const PfxEntry&);
private:
AffixMgr* pmyMgr;
PfxEntry* next;
PfxEntry* nexteq;
PfxEntry* nextne;
PfxEntry* flgnxt;
public:
- PfxEntry(AffixMgr* pmgr, affentry* dp);
- ~PfxEntry();
+ explicit PfxEntry(AffixMgr* pmgr);
- inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); }
+ bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
struct hentry* checkword(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
struct hentry* check_twosfx(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
- char* check_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag = FLAG_NULL);
+ std::string check_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag = FLAG_NULL);
- char* check_twosfx_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag = FLAG_NULL);
+ std::string check_twosfx_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag = FLAG_NULL);
- inline FLAG getFlag() { return aflag; }
- inline const char* getKey() { return appnd.c_str(); }
- char* add(const char* word, size_t len);
+ FLAG getFlag() { return aflag; }
+ const char* getKey() { return appnd.c_str(); }
+ std::string add(const char* word, size_t len);
inline short getKeyLen() { return appnd.size(); }
inline const char* getMorph() { return morphcode; }
inline const unsigned short* getCont() { return contclass; }
inline short getContLen() { return contclasslen; }
@@ -142,17 +139,17 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry
inline void setFlgNxt(PfxEntry* ptr) { flgnxt = ptr; }
inline char* nextchar(char* p);
inline int test_condition(const char* st);
};
/* A Suffix Entry */
-class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
+class SfxEntry : public AffEntry {
private:
SfxEntry(const SfxEntry&);
SfxEntry& operator=(const SfxEntry&);
private:
AffixMgr* pmyMgr;
std::string rappnd;
@@ -161,52 +158,48 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry
SfxEntry* nextne;
SfxEntry* flgnxt;
SfxEntry* l_morph;
SfxEntry* r_morph;
SfxEntry* eq_morph;
public:
- SfxEntry(AffixMgr* pmgr, affentry* dp);
- ~SfxEntry();
+ explicit SfxEntry(AffixMgr* pmgr);
- inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); }
+ bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
struct hentry* checkword(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
- char** wlst,
- int maxSug,
- int* ns,
- const FLAG cclass = FLAG_NULL,
- const FLAG needflag = FLAG_NULL,
- const FLAG badflag = FLAG_NULL);
+ const FLAG cclass,
+ const FLAG needflag,
+ const FLAG badflag);
struct hentry* check_twosfx(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
- char* check_twosfx_morph(const char* word,
- int len,
- int optflags,
- PfxEntry* ppfx,
- const FLAG needflag = FLAG_NULL);
+ std::string check_twosfx_morph(const char* word,
+ int len,
+ int optflags,
+ PfxEntry* ppfx,
+ const FLAG needflag = FLAG_NULL);
struct hentry* get_next_homonym(struct hentry* he);
struct hentry* get_next_homonym(struct hentry* word,
int optflags,
PfxEntry* ppfx,
const FLAG cclass,
const FLAG needflag);
- inline FLAG getFlag() { return aflag; }
- inline const char* getKey() { return rappnd.c_str(); }
- char* add(const char* word, size_t len);
+ FLAG getFlag() { return aflag; }
+ const char* getKey() { return rappnd.c_str(); }
+ std::string add(const char* word, size_t len);
inline const char* getMorph() { return morphcode; }
inline const unsigned short* getCont() { return contclass; }
inline short getContLen() { return contclasslen; }
inline const char* getAffix() { return appnd.c_str(); }
inline short getKeyLen() { return appnd.size(); }
@@ -219,14 +212,15 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry
inline SfxEntry* getRM() { return r_morph; }
inline SfxEntry* getEQM() { return eq_morph; }
inline SfxEntry* getFlgNxt() { return flgnxt; }
inline void setNext(SfxEntry* ptr) { next = ptr; }
inline void setNextNE(SfxEntry* ptr) { nextne = ptr; }
inline void setNextEQ(SfxEntry* ptr) { nexteq = ptr; }
inline void setFlgNxt(SfxEntry* ptr) { flgnxt = ptr; }
+ void initReverseWord();
inline char* nextchar(char* p);
inline int test_condition(const char* st, const char* begin);
};
#endif
--- a/extensions/spellcheck/hunspell/src/affixmgr.cxx
+++ b/extensions/spellcheck/hunspell/src/affixmgr.cxx
@@ -83,43 +83,34 @@
#include "affixmgr.hxx"
#include "affentry.hxx"
#include "langnum.hxx"
#include "csutil.hxx"
AffixMgr::AffixMgr(const char* affpath,
- HashMgr** ptr,
- int* md,
- const char* key) {
+ const std::vector<HashMgr*>& ptr,
+ const char* key)
+ : alldic(ptr)
+ , pHMgr(ptr[0]) {
+
// register hash manager and load affix data from aff file
- pHMgr = ptr[0];
- alldic = ptr;
- maxdic = md;
- keystring = NULL;
- trystring = NULL;
- encoding = NULL;
csconv = NULL;
utf8 = 0;
complexprefixes = 0;
- maptable = NULL;
- nummap = 0;
- breaktable = NULL;
- numbreak = -1;
- reptable = NULL;
- numrep = 0;
+ parsedmaptable = false;
+ parsedbreaktable = false;
+ parsedrep = false;
iconvtable = NULL;
oconvtable = NULL;
- checkcpdtable = NULL;
// allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN)
simplifiedcpd = 0;
- numcheckcpd = 0;
- defcpdtable = NULL;
- numdefcpd = 0;
+ parsedcheckcpd = false;
+ parseddefcpd = false;
phone = NULL;
compoundflag = FLAG_NULL; // permits word in compound forms
compoundbegin = FLAG_NULL; // may be first word in compound forms
compoundmiddle = FLAG_NULL; // may be middle word in compound forms
compoundend = FLAG_NULL; // may be last word in compound forms
compoundroot = FLAG_NULL; // compound word signing flag
compoundpermitflag = FLAG_NULL; // compound permitting flag for suffixed word
compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word
@@ -130,35 +121,25 @@ AffixMgr::AffixMgr(const char* affpath,
checkcompoundcase =
0; // forbid upper and lowercase combinations at word bounds
checkcompoundtriple = 0; // forbid compounds with triple letters
simplifiedtriple = 0; // allow simplified triple letters in compounds
// (Schiff+fahrt -> Schiffahrt)
forbiddenword = FORBIDDENWORD; // forbidden word signing flag
nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag
nongramsuggest = FLAG_NULL;
- lang = NULL; // language
langnum = 0; // language code (see http://l10n.openoffice.org/languages.html)
needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes
cpdwordmax = -1; // default: unlimited wordcount in compound words
cpdmin = -1; // undefined
cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words
- cpdvowels = NULL; // vowels (for calculating of Hungarian compounding limit,
- // O(n) search! XXX)
- cpdvowels_utf16 =
- NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search)
- cpdvowels_utf16_len = 0; // vowels
pfxappnd = NULL; // previous prefix for counting syllables of the prefix BUG
sfxappnd = NULL; // previous suffix for counting syllables of the suffix BUG
sfxextra = 0; // modifier for syllable count of sfxappnd BUG
- cpdsyllablenum = NULL; // syllable count incrementing flag
checknum = 0; // checking numbers, and word with numbers
- wordchars = NULL; // letters + spec. word characters
- ignorechars = NULL; // letters + spec. word characters
- version = NULL; // affix and dictionary file version string
havecontclass = 0; // flags of possible continuing classes (double affix)
// LEMMA_PRESENT: not put root into the morphological output. Lemma presents
// in morhological description in dictionary file. It's often combined with
// PSEUDOROOT.
lemma_present = FLAG_NULL;
circumfix = FLAG_NULL;
onlyincompound = FLAG_NULL;
maxngramsugs = -1; // undefined
@@ -220,93 +201,20 @@ AffixMgr::~AffixMgr() {
nptr = ptr->getNext();
delete (ptr);
ptr = nptr;
nptr = NULL;
}
sStart[j] = NULL;
}
- if (keystring)
- free(keystring);
- keystring = NULL;
- if (trystring)
- free(trystring);
- trystring = NULL;
- if (encoding)
- free(encoding);
- encoding = NULL;
- if (maptable) {
- for (int j = 0; j < nummap; j++) {
- for (int k = 0; k < maptable[j].len; k++) {
- if (maptable[j].set[k])
- free(maptable[j].set[k]);
- }
- free(maptable[j].set);
- maptable[j].set = NULL;
- maptable[j].len = 0;
- }
- free(maptable);
- maptable = NULL;
- }
- nummap = 0;
- if (breaktable) {
- for (int j = 0; j < numbreak; j++) {
- if (breaktable[j])
- free(breaktable[j]);
- breaktable[j] = NULL;
- }
- free(breaktable);
- breaktable = NULL;
- }
- numbreak = 0;
- if (reptable) {
- for (int j = 0; j < numrep; j++) {
- free(reptable[j].pattern);
- free(reptable[j].pattern2);
- }
- free(reptable);
- reptable = NULL;
- }
- if (iconvtable)
- delete iconvtable;
- if (oconvtable)
- delete oconvtable;
- if (phone && phone->rules) {
- for (int j = 0; j < phone->num + 1; j++) {
- free(phone->rules[j * 2]);
- free(phone->rules[j * 2 + 1]);
- }
- free(phone->rules);
- free(phone);
- phone = NULL;
- }
-
- if (defcpdtable) {
- for (int j = 0; j < numdefcpd; j++) {
- free(defcpdtable[j].def);
- defcpdtable[j].def = NULL;
- }
- free(defcpdtable);
- defcpdtable = NULL;
- }
- numrep = 0;
- if (checkcpdtable) {
- for (int j = 0; j < numcheckcpd; j++) {
- free(checkcpdtable[j].pattern);
- free(checkcpdtable[j].pattern2);
- free(checkcpdtable[j].pattern3);
- checkcpdtable[j].pattern = NULL;
- checkcpdtable[j].pattern2 = NULL;
- checkcpdtable[j].pattern3 = NULL;
- }
- free(checkcpdtable);
- checkcpdtable = NULL;
- }
- numcheckcpd = 0;
+ delete iconvtable;
+ delete oconvtable;
+ delete phone;
+
FREE_FLAG(compoundflag);
FREE_FLAG(compoundbegin);
FREE_FLAG(compoundmiddle);
FREE_FLAG(compoundend);
FREE_FLAG(compoundpermitflag);
FREE_FLAG(compoundforbidflag);
FREE_FLAG(compoundroot);
FREE_FLAG(forbiddenword);
@@ -316,49 +224,33 @@ AffixMgr::~AffixMgr() {
FREE_FLAG(lemma_present);
FREE_FLAG(circumfix);
FREE_FLAG(onlyincompound);
cpdwordmax = 0;
pHMgr = NULL;
cpdmin = 0;
cpdmaxsyllable = 0;
- if (cpdvowels)
- free(cpdvowels);
- if (cpdvowels_utf16)
- free(cpdvowels_utf16);
- if (cpdsyllablenum)
- free(cpdsyllablenum);
free_utf_tbl();
- if (lang)
- free(lang);
- if (wordchars)
- free(wordchars);
- if (ignorechars)
- free(ignorechars);
- if (version)
- free(version);
checknum = 0;
#ifdef MOZILLA_CLIENT
delete[] csconv;
#endif
}
void AffixMgr::finishFileMgr(FileMgr* afflst) {
delete afflst;
// convert affix trees to sorted list
process_pfx_tree_to_list();
process_sfx_tree_to_list();
}
// read in aff file and build up prefix and suffix entry objects
int AffixMgr::parse_file(const char* affpath, const char* key) {
- char* line; // io buffers
- char ft; // affix type
// checking flag duplication
char dupflags[CONTSIZE];
char dupflags_ini = 1;
// first line indicator for removing byte order mark
int firstline = 1;
@@ -370,449 +262,450 @@ int AffixMgr::parse_file(const char* aff
return 1;
}
// step one is to parse the affix file building up the internal
// affix data structures
// read in each line ignoring any that do not
// start with a known line type indicator
- while ((line = afflst->getline()) != NULL) {
+ std::string line;
+ while (afflst->getline(line)) {
mychomp(line);
/* remove byte order mark */
if (firstline) {
firstline = 0;
// Affix file begins with byte order mark: possible incompatibility with
// old Hunspell versions
- if (strncmp(line, "\xEF\xBB\xBF", 3) == 0) {
- memmove(line, line + 3, strlen(line + 3) + 1);
+ if (line.compare(0, 3, "\xEF\xBB\xBF", 3) == 0) {
+ line.erase(0, 3);
}
}
/* parse in the keyboard string */
- if (strncmp(line, "KEY", 3) == 0) {
- if (parse_string(line, &keystring, afflst->getlinenum())) {
+ if (line.compare(0, 3, "KEY", 3) == 0) {
+ if (!parse_string(line, keystring, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the try string */
- if (strncmp(line, "TRY", 3) == 0) {
- if (parse_string(line, &trystring, afflst->getlinenum())) {
+ if (line.compare(0, 3, "TRY", 3) == 0) {
+ if (!parse_string(line, trystring, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the name of the character set used by the .dict and .aff */
- if (strncmp(line, "SET", 3) == 0) {
- if (parse_string(line, &encoding, afflst->getlinenum())) {
+ if (line.compare(0, 3, "SET", 3) == 0) {
+ if (!parse_string(line, encoding, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
- if (strcmp(encoding, "UTF-8") == 0) {
+ if (encoding == "UTF-8") {
utf8 = 1;
#ifndef OPENOFFICEORG
#ifndef MOZILLA_CLIENT
- if (initialize_utf_tbl()) {
- finishFileMgr(afflst);
- return 1;
- }
+ initialize_utf_tbl();
#endif
#endif
}
}
/* parse COMPLEXPREFIXES for agglutinative languages with right-to-left
* writing system */
- if (strncmp(line, "COMPLEXPREFIXES", 15) == 0)
+ if (line.compare(0, 15, "COMPLEXPREFIXES", 15) == 0)
complexprefixes = 1;
/* parse in the flag used by the controlled compound words */
- if (strncmp(line, "COMPOUNDFLAG", 12) == 0) {
- if (parse_flag(line, &compoundflag, afflst)) {
+ if (line.compare(0, 12, "COMPOUNDFLAG", 12) == 0) {
+ if (!parse_flag(line, &compoundflag, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by compound words */
- if (strncmp(line, "COMPOUNDBEGIN", 13) == 0) {
+ if (line.compare(0, 13, "COMPOUNDBEGIN", 13) == 0) {
if (complexprefixes) {
- if (parse_flag(line, &compoundend, afflst)) {
+ if (!parse_flag(line, &compoundend, afflst)) {
finishFileMgr(afflst);
return 1;
}
} else {
- if (parse_flag(line, &compoundbegin, afflst)) {
+ if (!parse_flag(line, &compoundbegin, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
}
/* parse in the flag used by compound words */
- if (strncmp(line, "COMPOUNDMIDDLE", 14) == 0) {
- if (parse_flag(line, &compoundmiddle, afflst)) {
+ if (line.compare(0, 14, "COMPOUNDMIDDLE", 14) == 0) {
+ if (!parse_flag(line, &compoundmiddle, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
+
/* parse in the flag used by compound words */
- if (strncmp(line, "COMPOUNDEND", 11) == 0) {
+ if (line.compare(0, 11, "COMPOUNDEND", 11) == 0) {
if (complexprefixes) {
- if (parse_flag(line, &compoundbegin, afflst)) {
+ if (!parse_flag(line, &compoundbegin, afflst)) {
finishFileMgr(afflst);
return 1;
}
} else {
- if (parse_flag(line, &compoundend, afflst)) {
+ if (!parse_flag(line, &compoundend, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
}
/* parse in the data used by compound_check() method */
- if (strncmp(line, "COMPOUNDWORDMAX", 15) == 0) {
- if (parse_num(line, &cpdwordmax, afflst)) {
+ if (line.compare(0, 15, "COMPOUNDWORDMAX", 15) == 0) {
+ if (!parse_num(line, &cpdwordmax, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag sign compounds in dictionary */
- if (strncmp(line, "COMPOUNDROOT", 12) == 0) {
- if (parse_flag(line, &compoundroot, afflst)) {
+ if (line.compare(0, 12, "COMPOUNDROOT", 12) == 0) {
+ if (!parse_flag(line, &compoundroot, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by compound_check() method */
- if (strncmp(line, "COMPOUNDPERMITFLAG", 18) == 0) {
- if (parse_flag(line, &compoundpermitflag, afflst)) {
+ if (line.compare(0, 18, "COMPOUNDPERMITFLAG", 18) == 0) {
+ if (!parse_flag(line, &compoundpermitflag, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by compound_check() method */
- if (strncmp(line, "COMPOUNDFORBIDFLAG", 18) == 0) {
- if (parse_flag(line, &compoundforbidflag, afflst)) {
+ if (line.compare(0, 18, "COMPOUNDFORBIDFLAG", 18) == 0) {
+ if (!parse_flag(line, &compoundforbidflag, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "COMPOUNDMORESUFFIXES", 20) == 0) {
+ if (line.compare(0, 20, "COMPOUNDMORESUFFIXES", 20) == 0) {
compoundmoresuffixes = 1;
}
- if (strncmp(line, "CHECKCOMPOUNDDUP", 16) == 0) {
+ if (line.compare(0, 16, "CHECKCOMPOUNDDUP", 16) == 0) {
checkcompounddup = 1;
}
- if (strncmp(line, "CHECKCOMPOUNDREP", 16) == 0) {
+ if (line.compare(0, 16, "CHECKCOMPOUNDREP", 16) == 0) {
checkcompoundrep = 1;
}
- if (strncmp(line, "CHECKCOMPOUNDTRIPLE", 19) == 0) {
+ if (line.compare(0, 19, "CHECKCOMPOUNDTRIPLE", 19) == 0) {
checkcompoundtriple = 1;
}
- if (strncmp(line, "SIMPLIFIEDTRIPLE", 16) == 0) {
+ if (line.compare(0, 16, "SIMPLIFIEDTRIPLE", 16) == 0) {
simplifiedtriple = 1;
}
- if (strncmp(line, "CHECKCOMPOUNDCASE", 17) == 0) {
+ if (line.compare(0, 17, "CHECKCOMPOUNDCASE", 17) == 0) {
checkcompoundcase = 1;
}
- if (strncmp(line, "NOSUGGEST", 9) == 0) {
- if (parse_flag(line, &nosuggest, afflst)) {
+ if (line.compare(0, 9, "NOSUGGEST", 9) == 0) {
+ if (!parse_flag(line, &nosuggest, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "NONGRAMSUGGEST", 14) == 0) {
- if (parse_flag(line, &nongramsuggest, afflst)) {
+ if (line.compare(0, 14, "NONGRAMSUGGEST", 14) == 0) {
+ if (!parse_flag(line, &nongramsuggest, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by forbidden words */
- if (strncmp(line, "FORBIDDENWORD", 13) == 0) {
- if (parse_flag(line, &forbiddenword, afflst)) {
+ if (line.compare(0, 13, "FORBIDDENWORD", 13) == 0) {
+ if (!parse_flag(line, &forbiddenword, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by forbidden words */
- if (strncmp(line, "LEMMA_PRESENT", 13) == 0) {
- if (parse_flag(line, &lemma_present, afflst)) {
+ if (line.compare(0, 13, "LEMMA_PRESENT", 13) == 0) {
+ if (!parse_flag(line, &lemma_present, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by circumfixes */
- if (strncmp(line, "CIRCUMFIX", 9) == 0) {
- if (parse_flag(line, &circumfix, afflst)) {
+ if (line.compare(0, 9, "CIRCUMFIX", 9) == 0) {
+ if (!parse_flag(line, &circumfix, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by fogemorphemes */
- if (strncmp(line, "ONLYINCOMPOUND", 14) == 0) {
- if (parse_flag(line, &onlyincompound, afflst)) {
+ if (line.compare(0, 14, "ONLYINCOMPOUND", 14) == 0) {
+ if (!parse_flag(line, &onlyincompound, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by `needaffixs' */
- if (strncmp(line, "PSEUDOROOT", 10) == 0) {
- if (parse_flag(line, &needaffix, afflst)) {
+ if (line.compare(0, 10, "PSEUDOROOT", 10) == 0) {
+ if (!parse_flag(line, &needaffix, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by `needaffixs' */
- if (strncmp(line, "NEEDAFFIX", 9) == 0) {
- if (parse_flag(line, &needaffix, afflst)) {
+ if (line.compare(0, 9, "NEEDAFFIX", 9) == 0) {
+ if (!parse_flag(line, &needaffix, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the minimal length for words in compounds */
- if (strncmp(line, "COMPOUNDMIN", 11) == 0) {
- if (parse_num(line, &cpdmin, afflst)) {
+ if (line.compare(0, 11, "COMPOUNDMIN", 11) == 0) {
+ if (!parse_num(line, &cpdmin, afflst)) {
finishFileMgr(afflst);
return 1;
}
if (cpdmin < 1)
cpdmin = 1;
}
/* parse in the max. words and syllables in compounds */
- if (strncmp(line, "COMPOUNDSYLLABLE", 16) == 0) {
- if (parse_cpdsyllable(line, afflst)) {
+ if (line.compare(0, 16, "COMPOUNDSYLLABLE", 16) == 0) {
+ if (!parse_cpdsyllable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by compound_check() method */
- if (strncmp(line, "SYLLABLENUM", 11) == 0) {
- if (parse_string(line, &cpdsyllablenum, afflst->getlinenum())) {
+ if (line.compare(0, 11, "SYLLABLENUM", 11) == 0) {
+ if (!parse_string(line, cpdsyllablenum, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by the controlled compound words */
- if (strncmp(line, "CHECKNUM", 8) == 0) {
+ if (line.compare(0, 8, "CHECKNUM", 8) == 0) {
checknum = 1;
}
/* parse in the extra word characters */
- if (strncmp(line, "WORDCHARS", 9) == 0) {
- if (!parse_array(line, &wordchars, wordchars_utf16,
+ if (line.compare(0, 9, "WORDCHARS", 9) == 0) {
+ if (!parse_array(line, wordchars, wordchars_utf16,
utf8, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the ignored characters (for example, Arabic optional diacretics
* charachters */
- if (strncmp(line, "IGNORE", 6) == 0) {
- if (!parse_array(line, &ignorechars, ignorechars_utf16,
+ if (line.compare(0, 6, "IGNORE", 6) == 0) {
+ if (!parse_array(line, ignorechars, ignorechars_utf16,
utf8, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the typical fault correcting table */
- if (strncmp(line, "REP", 3) == 0) {
- if (parse_reptable(line, afflst)) {
+ if (line.compare(0, 3, "REP", 3) == 0) {
+ if (!parse_reptable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the input conversion table */
- if (strncmp(line, "ICONV", 5) == 0) {
- if (parse_convtable(line, afflst, &iconvtable, "ICONV")) {
+ if (line.compare(0, 5, "ICONV", 5) == 0) {
+ if (!parse_convtable(line, afflst, &iconvtable, "ICONV")) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the input conversion table */
- if (strncmp(line, "OCONV", 5) == 0) {
- if (parse_convtable(line, afflst, &oconvtable, "OCONV")) {
+ if (line.compare(0, 5, "OCONV", 5) == 0) {
+ if (!parse_convtable(line, afflst, &oconvtable, "OCONV")) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the phonetic translation table */
- if (strncmp(line, "PHONE", 5) == 0) {
- if (parse_phonetable(line, afflst)) {
+ if (line.compare(0, 5, "PHONE", 5) == 0) {
+ if (!parse_phonetable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the checkcompoundpattern table */
- if (strncmp(line, "CHECKCOMPOUNDPATTERN", 20) == 0) {
- if (parse_checkcpdtable(line, afflst)) {
+ if (line.compare(0, 20, "CHECKCOMPOUNDPATTERN", 20) == 0) {
+ if (!parse_checkcpdtable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the defcompound table */
- if (strncmp(line, "COMPOUNDRULE", 12) == 0) {
- if (parse_defcpdtable(line, afflst)) {
+ if (line.compare(0, 12, "COMPOUNDRULE", 12) == 0) {
+ if (!parse_defcpdtable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the related character map table */
- if (strncmp(line, "MAP", 3) == 0) {
- if (parse_maptable(line, afflst)) {
+ if (line.compare(0, 3, "MAP", 3) == 0) {
+ if (!parse_maptable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the word breakpoints table */
- if (strncmp(line, "BREAK", 5) == 0) {
- if (parse_breaktable(line, afflst)) {
+ if (line.compare(0, 5, "BREAK", 5) == 0) {
+ if (!parse_breaktable(line, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the language for language specific codes */
- if (strncmp(line, "LANG", 4) == 0) {
- if (parse_string(line, &lang, afflst->getlinenum())) {
+ if (line.compare(0, 4, "LANG", 4) == 0) {
+ if (!parse_string(line, lang, afflst->getlinenum())) {
finishFileMgr(afflst);
return 1;
}
langnum = get_lang_num(lang);
}
- if (strncmp(line, "VERSION", 7) == 0) {
- for (line = line + 7; *line == ' ' || *line == '\t'; line++)
- ;
- version = mystrdup(line);
+ if (line.compare(0, 7, "VERSION", 7) == 0) {
+ size_t startpos = line.find_first_not_of(" \t", 7);
+ if (startpos != std::string::npos) {
+ version = line.substr(startpos);
+ }
}
- if (strncmp(line, "MAXNGRAMSUGS", 12) == 0) {
- if (parse_num(line, &maxngramsugs, afflst)) {
+ if (line.compare(0, 12, "MAXNGRAMSUGS", 12) == 0) {
+ if (!parse_num(line, &maxngramsugs, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "ONLYMAXDIFF", 11) == 0)
+ if (line.compare(0, 11, "ONLYMAXDIFF", 11) == 0)
onlymaxdiff = 1;
- if (strncmp(line, "MAXDIFF", 7) == 0) {
- if (parse_num(line, &maxdiff, afflst)) {
+ if (line.compare(0, 7, "MAXDIFF", 7) == 0) {
+ if (!parse_num(line, &maxdiff, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "MAXCPDSUGS", 10) == 0) {
- if (parse_num(line, &maxcpdsugs, afflst)) {
+ if (line.compare(0, 10, "MAXCPDSUGS", 10) == 0) {
+ if (!parse_num(line, &maxcpdsugs, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "NOSPLITSUGS", 11) == 0) {
+ if (line.compare(0, 11, "NOSPLITSUGS", 11) == 0) {
nosplitsugs = 1;
}
- if (strncmp(line, "FULLSTRIP", 9) == 0) {
+ if (line.compare(0, 9, "FULLSTRIP", 9) == 0) {
fullstrip = 1;
}
- if (strncmp(line, "SUGSWITHDOTS", 12) == 0) {
+ if (line.compare(0, 12, "SUGSWITHDOTS", 12) == 0) {
sugswithdots = 1;
}
/* parse in the flag used by forbidden words */
- if (strncmp(line, "KEEPCASE", 8) == 0) {
- if (parse_flag(line, &keepcase, afflst)) {
+ if (line.compare(0, 8, "KEEPCASE", 8) == 0) {
+ if (!parse_flag(line, &keepcase, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by `forceucase' */
- if (strncmp(line, "FORCEUCASE", 10) == 0) {
- if (parse_flag(line, &forceucase, afflst)) {
+ if (line.compare(0, 10, "FORCEUCASE", 10) == 0) {
+ if (!parse_flag(line, &forceucase, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
/* parse in the flag used by `warn' */
- if (strncmp(line, "WARN", 4) == 0) {
- if (parse_flag(line, &warn, afflst)) {
+ if (line.compare(0, 4, "WARN", 4) == 0) {
+ if (!parse_flag(line, &warn, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "FORBIDWARN", 10) == 0) {
+ if (line.compare(0, 10, "FORBIDWARN", 10) == 0) {
forbidwarn = 1;
}
/* parse in the flag used by the affix generator */
- if (strncmp(line, "SUBSTANDARD", 11) == 0) {
- if (parse_flag(line, &substandard, afflst)) {
+ if (line.compare(0, 11, "SUBSTANDARD", 11) == 0) {
+ if (!parse_flag(line, &substandard, afflst)) {
finishFileMgr(afflst);
return 1;
}
}
- if (strncmp(line, "CHECKSHARPS", 11) == 0) {
+ if (line.compare(0, 11, "CHECKSHARPS", 11) == 0) {
checksharps = 1;
}
/* parse this affix: P - prefix, S - suffix */
- ft = ' ';
- if (strncmp(line, "PFX", 3) == 0)
+ // affix type
+ char ft = ' ';
+ if (line.compare(0, 3, "PFX", 3) == 0)
ft = complexprefixes ? 'S' : 'P';
- if (strncmp(line, "SFX", 3) == 0)
+ if (line.compare(0, 3, "SFX", 3) == 0)
ft = complexprefixes ? 'P' : 'S';
if (ft != ' ') {
if (dupflags_ini) {
memset(dupflags, 0, sizeof(dupflags));
dupflags_ini = 0;
}
- if (parse_affix(line, ft, afflst, dupflags)) {
+ if (!parse_affix(line, ft, afflst, dupflags)) {
finishFileMgr(afflst);
return 1;
}
}
}
finishFileMgr(afflst);
// affix trees are sorted now
@@ -843,47 +736,32 @@ int AffixMgr::parse_file(const char* aff
// initialize
// the nextne and nexteq pointers that relate them
process_pfx_order();
process_sfx_order();
/* get encoding for CHECKCOMPOUNDCASE */
if (!utf8) {
- char* enc = get_encoding();
- csconv = get_current_cs(enc);
- free(enc);
- enc = NULL;
-
- std::string expw;
- if (wordchars) {
- expw.assign(wordchars);
- free(wordchars);
- }
-
+ csconv = get_current_cs(get_encoding());
for (int i = 0; i <= 255; i++) {
if ((csconv[i].cupper != csconv[i].clower) &&
- (expw.find((char)i) == std::string::npos)) {
- expw.push_back((char)i);
+ (wordchars.find((char)i) == std::string::npos)) {
+ wordchars.push_back((char)i);
}
}
- wordchars = mystrdup(expw.c_str());
}
// default BREAK definition
- if (numbreak == -1) {
- breaktable = (char**)malloc(sizeof(char*) * 3);
- if (!breaktable)
- return 1;
- breaktable[0] = mystrdup("-");
- breaktable[1] = mystrdup("^-");
- breaktable[2] = mystrdup("-$");
- if (breaktable[0] && breaktable[1] && breaktable[2])
- numbreak = 3;
+ if (!parsedbreaktable) {
+ breaktable.push_back("-");
+ breaktable.push_back("^-");
+ breaktable.push_back("-$");
+ parsedbreaktable = true;
}
return 0;
}
// we want to be able to quickly access prefix information
// both by prefix flag, and sorted by prefix string itself
// so we need to set up two indexes
@@ -944,16 +822,19 @@ int AffixMgr::build_pfxtree(PfxEntry* pf
}
return 0;
}
// we want to be able to quickly access suffix information
// both by suffix flag, and sorted by the reverse of the
// suffix string itself; so we need to set up two indexes
int AffixMgr::build_sfxtree(SfxEntry* sfxptr) {
+
+ sfxptr->initReverseWord();
+
SfxEntry* ptr;
SfxEntry* pptr;
SfxEntry* ep = sfxptr;
/* get the right starting point */
const char* key = ep->getKey();
const unsigned char flg = (unsigned char)(ep->getFlag() & 0x00FF);
@@ -1138,27 +1019,16 @@ int AffixMgr::process_sfx_order() {
if (mptr)
mptr->setNextNE(NULL);
}
}
return 0;
}
// add flags to the result for dictionary debugging
-void AffixMgr::debugflag(char* result, unsigned short flag) {
- char* st = encode_flag(flag);
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, MORPH_FLAG, MAXLNLEN);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
-}
-
-// add flags to the result for dictionary debugging
std::string& AffixMgr::debugflag(std::string& result, unsigned short flag) {
char* st = encode_flag(flag);
result.append(" ");
result.append(MORPH_FLAG);
if (st) {
result.append(st);
free(st);
}
@@ -1176,23 +1046,28 @@ int AffixMgr::condlen(const char* st) {
} else if (*st == ']')
group = false;
else if (!group && (!utf8 || (!(*st & 0x80) || ((*st & 0xc0) == 0x80))))
l++;
}
return l;
}
-int AffixMgr::encodeit(affentry& entry, const char* cs) {
+int AffixMgr::encodeit(AffEntry& entry, const char* cs) {
if (strcmp(cs, ".") != 0) {
entry.numconds = (char)condlen(cs);
- // coverity[buffer_size_warning] - deliberate use of lack of end of conds
- // padded by strncpy as long condition flag
- strncpy(entry.c.conds, cs, MAXCONDLEN);
- if (entry.c.conds[MAXCONDLEN - 1] && cs[MAXCONDLEN]) {
+ const size_t cslen = strlen(cs);
+ const size_t short_part = std::min<size_t>(MAXCONDLEN, cslen);
+ memcpy(entry.c.conds, cs, short_part);
+ if (short_part < MAXCONDLEN) {
+ //blank out the remaining space
+ memset(entry.c.conds + short_part, 0, MAXCONDLEN - short_part);
+ } else if (cs[MAXCONDLEN]) {
+ //there is more conditions than fit in fixed space, so its
+ //a long condition
entry.opts += aeLONGCOND;
entry.c.l.conds2 = mystrdup(cs + MAXCONDLEN_1);
if (!entry.c.l.conds2)
return 1;
}
} else {
entry.numconds = 0;
entry.c.conds[0] = '\0';
@@ -1311,156 +1186,149 @@ struct hentry* AffixMgr::prefix_check_tw
pptr = pptr->getNextNE();
}
}
return NULL;
}
// check word for prefixes
-char* AffixMgr::prefix_check_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag) {
-
- char result[MAXLNLEN];
- result[0] = '\0';
+std::string AffixMgr::prefix_check_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag) {
+
+ std::string result;
pfx = NULL;
sfxappnd = NULL;
sfxextra = 0;
// first handle the special case of 0 length prefixes
PfxEntry* pe = pStart[0];
while (pe) {
- char* st = pe->check_morph(word, len, in_compound, needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
- }
- // if (rv) return rv;
- pe = pe->getNext();
- }
-
- // now handle the general case
- unsigned char sp = *((const unsigned char*)word);
- PfxEntry* pptr = pStart[sp];
-
- while (pptr) {
- if (isSubset(pptr->getKey(), word)) {
- char* st = pptr->check_morph(word, len, in_compound, needflag);
- if (st) {
- // fogemorpheme
- if ((in_compound != IN_CPD_NOT) ||
- !((pptr->getCont() && (TESTAFF(pptr->getCont(), onlyincompound,
- pptr->getContLen()))))) {
- mystrcat(result, st, MAXLNLEN);
- pfx = pptr;
- }
- free(st);
- }
- pptr = pptr->getNextEQ();
- } else {
- pptr = pptr->getNextNE();
- }
- }
-
- if (*result)
- return mystrdup(result);
- return NULL;
-}
-
-// check word for prefixes
-char* AffixMgr::prefix_check_twosfx_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag) {
- char result[MAXLNLEN];
- result[0] = '\0';
-
- pfx = NULL;
- sfxappnd = NULL;
- sfxextra = 0;
-
- // first handle the special case of 0 length prefixes
- PfxEntry* pe = pStart[0];
- while (pe) {
- char* st = pe->check_twosfx_morph(word, len, in_compound, needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ std::string st = pe->check_morph(word, len, in_compound, needflag);
+ if (!st.empty()) {
+ result.append(st);
}
pe = pe->getNext();
}
// now handle the general case
unsigned char sp = *((const unsigned char*)word);
PfxEntry* pptr = pStart[sp];
while (pptr) {
if (isSubset(pptr->getKey(), word)) {
- char* st = pptr->check_twosfx_morph(word, len, in_compound, needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ std::string st = pptr->check_morph(word, len, in_compound, needflag);
+ if (!st.empty()) {
+ // fogemorpheme
+ if ((in_compound != IN_CPD_NOT) ||
+ !((pptr->getCont() && (TESTAFF(pptr->getCont(), onlyincompound,
+ pptr->getContLen()))))) {
+ result.append(st);
+ pfx = pptr;
+ }
+ }
+ pptr = pptr->getNextEQ();
+ } else {
+ pptr = pptr->getNextNE();
+ }
+ }
+
+ return result;
+}
+
+// check word for prefixes
+std::string AffixMgr::prefix_check_twosfx_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag) {
+ std::string result;
+
+ pfx = NULL;
+ sfxappnd = NULL;
+ sfxextra = 0;
+
+ // first handle the special case of 0 length prefixes
+ PfxEntry* pe = pStart[0];
+ while (pe) {
+ std::string st = pe->check_twosfx_morph(word, len, in_compound, needflag);
+ if (!st.empty()) {
+ result.append(st);
+ }
+ pe = pe->getNext();
+ }
+
+ // now handle the general case
+ unsigned char sp = *((const unsigned char*)word);
+ PfxEntry* pptr = pStart[sp];
+
+ while (pptr) {
+ if (isSubset(pptr->getKey(), word)) {
+ std::string st = pptr->check_twosfx_morph(word, len, in_compound, needflag);
+ if (!st.empty()) {
+ result.append(st);
pfx = pptr;
}
pptr = pptr->getNextEQ();
} else {
pptr = pptr->getNextNE();
}
}
- if (*result)
- return mystrdup(result);
- return NULL;
+ return result;
}
// Is word a non compound with a REP substitution (see checkcompoundrep)?
int AffixMgr::cpdrep_check(const char* word, int wl) {
- if ((wl < 2) || !numrep)
+ if ((wl < 2) || reptable.empty())
return 0;
- for (int i = 0; i < numrep; i++) {
+ for (size_t i = 0; i < reptable.size(); ++i) {
const char* r = word;
- int lenp = strlen(reptable[i].pattern);
+ const size_t lenp = reptable[i].pattern.size();
// search every occurence of the pattern in the word
- while ((r = strstr(r, reptable[i].pattern)) != NULL) {
+ while ((r = strstr(r, reptable[i].pattern.c_str())) != NULL) {
std::string candidate(word);
- candidate.replace(r - word, lenp, reptable[i].pattern2);
+ size_t type = r == word ? 1 : 0;
+ if (r - word + reptable[i].pattern.size() == lenp)
+ type += 2;
+ candidate.replace(r - word, lenp, reptable[i].outstrings[type]);
if (candidate_check(candidate.c_str(), candidate.size()))
return 1;
- r++; // search for the next letter
+ ++r; // search for the next letter
}
}
+
return 0;
}
// forbid compoundings when there are special patterns at word bound
int AffixMgr::cpdpat_check(const char* word,
int pos,
hentry* r1,
hentry* r2,
const char /*affixed*/) {
- int len;
- for (int i = 0; i < numcheckcpd; i++) {
- if (isSubset(checkcpdtable[i].pattern2, word + pos) &&
+ for (size_t i = 0; i < checkcpdtable.size(); ++i) {
+ size_t len;
+ if (isSubset(checkcpdtable[i].pattern2.c_str(), word + pos) &&
(!r1 || !checkcpdtable[i].cond ||
(r1->astr && TESTAFF(r1->astr, checkcpdtable[i].cond, r1->alen))) &&
(!r2 || !checkcpdtable[i].cond2 ||
(r2->astr && TESTAFF(r2->astr, checkcpdtable[i].cond2, r2->alen))) &&
// zero length pattern => only TESTAFF
// zero pattern (0/flag) => unmodified stem (zero affixes allowed)
- (!*(checkcpdtable[i].pattern) ||
- ((*(checkcpdtable[i].pattern) == '0' && r1->blen <= pos &&
+ (checkcpdtable[i].pattern.empty() ||
+ ((checkcpdtable[i].pattern[0] == '0' && r1->blen <= pos &&
strncmp(word + pos - r1->blen, r1->word, r1->blen) == 0) ||
- (*(checkcpdtable[i].pattern) != '0' &&
- ((len = strlen(checkcpdtable[i].pattern)) != 0) &&
- strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)))) {
+ (checkcpdtable[i].pattern[0] != '0' &&
+ ((len = checkcpdtable[i].pattern.size()) != 0) &&
+ strncmp(word + pos - len, checkcpdtable[i].pattern.c_str(), len) == 0)))) {
return 1;
}
}
return 0;
}
// forbid compounding with neighbouring upper and lower case characters at word
// bounds
@@ -1508,63 +1376,62 @@ int AffixMgr::defcpd_check(hentry*** wor
if (!*words) {
return 0;
}
std::vector<metachar_data> btinfo(1);
short bt = 0;
- int i, j;
(*words)[wnum] = rv;
// has the last word COMPOUNDRULE flag?
if (rv->alen == 0) {
(*words)[wnum] = NULL;
if (w)
*words = NULL;
return 0;
}
int ok = 0;
- for (i = 0; i < numdefcpd; i++) {
- for (j = 0; j < defcpdtable[i].len; j++) {
- if (defcpdtable[i].def[j] != '*' && defcpdtable[i].def[j] != '?' &&
- TESTAFF(rv->astr, defcpdtable[i].def[j], rv->alen)) {
+ for (size_t i = 0; i < defcpdtable.size(); ++i) {
+ for (size_t j = 0; j < defcpdtable[i].size(); ++j) {
+ if (defcpdtable[i][j] != '*' && defcpdtable[i][j] != '?' &&
+ TESTAFF(rv->astr, defcpdtable[i][j], rv->alen)) {
ok = 1;
break;
}
}
}
if (ok == 0) {
(*words)[wnum] = NULL;
if (w)
*words = NULL;
return 0;
}
- for (i = 0; i < numdefcpd; i++) {
- signed short pp = 0; // pattern position
+ for (size_t i = 0; i < defcpdtable.size(); ++i) {
+ size_t pp = 0; // pattern position
signed short wp = 0; // "words" position
int ok2;
ok = 1;
ok2 = 1;
do {
- while ((pp < defcpdtable[i].len) && (wp <= wnum)) {
- if (((pp + 1) < defcpdtable[i].len) &&
- ((defcpdtable[i].def[pp + 1] == '*') ||
- (defcpdtable[i].def[pp + 1] == '?'))) {
- int wend = (defcpdtable[i].def[pp + 1] == '?') ? wp : wnum;
+ while ((pp < defcpdtable[i].size()) && (wp <= wnum)) {
+ if (((pp + 1) < defcpdtable[i].size()) &&
+ ((defcpdtable[i][pp + 1] == '*') ||
+ (defcpdtable[i][pp + 1] == '?'))) {
+ int wend = (defcpdtable[i][pp + 1] == '?') ? wp : wnum;
ok2 = 1;
pp += 2;
btinfo[bt].btpp = pp;
btinfo[bt].btwp = wp;
while (wp <= wend) {
if (!(*words)[wp]->alen ||
- !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp - 2],
+ !TESTAFF((*words)[wp]->astr, defcpdtable[i][pp - 2],
(*words)[wp]->alen)) {
ok2 = 0;
break;
}
wp++;
}
if (wp <= wnum)
ok2 = 0;
@@ -1573,56 +1440,56 @@ int AffixMgr::defcpd_check(hentry*** wor
++bt;
btinfo.resize(bt+1);
}
if (ok2)
break;
} else {
ok2 = 1;
if (!(*words)[wp] || !(*words)[wp]->alen ||
- !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp],
+ !TESTAFF((*words)[wp]->astr, defcpdtable[i][pp],
(*words)[wp]->alen)) {
ok = 0;
break;
}
pp++;
wp++;
- if ((defcpdtable[i].len == pp) && !(wp > wnum))
+ if ((defcpdtable[i].size() == pp) && !(wp > wnum))
ok = 0;
}
}
if (ok && ok2) {
- int r = pp;
- while ((defcpdtable[i].len > r) && ((r + 1) < defcpdtable[i].len) &&
- ((defcpdtable[i].def[r + 1] == '*') ||
- (defcpdtable[i].def[r + 1] == '?')))
+ size_t r = pp;
+ while ((defcpdtable[i].size() > r) && ((r + 1) < defcpdtable[i].size()) &&
+ ((defcpdtable[i][r + 1] == '*') ||
+ (defcpdtable[i][r + 1] == '?')))
r += 2;
- if (defcpdtable[i].len <= r)
+ if (defcpdtable[i].size() <= r)
return 1;
}
// backtrack
if (bt)
do {
ok = 1;
btinfo[bt - 1].btnum--;
pp = btinfo[bt - 1].btpp;
wp = btinfo[bt - 1].btwp + (signed short)btinfo[bt - 1].btnum;
} while ((btinfo[bt - 1].btnum < 0) && --bt);
} while (bt);
- if (ok && ok2 && (!all || (defcpdtable[i].len <= pp)))
+ if (ok && ok2 && (!all || (defcpdtable[i].size() <= pp)))
return 1;
// check zero ending
- while (ok && ok2 && (defcpdtable[i].len > pp) &&
- ((pp + 1) < defcpdtable[i].len) &&
- ((defcpdtable[i].def[pp + 1] == '*') ||
- (defcpdtable[i].def[pp + 1] == '?')))
+ while (ok && ok2 && (defcpdtable[i].size() > pp) &&
+ ((pp + 1) < defcpdtable[i].size()) &&
+ ((defcpdtable[i][pp + 1] == '*') ||
+ (defcpdtable[i][pp + 1] == '?')))
pp += 2;
- if (ok && ok2 && (defcpdtable[i].len <= pp))
+ if (ok && ok2 && (defcpdtable[i].size() <= pp))
return 1;
}
(*words)[wnum] = NULL;
if (w)
*words = NULL;
return 0;
}
@@ -1646,30 +1513,33 @@ inline int AffixMgr::candidate_check(con
short AffixMgr::get_syllable(const std::string& word) {
if (cpdmaxsyllable == 0)
return 0;
short num = 0;
if (!utf8) {
for (size_t i = 0; i < word.size(); ++i) {
- if (strchr(cpdvowels, word[i]))
- num++;
+ if (std::binary_search(cpdvowels.begin(), cpdvowels.end(),
+ word[i])) {
+ ++num;
+ }
}
- } else if (cpdvowels_utf16) {
+ } else if (!cpdvowels_utf16.empty()) {
std::vector<w_char> w;
- int i = u8_u16(w, word);
- for (; i > 0; i--) {
- if (std::binary_search(cpdvowels_utf16,
- cpdvowels_utf16 + cpdvowels_utf16_len,
- w[i - 1])) {
+ u8_u16(w, word);
+ for (size_t i = 0; i < w.size(); ++i) {
+ if (std::binary_search(cpdvowels_utf16.begin(),
+ cpdvowels_utf16.end(),
+ w[i])) {
++num;
}
}
}
+
return num;
}
void AffixMgr::setcminmax(int* cmin, int* cmax, const char* word, int len) {
if (utf8) {
int i;
for (*cmin = 0, i = 0; (i < cpdmin) && *cmin < len; i++) {
for ((*cmin)++; *cmin < len && (word[*cmin] & 0xc0) == 0x80; (*cmin)++)
@@ -1682,18 +1552,17 @@ void AffixMgr::setcminmax(int* cmin, int
} else {
*cmin = cpdmin;
*cmax = len - cpdmin + 1;
}
}
// check if compound word is correctly spelled
// hu_mov_rule = spec. Hungarian rule (XXX)
-struct hentry* AffixMgr::compound_check(const char* word,
- int len,
+struct hentry* AffixMgr::compound_check(const std::string& word,
short wordnum,
short numsyllable,
short maxwordnum,
short wnum,
hentry** words = NULL,
hentry** rwords = NULL,
char hu_mov_rule = 0,
char is_sug = 0,
@@ -1702,73 +1571,73 @@ struct hentry* AffixMgr::compound_check(
short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
struct hentry* rv = NULL;
struct hentry* rv_first;
std::string st;
char ch = '\0';
int cmin;
int cmax;
int striple = 0;
- int scpd = 0;
+ size_t scpd = 0;
int soldi = 0;
int oldcmin = 0;
int oldcmax = 0;
int oldlen = 0;
int checkedstriple = 0;
- int onlycpdrule;
char affixed = 0;
hentry** oldwords = words;
+ size_t len = word.size();
int checked_prefix;
- setcminmax(&cmin, &cmax, word, len);
+ setcminmax(&cmin, &cmax, word.c_str(), len);
st.assign(word);
for (i = cmin; i < cmax; i++) {
// go to end of the UTF-8 character
if (utf8) {
for (; (st[i] & 0xc0) == 0x80; i++)
;
if (i >= cmax)
return NULL;
}
words = oldwords;
- onlycpdrule = (words) ? 1 : 0;
+ int onlycpdrule = (words) ? 1 : 0;
do { // onlycpdrule loop
oldnumsyllable = numsyllable;
oldwordnum = wordnum;
checked_prefix = 0;
do { // simplified checkcompoundpattern loop
if (scpd > 0) {
- for (; scpd <= numcheckcpd &&
- (!checkcpdtable[scpd - 1].pattern3 ||
- strncmp(word + i, checkcpdtable[scpd - 1].pattern3,
- strlen(checkcpdtable[scpd - 1].pattern3)) != 0);
+ for (; scpd <= checkcpdtable.size() &&
+ (checkcpdtable[scpd - 1].pattern3.empty() ||
+ strncmp(word.c_str() + i, checkcpdtable[scpd - 1].pattern3.c_str(),
+ checkcpdtable[scpd - 1].pattern3.size()) != 0);
scpd++)
;
- if (scpd > numcheckcpd)
+ if (scpd > checkcpdtable.size())
break; // break simplified checkcompoundpattern loop
st.replace(i, std::string::npos, checkcpdtable[scpd - 1].pattern);
soldi = i;
- i += strlen(checkcpdtable[scpd - 1].pattern);
+ i += checkcpdtable[scpd - 1].pattern.size();
st.replace(i, std::string::npos, checkcpdtable[scpd - 1].pattern2);
- st.replace(i + strlen(checkcpdtable[scpd - 1].pattern2), std::string::npos,
- word + soldi + strlen(checkcpdtable[scpd - 1].pattern3));
+ st.replace(i + checkcpdtable[scpd - 1].pattern2.size(), std::string::npos,
+ word.substr(soldi + checkcpdtable[scpd - 1].pattern3.size()));
oldlen = len;
- len += strlen(checkcpdtable[scpd - 1].pattern) +
- strlen(checkcpdtable[scpd - 1].pattern2) -
- strlen(checkcpdtable[scpd - 1].pattern3);
+ len += checkcpdtable[scpd - 1].pattern.size() +
+ checkcpdtable[scpd - 1].pattern2.size() -
+ checkcpdtable[scpd - 1].pattern3.size();
oldcmin = cmin;
oldcmax = cmax;
setcminmax(&cmin, &cmax, st.c_str(), len);
cmax = len - cpdmin + 1;
}
ch = st[i];
@@ -1786,17 +1655,17 @@ struct hentry* AffixMgr::compound_check(
while ((rv) && !hu_mov_rule &&
((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
!((compoundflag && !words && !onlycpdrule &&
TESTAFF(rv->astr, compoundflag, rv->alen)) ||
(compoundbegin && !wordnum && !onlycpdrule &&
TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
(compoundmiddle && wordnum && !words && !onlycpdrule &&
TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
- (numdefcpd && onlycpdrule &&
+ (!defcpdtable.empty() && onlycpdrule &&
((!words && !wordnum &&
defcpd_check(&words, wnum, rv, rwords, 0)) ||
(words &&
defcpd_check(&words, wnum, rv, rwords, 0))))) ||
(scpd != 0 && checkcpdtable[scpd - 1].cond != FLAG_NULL &&
!TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond, rv->alen)))) {
rv = rv->next_homonym;
}
@@ -1807,45 +1676,45 @@ struct hentry* AffixMgr::compound_check(
if (!rv) {
if (onlycpdrule)
break;
if (compoundflag &&
!(rv = prefix_check(st.c_str(), i,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
compoundflag))) {
if (((rv = suffix_check(
- st.c_str(), i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundflag,
+ st.c_str(), i, 0, NULL, FLAG_NULL, compoundflag,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
(compoundmoresuffixes &&
(rv = suffix_check_twosfx(st.c_str(), i, 0, NULL, compoundflag)))) &&
!hu_mov_rule && sfx->getCont() &&
((compoundforbidflag &&
TESTAFF(sfx->getCont(), compoundforbidflag,
sfx->getContLen())) ||
(compoundend &&
TESTAFF(sfx->getCont(), compoundend, sfx->getContLen())))) {
rv = NULL;
}
}
if (rv ||
(((wordnum == 0) && compoundbegin &&
((rv = suffix_check(
- st.c_str(), i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin,
+ st.c_str(), i, 0, NULL, FLAG_NULL, compoundbegin,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
(compoundmoresuffixes &&
(rv = suffix_check_twosfx(
st.c_str(), i, 0, NULL,
compoundbegin))) || // twofold suffixes + compound
(rv = prefix_check(st.c_str(), i,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
compoundbegin)))) ||
((wordnum > 0) && compoundmiddle &&
((rv = suffix_check(
- st.c_str(), i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle,
+ st.c_str(), i, 0, NULL, FLAG_NULL, compoundmiddle,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
(compoundmoresuffixes &&
(rv = suffix_check_twosfx(
st.c_str(), i, 0, NULL,
compoundmiddle))) || // twofold suffixes + compound
(rv = prefix_check(st.c_str(), i,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
compoundmiddle))))))
@@ -1906,18 +1775,17 @@ struct hentry* AffixMgr::compound_check(
// first word is acceptable in compound words?
if (((rv) &&
(checked_prefix || (words && words[wnum]) ||
(compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
((oldwordnum == 0) && compoundbegin &&
TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
((oldwordnum > 0) && compoundmiddle &&
- TESTAFF(rv->astr, compoundmiddle, rv->alen)) // ||
- // (numdefcpd && )
+ TESTAFF(rv->astr, compoundmiddle, rv->alen))
// LANG_hu section: spec. Hungarian rule
|| ((langnum == LANG_hu) && hu_mov_rule &&
(TESTAFF(
rv->astr, 'F',
rv->alen) || // XXX hardwired Hungarian dictionary codes
TESTAFF(rv->astr, 'G', rv->alen) ||
TESTAFF(rv->astr, 'H', rv->alen)))
@@ -1929,17 +1797,17 @@ struct hentry* AffixMgr::compound_check(
TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond, rv->alen)) &&
!((checkcompoundtriple && scpd == 0 &&
!words && // test triple letters
(word[i - 1] == word[i]) &&
(((i > 1) && (word[i - 1] == word[i - 2])) ||
((word[i - 1] == word[i + 1])) // may be word[i+1] == '\0'
)) ||
(checkcompoundcase && scpd == 0 && !words &&
- cpdcase_check(word, i))))
+ cpdcase_check(word.c_str(), i))))
// LANG_hu section: spec. Hungarian rule
|| ((!rv) && (langnum == LANG_hu) && hu_mov_rule &&
(rv = affix_check(st.c_str(), i)) &&
(sfx && sfx->getCont() &&
( // XXX hardwired Hungarian dic. codes
TESTAFF(sfx->getCont(), (unsigned short)'x',
sfx->getContLen()) ||
TESTAFF(
@@ -1963,30 +1831,30 @@ struct hentry* AffixMgr::compound_check(
do { // striple loop
// check simplifiedtriple
if (simplifiedtriple) {
if (striple) {
checkedstriple = 1;
i--; // check "fahrt" instead of "ahrt" in "Schiffahrt"
- } else if (i > 2 && *(word + i - 1) == *(word + i - 2))
+ } else if (i > 2 && word[i - 1] == word[i - 2])
striple = 1;
}
rv = lookup(st.c_str() + i); // perhaps without prefix
// search homonym with compound flag
while ((rv) &&
((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
!((compoundflag && !words &&
TESTAFF(rv->astr, compoundflag, rv->alen)) ||
(compoundend && !words &&
TESTAFF(rv->astr, compoundend, rv->alen)) ||
- (numdefcpd && words &&
+ (!defcpdtable.empty() && words &&
defcpd_check(&words, wnum + 1, rv, NULL, 1))) ||
(scpd != 0 && checkcpdtable[scpd - 1].cond2 != FLAG_NULL &&
!TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond2,
rv->alen)))) {
rv = rv->next_homonym;
}
// check FORCEUCASE
@@ -2033,63 +1901,63 @@ struct hentry* AffixMgr::compound_check(
((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
(compoundend && TESTAFF(rv->astr, compoundend, rv->alen))) &&
(((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
((cpdmaxsyllable != 0) &&
(numsyllable + get_syllable(std::string(HENTRY_WORD(rv), rv->clen)) <=
cpdmaxsyllable))) &&
(
// test CHECKCOMPOUNDPATTERN
- !numcheckcpd || scpd != 0 ||
- !cpdpat_check(word, i, rv_first, rv, 0)) &&
+ checkcpdtable.empty() || scpd != 0 ||
+ !cpdpat_check(word.c_str(), i, rv_first, rv, 0)) &&
((!checkcompounddup || (rv != rv_first)))
// test CHECKCOMPOUNDPATTERN conditions
&&
(scpd == 0 || checkcpdtable[scpd - 1].cond2 == FLAG_NULL ||
TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond2, rv->alen))) {
// forbid compound word, if it is a non compound word with typical
// fault
- if (checkcompoundrep && cpdrep_check(word, len))
+ if (checkcompoundrep && cpdrep_check(word.c_str(), len))
return NULL;
return rv_first;
}
numsyllable = oldnumsyllable2;
wordnum = oldwordnum2;
// perhaps second word has prefix or/and suffix
sfx = NULL;
sfxflag = FLAG_NULL;
rv = (compoundflag && !onlycpdrule)
- ? affix_check((word + i), strlen(word + i), compoundflag,
+ ? affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundflag,
IN_CPD_END)
: NULL;
if (!rv && compoundend && !onlycpdrule) {
sfx = NULL;
pfx = NULL;
- rv = affix_check((word + i), strlen(word + i), compoundend,
+ rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundend,
IN_CPD_END);
}
- if (!rv && numdefcpd && words) {
- rv = affix_check((word + i), strlen(word + i), 0, IN_CPD_END);
+ if (!rv && !defcpdtable.empty() && words) {
+ rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), 0, IN_CPD_END);
if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1))
return rv_first;
rv = NULL;
}
// test CHECKCOMPOUNDPATTERN conditions (allowed forms)
if (rv &&
!(scpd == 0 || checkcpdtable[scpd - 1].cond2 == FLAG_NULL ||
TESTAFF(rv->astr, checkcpdtable[scpd - 1].cond2, rv->alen)))
rv = NULL;
// test CHECKCOMPOUNDPATTERN conditions (forbidden compounds)
- if (rv && numcheckcpd && scpd == 0 &&
- cpdpat_check(word, i, rv_first, rv, affixed))
+ if (rv && !checkcpdtable.empty() && scpd == 0 &&
+ cpdpat_check(word.c_str(), i, rv_first, rv, affixed))
rv = NULL;
// check non_compound flag in suffix and prefix
if ((rv) && ((pfx && pfx->getCont() &&
TESTAFF(pfx->getCont(), compoundforbidflag,
pfx->getContLen())) ||
(sfx && sfx->getCont() &&
TESTAFF(sfx->getCont(), compoundforbidflag,
@@ -2113,17 +1981,17 @@ struct hentry* AffixMgr::compound_check(
// pfxappnd = prefix of word+i, or NULL
// calculate syllable number of prefix.
// hungarian convention: when syllable number of prefix is more,
// than 1, the prefix+word counts as two words.
if (langnum == LANG_hu) {
// calculate syllable number of the word
- numsyllable += get_syllable(word + i);
+ numsyllable += get_syllable(word.c_str() + i);
// - affix syllable num.
// XXX only second suffix (inflections, not derivations)
if (sfxappnd) {
std::string tmp(sfxappnd);
reverseword(tmp);
numsyllable -= get_syllable(tmp) + sfxextra;
}
@@ -2131,17 +1999,17 @@ struct hentry* AffixMgr::compound_check(
// + 1 word, if syllable number of the prefix > 1 (hungarian
// convention)
if (pfx && (get_syllable(pfx->getKey()) > 1))
wordnum++;
// increment syllable num, if last word has a SYLLABLENUM flag
// and the suffix is beginning `s'
- if (cpdsyllablenum) {
+ if (!cpdsyllablenum.empty()) {
switch (sfxflag) {
case 'c': {
numsyllable += 2;
break;
}
case 'J': {
numsyllable += 1;
break;
@@ -2166,62 +2034,61 @@ struct hentry* AffixMgr::compound_check(
// when compound forms consist 2 word, otherwise
// the syllable number of root words is 6, or lesser.
if ((rv) &&
(((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
((cpdmaxsyllable != 0) && (numsyllable <= cpdmaxsyllable))) &&
((!checkcompounddup || (rv != rv_first)))) {
// forbid compound word, if it is a non compound word with typical
// fault
- if (checkcompoundrep && cpdrep_check(word, len))
+ if (checkcompoundrep && cpdrep_check(word.c_str(), len))
return NULL;
return rv_first;
}
numsyllable = oldnumsyllable2;
wordnum = oldwordnum2;
// perhaps second word is a compound word (recursive call)
if (wordnum < maxwordnum) {
- rv = compound_check(st.c_str() + i, strlen(st.c_str() + i), wordnum + 1,
+ rv = compound_check(st.substr(i), wordnum + 1,
numsyllable, maxwordnum, wnum + 1, words, rwords, 0,
is_sug, info);
- if (rv && numcheckcpd &&
+ if (rv && !checkcpdtable.empty() &&
((scpd == 0 &&
- cpdpat_check(word, i, rv_first, rv, affixed)) ||
+ cpdpat_check(word.c_str(), i, rv_first, rv, affixed)) ||
(scpd != 0 &&
- !cpdpat_check(word, i, rv_first, rv, affixed))))
+ !cpdpat_check(word.c_str(), i, rv_first, rv, affixed))))
rv = NULL;
} else {
rv = NULL;
}
if (rv) {
// forbid compound word, if it is a non compound word with typical
// fault
if (checkcompoundrep || forbiddenword) {
- struct hentry* rv2 = NULL;
-
- if (checkcompoundrep && cpdrep_check(word, len))
+
+ if (checkcompoundrep && cpdrep_check(word.c_str(), len))
return NULL;
// check first part
- if (strncmp(rv->word, word + i, rv->blen) == 0) {
+ if (strncmp(rv->word, word.c_str() + i, rv->blen) == 0) {
char r = st[i + rv->blen];
st[i + rv->blen] = '\0';
if (checkcompoundrep && cpdrep_check(st.c_str(), i + rv->blen)) {
st[ + i + rv->blen] = r;
continue;
}
if (forbiddenword) {
- rv2 = lookup(word);
+ struct hentry* rv2 = lookup(word.c_str());
if (!rv2)
- rv2 = affix_check(word, len);
+ rv2 = affix_check(word.c_str(), len);
if (rv2 && rv2->astr &&
TESTAFF(rv2->astr, forbiddenword, rv2->alen) &&
(strncmp(rv2->word, st.c_str(), i + rv->blen) == 0)) {
return NULL;
}
}
st[i + rv->blen] = r;
}
@@ -2243,65 +2110,64 @@ struct hentry* AffixMgr::compound_check(
soldi = 0;
len = oldlen;
cmin = oldcmin;
cmax = oldcmax;
}
scpd++;
} while (!onlycpdrule && simplifiedcpd &&
- scpd <= numcheckcpd); // end of simplifiedcpd loop
+ scpd <= checkcpdtable.size()); // end of simplifiedcpd loop
scpd = 0;
wordnum = oldwordnum;
numsyllable = oldnumsyllable;
if (soldi != 0) {
i = soldi;
st.assign(word); // XXX add more optim.
soldi = 0;
} else
st[i] = ch;
- } while (numdefcpd && oldwordnum == 0 &&
+ } while (!defcpdtable.empty() && oldwordnum == 0 &&
onlycpdrule++ < 1); // end of onlycpd loop
}
return NULL;
}
// check if compound word is correctly spelled
// hu_mov_rule = spec. Hungarian rule (XXX)
int AffixMgr::compound_check_morph(const char* word,
int len,
short wordnum,
short numsyllable,
short maxwordnum,
short wnum,
hentry** words,
hentry** rwords,
- char hu_mov_rule = 0,
- char** result = NULL,
- char* partresult = NULL) {
+ char hu_mov_rule,
+ std::string& result,
+ const std::string* partresult) {
int i;
short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2;
int ok = 0;
struct hentry* rv = NULL;
struct hentry* rv_first;
std::string st;
char ch;
int checked_prefix;
- char presult[MAXLNLEN];
+ std::string presult;
int cmin;
int cmax;
- int onlycpdrule;
char affixed = 0;
hentry** oldwords = words;
setcminmax(&cmin, &cmax, word, len);
st.assign(word);
for (i = cmin; i < cmax; i++) {
@@ -2309,138 +2175,133 @@ int AffixMgr::compound_check_morph(const
if (utf8) {
for (; (st[i] & 0xc0) == 0x80; i++)
;
if (i >= cmax)
return 0;
}
words = oldwords;
- onlycpdrule = (words) ? 1 : 0;
+ int onlycpdrule = (words) ? 1 : 0;
do { // onlycpdrule loop
oldnumsyllable = numsyllable;
oldwordnum = wordnum;
checked_prefix = 0;
ch = st[i];
st[i] = '\0';
sfx = NULL;
// FIRST WORD
affixed = 1;
- *presult = '\0';
+ presult.clear();
if (partresult)
- mystrcat(presult, partresult, MAXLNLEN);
+ presult.append(*partresult);
rv = lookup(st.c_str()); // perhaps without prefix
// search homonym with compound flag
while ((rv) && !hu_mov_rule &&
((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
!((compoundflag && !words && !onlycpdrule &&
TESTAFF(rv->astr, compoundflag, rv->alen)) ||
(compoundbegin && !wordnum && !onlycpdrule &&
TESTAFF(rv->astr, compoundbegin, rv->alen)) ||
(compoundmiddle && wordnum && !words && !onlycpdrule &&
TESTAFF(rv->astr, compoundmiddle, rv->alen)) ||
- (numdefcpd && onlycpdrule &&
+ (!defcpdtable.empty() && onlycpdrule &&
((!words && !wordnum &&
defcpd_check(&words, wnum, rv, rwords, 0)) ||
(words &&
defcpd_check(&words, wnum, rv, rwords, 0))))))) {
rv = rv->next_homonym;
}
if (rv)
affixed = 0;
if (rv) {
- sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_PART, st.c_str());
+ presult.push_back(MSEP_FLD);
+ presult.append(MORPH_PART);
+ presult.append(st.c_str());
if (!HENTRY_FIND(rv, MORPH_STEM)) {
- sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_STEM,
- st.c_str());
+ presult.push_back(MSEP_FLD);
+ presult.append(MORPH_STEM);
+ presult.append(st.c_str());
}
- // store the pointer of the hash entry
- // sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD,
- // MORPH_HENTRY, rv);
if (HENTRY_DATA(rv)) {
- sprintf(presult + strlen(presult), "%c%s", MSEP_FLD,
- HENTRY_DATA2(rv));
+ presult.push_back(MSEP_FLD);
+ presult.append(HENTRY_DATA2(rv));
}
}
if (!rv) {
- if (onlycpdrule && strlen(*result) > MAXLNLEN / 10)
- break;
if (compoundflag &&
!(rv =
prefix_check(st.c_str(), i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
compoundflag))) {
- if (((rv = suffix_check(st.c_str(), i, 0, NULL, NULL, 0, NULL, FLAG_NULL,
+ if (((rv = suffix_check(st.c_str(), i, 0, NULL, FLAG_NULL,
compoundflag,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
(compoundmoresuffixes &&
(rv = suffix_check_twosfx(st.c_str(), i, 0, NULL, compoundflag)))) &&
!hu_mov_rule && sfx->getCont() &&
((compoundforbidflag &&
TESTAFF(sfx->getCont(), compoundforbidflag,
sfx->getContLen())) ||
(compoundend &&
TESTAFF(sfx->getCont(), compoundend, sfx->getContLen())))) {
rv = NULL;
}
}
if (rv ||
(((wordnum == 0) && compoundbegin &&
- ((rv = suffix_check(st.c_str(), i, 0, NULL, NULL, 0, NULL, FLAG_NULL,
+ ((rv = suffix_check(st.c_str(), i, 0, NULL, FLAG_NULL,
compoundbegin,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
(compoundmoresuffixes &&
(rv = suffix_check_twosfx(
st.c_str(), i, 0, NULL,
compoundbegin))) || // twofold suffix+compound
(rv = prefix_check(st.c_str(), i,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
compoundbegin)))) ||
((wordnum > 0) && compoundmiddle &&
- ((rv = suffix_check(st.c_str(), i, 0, NULL, NULL, 0, NULL, FLAG_NULL,
+ ((rv = suffix_check(st.c_str(), i, 0, NULL, FLAG_NULL,
compoundmiddle,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) ||
(compoundmoresuffixes &&
(rv = suffix_check_twosfx(
st.c_str(), i, 0, NULL,
compoundmiddle))) || // twofold suffix+compound
(rv = prefix_check(st.c_str(), i,
hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN,
compoundmiddle)))))) {
- // char * p = prefix_check_morph(st, i, 0, compound);
- char* p = NULL;
+ std::string p;
if (compoundflag)
p = affix_check_morph(st.c_str(), i, compoundflag);
- if (!p || (*p == '\0')) {
- if (p)
- free(p);
- p = NULL;
+ if (p.empty()) {
if ((wordnum == 0) && compoundbegin) {
p = affix_check_morph(st.c_str(), i, compoundbegin);
} else if ((wordnum > 0) && compoundmiddle) {
p = affix_check_morph(st.c_str(), i, compoundmiddle);
}
}
- if (p && (*p != '\0')) {
- sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD, MORPH_PART,
- st.c_str(), line_uniq_app(&p, MSEP_REC));
+ if (!p.empty()) {
+ presult.push_back(MSEP_FLD);
+ presult.append(MORPH_PART);
+ presult.append(st.c_str());
+ line_uniq_app(p, MSEP_REC);
+ presult.append(p);
}
- if (p)
- free(p);
checked_prefix = 1;
}
// else check forbiddenwords
} else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) ||
TESTAFF(rv->astr, needaffix, rv->alen))) {
st[i] = ch;
continue;
@@ -2502,17 +2363,17 @@ int AffixMgr::compound_check_morph(const
) &&
!((checkcompoundtriple && !words && // test triple letters
(word[i - 1] == word[i]) &&
(((i > 1) && (word[i - 1] == word[i - 2])) ||
((word[i - 1] == word[i + 1])) // may be word[i+1] == '\0'
)) ||
(
// test CHECKCOMPOUNDPATTERN
- numcheckcpd && !words &&
+ !checkcpdtable.empty() && !words &&
cpdpat_check(word, i, rv, NULL, affixed)) ||
(checkcompoundcase && !words && cpdcase_check(word, i))))
// LANG_hu section: spec. Hungarian rule
||
((!rv) && (langnum == LANG_hu) && hu_mov_rule &&
(rv = affix_check(st.c_str(), i)) &&
(sfx && sfx->getCont() &&
(TESTAFF(sfx->getCont(), (unsigned short)'x', sfx->getContLen()) ||
@@ -2536,41 +2397,39 @@ int AffixMgr::compound_check_morph(const
rv = lookup((word + i)); // perhaps without prefix
// search homonym with compound flag
while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) ||
!((compoundflag && !words &&
TESTAFF(rv->astr, compoundflag, rv->alen)) ||
(compoundend && !words &&
TESTAFF(rv->astr, compoundend, rv->alen)) ||
- (numdefcpd && words &&
+ (!defcpdtable.empty() && words &&
defcpd_check(&words, wnum + 1, rv, NULL, 1))))) {
rv = rv->next_homonym;
}
if (rv && words && words[wnum + 1]) {
- mystrcat(*result, presult, MAXLNLEN);
- mystrcat(*result, " ", MAXLNLEN);
- mystrcat(*result, MORPH_PART, MAXLNLEN);
- mystrcat(*result, word + i, MAXLNLEN);
+ result.append(presult);
+ result.append(" ");
+ result.append(MORPH_PART);
+ result.append(word + i);
if (complexprefixes && HENTRY_DATA(rv))
- mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(HENTRY_DATA2(rv));
if (!HENTRY_FIND(rv, MORPH_STEM)) {
- mystrcat(*result, " ", MAXLNLEN);
- mystrcat(*result, MORPH_STEM, MAXLNLEN);
- mystrcat(*result, HENTRY_WORD(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(MORPH_STEM);
+ result.append(HENTRY_WORD(rv));
}
// store the pointer of the hash entry
- // sprintf(*result + strlen(*result), " %s%p",
- // MORPH_HENTRY, rv);
if (!complexprefixes && HENTRY_DATA(rv)) {
- mystrcat(*result, " ", MAXLNLEN);
- mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(HENTRY_DATA2(rv));
}
- mystrcat(*result, "\n", MAXLNLEN);
+ result.append("\n");
return 0;
}
oldnumsyllable2 = numsyllable;
oldwordnum2 = wordnum;
// LANG_hu section: spec. Hungarian rule
if ((rv) && (langnum == LANG_hu) &&
@@ -2601,38 +2460,36 @@ int AffixMgr::compound_check_morph(const
((compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) ||
(compoundend && TESTAFF(rv->astr, compoundend, rv->alen))) &&
(((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
((cpdmaxsyllable != 0) &&
(numsyllable + get_syllable(std::string(HENTRY_WORD(rv), rv->blen)) <=
cpdmaxsyllable))) &&
((!checkcompounddup || (rv != rv_first)))) {
// bad compound word
- mystrcat(*result, presult, MAXLNLEN);
- mystrcat(*result, " ", MAXLNLEN);
- mystrcat(*result, MORPH_PART, MAXLNLEN);
- mystrcat(*result, word + i, MAXLNLEN);
+ result.append(presult);
+ result.append(" ");
+ result.append(MORPH_PART);
+ result.append(word + i);
if (HENTRY_DATA(rv)) {
if (complexprefixes)
- mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(HENTRY_DATA2(rv));
if (!HENTRY_FIND(rv, MORPH_STEM)) {
- mystrcat(*result, " ", MAXLNLEN);
- mystrcat(*result, MORPH_STEM, MAXLNLEN);
- mystrcat(*result, HENTRY_WORD(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(MORPH_STEM);
+ result.append(HENTRY_WORD(rv));
}
// store the pointer of the hash entry
- // sprintf(*result + strlen(*result), "
- // %s%p", MORPH_HENTRY, rv);
if (!complexprefixes) {
- mystrcat(*result, " ", MAXLNLEN);
- mystrcat(*result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(HENTRY_DATA2(rv));
}
}
- mystrcat(*result, "\n", MAXLNLEN);
+ result.append("\n");
ok = 1;
}
numsyllable = oldnumsyllable2;
wordnum = oldwordnum2;
// perhaps second word has prefix or/and suffix
sfx = NULL;
@@ -2644,37 +2501,34 @@ int AffixMgr::compound_check_morph(const
rv = NULL;
if (!rv && compoundend && !onlycpdrule) {
sfx = NULL;
pfx = NULL;
rv = affix_check((word + i), strlen(word + i), compoundend);
}
- if (!rv && numdefcpd && words) {
+ if (!rv && !defcpdtable.empty() && words) {
rv = affix_check((word + i), strlen(word + i), 0, IN_CPD_END);
if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) {
- char* m = NULL;
+ std::string m;
if (compoundflag)
m = affix_check_morph((word + i), strlen(word + i), compoundflag);
- if ((!m || *m == '\0') && compoundend) {
- if (m)
- free(m);
+ if (m.empty() && compoundend) {
m = affix_check_morph((word + i), strlen(word + i), compoundend);
}
- mystrcat(*result, presult, MAXLNLEN);
- if (m || (*m != '\0')) {
- char m2[MAXLNLEN];
- sprintf(m2, "%c%s%s%s", MSEP_FLD, MORPH_PART, word + i,
- line_uniq_app(&m, MSEP_REC));
- mystrcat(*result, m2, MAXLNLEN);
+ result.append(presult);
+ if (!m.empty()) {
+ result.push_back(MSEP_FLD);
+ result.append(MORPH_PART);
+ result.append(word + i);
+ line_uniq_app(m, MSEP_REC);
+ result.append(m);
}
- if (m)
- free(m);
- mystrcat(*result, "\n", MAXLNLEN);
+ result.append("\n");
ok = 1;
}
}
// check non_compound flag in suffix and prefix
if ((rv) &&
((pfx && pfx->getCont() &&
TESTAFF(pfx->getCont(), compoundforbidflag, pfx->getContLen())) ||
@@ -2708,17 +2562,17 @@ int AffixMgr::compound_check_morph(const
// + 1 word, if syllable number of the prefix > 1 (hungarian
// convention)
if (pfx && (get_syllable(pfx->getKey()) > 1))
wordnum++;
// increment syllable num, if last word has a SYLLABLENUM flag
// and the suffix is beginning `s'
- if (cpdsyllablenum) {
+ if (!cpdsyllablenum.empty()) {
switch (sfxflag) {
case 'c': {
numsyllable += 2;
break;
}
case 'J': {
numsyllable += 1;
break;
@@ -2740,94 +2594,73 @@ int AffixMgr::compound_check_morph(const
// second word is acceptable, as a word with prefix or/and suffix?
// hungarian conventions: compounding is acceptable,
// when compound forms consist 2 word, otherwise
// the syllable number of root words is 6, or lesser.
if ((rv) &&
(((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) ||
((cpdmaxsyllable != 0) && (numsyllable <= cpdmaxsyllable))) &&
((!checkcompounddup || (rv != rv_first)))) {
- char* m = NULL;
+ std::string m;
if (compoundflag)
m = affix_check_morph((word + i), strlen(word + i), compoundflag);
- if ((!m || *m == '\0') && compoundend) {
- if (m)
- free(m);
+ if (m.empty() && compoundend) {
m = affix_check_morph((word + i), strlen(word + i), compoundend);
}
- mystrcat(*result, presult, MAXLNLEN);
- if (m && (*m != '\0')) {
- char m2[MAXLNLEN];
- sprintf(m2, "%c%s%s%s", MSEP_FLD, MORPH_PART, word + i,
- line_uniq_app(&m, MSEP_REC));
- mystrcat(*result, m2, MAXLNLEN);
+ result.append(presult);
+ if (!m.empty()) {
+ result.push_back(MSEP_FLD);
+ result.append(MORPH_PART);
+ result.append(word + 1);
+ line_uniq_app(m, MSEP_REC);
+ result.append(m);
}
- if (m)
- free(m);
- if (strlen(*result) + 1 < MAXLNLEN)
- sprintf(*result + strlen(*result), "%c", MSEP_REC);
+ result.push_back(MSEP_REC);
ok = 1;
}
numsyllable = oldnumsyllable2;
wordnum = oldwordnum2;
// perhaps second word is a compound word (recursive call)
if ((wordnum < maxwordnum) && (ok == 0)) {
compound_check_morph((word + i), strlen(word + i), wordnum + 1,
numsyllable, maxwordnum, wnum + 1, words, rwords, 0,
- result, presult);
+ result, &presult);
} else {
rv = NULL;
}
}
st[i] = ch;
wordnum = oldwordnum;
numsyllable = oldnumsyllable;
- } while (numdefcpd && oldwordnum == 0 &&
+ } while (!defcpdtable.empty() && oldwordnum == 0 &&
onlycpdrule++ < 1); // end of onlycpd loop
}
return 0;
}
-// return 1 if s1 (reversed) is a leading subset of end of s2
-/* inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int
- len)
- {
- while ((len > 0) && *s1 && (*s1 == *end_of_s2)) {
- s1++;
- end_of_s2--;
- len--;
- }
- return (*s1 == '\0');
- }
- */
-
inline int AffixMgr::isRevSubset(const char* s1,
const char* end_of_s2,
int len) {
while ((len > 0) && (*s1 != '\0') && ((*s1 == *end_of_s2) || (*s1 == '.'))) {
s1++;
end_of_s2--;
len--;
}
return (*s1 == '\0');
}
// check word for suffixes
-
struct hentry* AffixMgr::suffix_check(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
- char** wlst,
- int maxSug,
- int* ns,
const FLAG cclass,
const FLAG needflag,
char in_compound) {
struct hentry* rv = NULL;
PfxEntry* ep = ppfx;
// first handle the special case of 0 length suffixes
SfxEntry* se = sStart[0];
@@ -2856,17 +2689,17 @@ struct hentry* AffixMgr::suffix_check(co
(TESTAFF(se->getCont(), onlyincompound, se->getContLen())))) &&
// needaffix on prefix or first suffix
(cclass ||
!(se->getCont() &&
TESTAFF(se->getCont(), needaffix, se->getContLen())) ||
(ppfx &&
!((ep->getCont()) &&
TESTAFF(ep->getCont(), needaffix, ep->getContLen()))))) {
- rv = se->checkword(word, len, sfxopts, ppfx, wlst, maxSug, ns,
+ rv = se->checkword(word, len, sfxopts, ppfx,
(FLAG)cclass, needflag,
(in_compound ? 0 : onlyincompound));
if (rv) {
sfx = se; // BUG: sfx not stateless
return rv;
}
}
}
@@ -2907,17 +2740,17 @@ struct hentry* AffixMgr::suffix_check(co
!(sptr->getCont() &&
TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) ||
(ppfx &&
!((ep->getCont()) &&
TESTAFF(ep->getCont(), needaffix, ep->getContLen())))))
if (in_compound != IN_CPD_END || ppfx ||
!(sptr->getCont() &&
TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))) {
- rv = sptr->checkword(word, len, sfxopts, ppfx, wlst, maxSug, ns,
+ rv = sptr->checkword(word, len, sfxopts, ppfx,
cclass, needflag,
(in_compound ? 0 : onlyincompound));
if (rv) {
sfx = sptr; // BUG: sfx not stateless
sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
if (!sptr->getCont())
sfxappnd = sptr->getKey(); // BUG: sfxappnd not stateless
// LANG_hu section: spec. Hungarian rule
@@ -2980,69 +2813,65 @@ struct hentry* AffixMgr::suffix_check_tw
} else {
sptr = sptr->getNextNE();
}
}
return NULL;
}
-char* AffixMgr::suffix_check_twosfx_morph(const char* word,
- int len,
- int sfxopts,
- PfxEntry* ppfx,
- const FLAG needflag) {
+std::string AffixMgr::suffix_check_twosfx_morph(const char* word,
+ int len,
+ int sfxopts,
+ PfxEntry* ppfx,
+ const FLAG needflag) {
std::string result;
std::string result2;
std::string result3;
- char* st;
-
// first handle the special case of 0 length suffixes
SfxEntry* se = sStart[0];
while (se) {
if (contclasses[se->getFlag()]) {
- st = se->check_twosfx_morph(word, len, sfxopts, ppfx, needflag);
- if (st) {
+ std::string st = se->check_twosfx_morph(word, len, sfxopts, ppfx, needflag);
+ if (!st.empty()) {
if (ppfx) {
if (ppfx->getMorph()) {
result.append(ppfx->getMorph());
result.append(" ");
} else
debugflag(result, ppfx->getFlag());
}
result.append(st);
- free(st);
if (se->getMorph()) {
result.append(" ");
result.append(se->getMorph());
} else
debugflag(result, se->getFlag());
result.append("\n");
}
}
se = se->getNext();
}
// now handle the general case
if (len == 0)
- return NULL; // FULLSTRIP
+ return std::string(); // FULLSTRIP
unsigned char sp = *((const unsigned char*)(word + len - 1));
SfxEntry* sptr = sStart[sp];
while (sptr) {
if (isRevSubset(sptr->getKey(), word + len - 1, len)) {
if (contclasses[sptr->getFlag()]) {
- st = sptr->check_twosfx_morph(word, len, sfxopts, ppfx, needflag);
- if (st) {
+ std::string st = sptr->check_twosfx_morph(word, len, sfxopts, ppfx, needflag);
+ if (!st.empty()) {
sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless
if (!sptr->getCont())
sfxappnd = sptr->getKey(); // BUG: sfxappnd not stateless
result2.assign(st);
- free(st);
result3.clear();
if (sptr->getMorph()) {
result3.append(" ");
result3.append(sptr->getMorph());
} else
debugflag(result3, sptr->getFlag());
@@ -3052,35 +2881,30 @@ char* AffixMgr::suffix_check_twosfx_morp
}
}
sptr = sptr->getNextEQ();
} else {
sptr = sptr->getNextNE();
}
}
- if (!result.empty())
- return mystrdup(result.c_str());
-
- return NULL;
+ return result;
}
-char* AffixMgr::suffix_check_morph(const char* word,
- int len,
- int sfxopts,
- PfxEntry* ppfx,
- const FLAG cclass,
- const FLAG needflag,
- char in_compound) {
- char result[MAXLNLEN];
+std::string AffixMgr::suffix_check_morph(const char* word,
+ int len,
+ int sfxopts,
+ PfxEntry* ppfx,
+ const FLAG cclass,
+ const FLAG needflag,
+ char in_compound) {
+ std::string result;
struct hentry* rv = NULL;
- result[0] = '\0';
-
PfxEntry* ep = ppfx;
// first handle the special case of 0 length suffixes
SfxEntry* se = sStart[0];
while (se) {
if (!cclass || se->getCont()) {
// suffixes are not allowed in beginning of compounds
if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass
@@ -3104,56 +2928,53 @@ char* AffixMgr::suffix_check_morph(const
(TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) &&
// needaffix on prefix or first suffix
(cclass ||
!(se->getCont() &&
TESTAFF(se->getCont(), needaffix, se->getContLen())) ||
(ppfx &&
!((ep->getCont()) &&
TESTAFF(ep->getCont(), needaffix, ep->getContLen()))))))
- rv = se->checkword(word, len, sfxopts, ppfx, NULL, 0, 0, cclass,
- needflag);
+ rv = se->checkword(word, len, sfxopts, ppfx, cclass,
+ needflag, FLAG_NULL);
while (rv) {
if (ppfx) {
if (ppfx->getMorph()) {
- mystrcat(result, ppfx->getMorph(), MAXLNLEN);
- mystrcat(result, " ", MAXLNLEN);
+ result.append(ppfx->getMorph());
+ result.append(" ");
} else
debugflag(result, ppfx->getFlag());
}
if (complexprefixes && HENTRY_DATA(rv))
- mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(HENTRY_DATA2(rv));
if (!HENTRY_FIND(rv, MORPH_STEM)) {
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, MORPH_STEM, MAXLNLEN);
- mystrcat(result, HENTRY_WORD(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(MORPH_STEM);
+ result.append(HENTRY_WORD(rv));
}
- // store the pointer of the hash entry
- // sprintf(result + strlen(result), " %s%p", MORPH_HENTRY,
- // rv);
if (!complexprefixes && HENTRY_DATA(rv)) {
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(HENTRY_DATA2(rv));
}
if (se->getMorph()) {
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, se->getMorph(), MAXLNLEN);
+ result.append(" ");
+ result.append(se->getMorph());
} else
debugflag(result, se->getFlag());
- mystrcat(result, "\n", MAXLNLEN);
+ result.append("\n");
rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
}
}
se = se->getNext();
}
// now handle the general case
if (len == 0)
- return NULL; // FULLSTRIP
+ return std::string(); // FULLSTRIP
unsigned char sp = *((const unsigned char*)(word + len - 1));
SfxEntry* sptr = sStart[sp];
while (sptr) {
if (isRevSubset(sptr->getKey(), word + len - 1, len)) {
// suffixes are not allowed in beginning of compounds
if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass
// except when signed with compoundpermitflag flag
@@ -3174,76 +2995,70 @@ char* AffixMgr::suffix_check_morph(const
// fogemorpheme
(in_compound ||
!((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound,
sptr->getContLen()))))) &&
// needaffix on first suffix
(cclass ||
!(sptr->getCont() &&
TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())))))
- rv = sptr->checkword(word, len, sfxopts, ppfx, NULL, 0, 0, cclass,
- needflag);
+ rv = sptr->checkword(word, len, sfxopts, ppfx, cclass,
+ needflag, FLAG_NULL);
while (rv) {
if (ppfx) {
if (ppfx->getMorph()) {
- mystrcat(result, ppfx->getMorph(), MAXLNLEN);
- mystrcat(result, " ", MAXLNLEN);
+ result.append(ppfx->getMorph());
+ result.append(" ");
} else
debugflag(result, ppfx->getFlag());
}
if (complexprefixes && HENTRY_DATA(rv))
- mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(HENTRY_DATA2(rv));
if (!HENTRY_FIND(rv, MORPH_STEM)) {
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, MORPH_STEM, MAXLNLEN);
- mystrcat(result, HENTRY_WORD(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(MORPH_STEM);
+ result.append(HENTRY_WORD(rv));
}
- // store the pointer of the hash entry
- // sprintf(result + strlen(result), " %s%p",
- // MORPH_HENTRY, rv);
if (!complexprefixes && HENTRY_DATA(rv)) {
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, HENTRY_DATA2(rv), MAXLNLEN);
+ result.append(" ");
+ result.append(HENTRY_DATA2(rv));
}
if (sptr->getMorph()) {
- mystrcat(result, " ", MAXLNLEN);
- mystrcat(result, sptr->getMorph(), MAXLNLEN);
+ result.append(" ");
+ result.append(sptr->getMorph());
} else
debugflag(result, sptr->getFlag());
- mystrcat(result, "\n", MAXLNLEN);
+ result.append("\n");
rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag);
}
sptr = sptr->getNextEQ();
} else {
sptr = sptr->getNextNE();
}
}
- if (*result)
- return mystrdup(result);
- return NULL;
+ return result;
}
// check if word with affixes is correctly spelled
struct hentry* AffixMgr::affix_check(const char* word,
int len,
const FLAG needflag,
char in_compound) {
struct hentry* rv = NULL;
// check all prefixes (also crossed with suffixes if allowed)
rv = prefix_check(word, len, in_compound, needflag);
if (rv)
return rv;
// if still not found check all suffixes
- rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag,
- in_compound);
+ rv = suffix_check(word, len, 0, NULL, FLAG_NULL, needflag, in_compound);
if (havecontclass) {
sfx = NULL;
pfx = NULL;
if (rv)
return rv;
// if still not found check all two-level suffixes
@@ -3254,77 +3069,153 @@ struct hentry* AffixMgr::affix_check(con
// if still not found check all two-level suffixes
rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag);
}
return rv;
}
// check if word with affixes is correctly spelled
-char* AffixMgr::affix_check_morph(const char* word,
+std::string AffixMgr::affix_check_morph(const char* word,
int len,
const FLAG needflag,
char in_compound) {
- char result[MAXLNLEN];
- char* st = NULL;
-
- *result = '\0';
+ std::string result;
// check all prefixes (also crossed with suffixes if allowed)
- st = prefix_check_morph(word, len, in_compound);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ std::string st = prefix_check_morph(word, len, in_compound);
+ if (!st.empty()) {
+ result.append(st);
}
// if still not found check all suffixes
st = suffix_check_morph(word, len, 0, NULL, '\0', needflag, in_compound);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ if (!st.empty()) {
+ result.append(st);
}
if (havecontclass) {
sfx = NULL;
pfx = NULL;
// if still not found check all two-level suffixes
st = suffix_check_twosfx_morph(word, len, 0, NULL, needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ if (!st.empty()) {
+ result.append(st);
}
// if still not found check all two-level suffixes
st = prefix_check_twosfx_morph(word, len, IN_CPD_NOT, needflag);
- if (st) {
- mystrcat(result, st, MAXLNLEN);
- free(st);
+ if (!st.empty()) {
+ result.append(st);
}
}
- return mystrdup(result);
+ return result;
}
-char* AffixMgr::morphgen(const char* ts,
- int wl,
- const unsigned short* ap,
- unsigned short al,
- const char* morph,
- const char* targetmorph,
+// morphcmp(): compare MORPH_DERI_SFX, MORPH_INFL_SFX and MORPH_TERM_SFX fields
+// in the first line of the inputs
+// return 0, if inputs equal
+// return 1, if inputs may equal with a secondary suffix
+// otherwise return -1
+static int morphcmp(const char* s, const char* t) {
+ int se = 0;
+ int te = 0;
+ const char* sl;
+ const char* tl;
+ const char* olds;
+ const char* oldt;
+ if (!s || !t)
+ return 1;
+ olds = s;
+ sl = strchr(s, '\n');
+ s = strstr(s, MORPH_DERI_SFX);
+ if (!s || (sl && sl < s))
+ s = strstr(olds, MORPH_INFL_SFX);
+ if (!s || (sl && sl < s)) {
+ s = strstr(olds, MORPH_TERM_SFX);
+ olds = NULL;
+ }
+ oldt = t;
+ tl = strchr(t, '\n');
+ t = strstr(t, MORPH_DERI_SFX);
+ if (!t || (tl && tl < t))
+ t = strstr(oldt, MORPH_INFL_SFX);
+ if (!t || (tl && tl < t)) {
+ t = strstr(oldt, MORPH_TERM_SFX);
+ oldt = NULL;
+ }
+ while (s && t && (!sl || sl > s) && (!tl || tl > t)) {
+ s += MORPH_TAG_LEN;
+ t += MORPH_TAG_LEN;
+ se = 0;
+ te = 0;
+ while ((*s == *t) && !se && !te) {
+ s++;
+ t++;
+ switch (*s) {
+ case ' ':
+ case '\n':
+ case '\t':
+ case '\0':
+ se = 1;
+ }
+ switch (*t) {
+ case ' ':
+ case '\n':
+ case '\t':
+ case '\0':
+ te = 1;
+ }
+ }
+ if (!se || !te) {
+ // not terminal suffix difference
+ if (olds)
+ return -1;
+ return 1;
+ }
+ olds = s;
+ s = strstr(s, MORPH_DERI_SFX);
+ if (!s || (sl && sl < s))
+ s = strstr(olds, MORPH_INFL_SFX);
+ if (!s || (sl && sl < s)) {
+ s = strstr(olds, MORPH_TERM_SFX);
+ olds = NULL;
+ }
+ oldt = t;
+ t = strstr(t, MORPH_DERI_SFX);
+ if (!t || (tl && tl < t))
+ t = strstr(oldt, MORPH_INFL_SFX);
+ if (!t || (tl && tl < t)) {
+ t = strstr(oldt, MORPH_TERM_SFX);
+ oldt = NULL;
+ }
+ }
+ if (!s && !t && se && te)
+ return 0;
+ return 1;
+}
+
+std::string AffixMgr::morphgen(const char* ts,
+ int wl,
+ const unsigned short* ap,
+ unsigned short al,
+ const char* morph,
+ const char* targetmorph,
int level) {
// handle suffixes
if (!morph)
- return NULL;
+ return std::string();
// check substandard flag
if (TESTAFF(ap, substandard, al))
- return NULL;
+ return std::string();
if (morphcmp(morph, targetmorph) == 0)
- return mystrdup(ts);
+ return ts;
size_t stemmorphcatpos;
std::string mymorph;
// use input suffix fields, if exist
if (strstr(morph, MORPH_INFL_SFX) || strstr(morph, MORPH_DERI_SFX)) {
mymorph.assign(morph);
mymorph.append(" ");
@@ -3347,51 +3238,46 @@ char* AffixMgr::morphgen(const char* ts,
stemmorph = mymorph.c_str();
} else {
stemmorph = sptr->getMorph();
}
int cmp = morphcmp(stemmorph, targetmorph);
if (cmp == 0) {
- char* newword = sptr->add(ts, wl);
- if (newword) {
- hentry* check = pHMgr->lookup(newword); // XXX extra dic
+ std::string newword = sptr->add(ts, wl);
+ if (!newword.empty()) {
+ hentry* check = pHMgr->lookup(newword.c_str()); // XXX extra dic
if (!check || !check->astr ||
!(TESTAFF(check->astr, forbiddenword, check->alen) ||
TESTAFF(check->astr, ONLYUPCASEFLAG, check->alen))) {
return newword;
}
- free(newword);
}
}
// recursive call for secondary suffixes
if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) &&
- // (get_sfxcount(stemmorph) < targetcount) &&
!TESTAFF(sptr->getCont(), substandard, sptr->getContLen())) {
- char* newword = sptr->add(ts, wl);
- if (newword) {
- char* newword2 =
- morphgen(newword, strlen(newword), sptr->getCont(),
+ std::string newword = sptr->add(ts, wl);
+ if (!newword.empty()) {
+ std::string newword2 =
+ morphgen(newword.c_str(), newword.size(), sptr->getCont(),
sptr->getContLen(), stemmorph, targetmorph, 1);
- if (newword2) {
- free(newword);
+ if (!newword2.empty()) {
return newword2;
}
- free(newword);
- newword = NULL;
}
}
}
sptr = sptr->getFlgNxt();
}
}
- return NULL;
+ return std::string();
}
int AffixMgr::expand_rootword(struct guessword* wlst,
int maxn,
const char* ts,
int wl,
const unsigned short* ap,
unsigned short al,
@@ -3434,40 +3320,38 @@ int AffixMgr::expand_rootword(struct gue
// check needaffix flag
!(sptr->getCont() &&
((needaffix &&
TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) ||
(circumfix &&
TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) ||
(onlyincompound &&
TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) {
- char* newword = sptr->add(ts, wl);
- if (newword) {
+ std::string newword = sptr->add(ts, wl);
+ if (!newword.empty()) {
if (nh < maxn) {
- wlst[nh].word = newword;
+ wlst[nh].word = mystrdup(newword.c_str());
wlst[nh].allow = sptr->allowCross();
wlst[nh].orig = NULL;
nh++;
// add special phonetic version
if (phon && (nh < maxn)) {
std::string prefix(phon);
std::string key(sptr->getKey());
reverseword(key);
prefix.append(key);
wlst[nh].word = mystrdup(prefix.c_str());
if (!wlst[nh].word)
return nh - 1;
wlst[nh].allow = (1 == 0);
- wlst[nh].orig = mystrdup(newword);
+ wlst[nh].orig = mystrdup(newword.c_str());
if (!wlst[nh].orig)
return nh - 1;
nh++;
}
- } else {
- free(newword);
}
}
}
sptr = sptr->getFlgNxt();
}
}
int n = nh;
@@ -3479,25 +3363,23 @@ int AffixMgr::expand_rootword(struct gue
const unsigned char c = (unsigned char)(ap[k] & 0x00FF);
PfxEntry* cptr = pFlag[c];
while (cptr) {
if ((cptr->getFlag() == ap[k]) && cptr->allowCross() &&
(!cptr->getKeyLen() ||
((badl > cptr->getKeyLen()) &&
(strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) {
int l1 = strlen(wlst[j].word);
- char* newword = cptr->add(wlst[j].word, l1);
- if (newword) {
+ std::string newword = cptr->add(wlst[j].word, l1);
+ if (!newword.empty()) {
if (nh < maxn) {
- wlst[nh].word = newword;
+ wlst[nh].word = mystrdup(newword.c_str());
wlst[nh].allow = cptr->allowCross();
wlst[nh].orig = NULL;
nh++;
- } else {
- free(newword);
}
}
}
cptr = cptr->getFlgNxt();
}
}
}
@@ -3513,44 +3395,35 @@ int AffixMgr::expand_rootword(struct gue
// check needaffix flag
!(ptr->getCont() &&
((needaffix &&
TESTAFF(ptr->getCont(), needaffix, ptr->getContLen())) ||
(circumfix &&
TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) ||
(onlyincompound &&
TESTAFF(ptr->getCont(), onlyincompound, ptr->getContLen()))))) {
- char* newword = ptr->add(ts, wl);
- if (newword) {
+ std::string newword = ptr->add(ts, wl);
+ if (!newword.empty()) {
if (nh < maxn) {
- wlst[nh].word = newword;
+ wlst[nh].word = mystrdup(newword.c_str());
wlst[nh].allow = ptr->allowCross();
wlst[nh].orig = NULL;
nh++;
- } else {
- free(newword);
}
}
}
ptr = ptr->getFlgNxt();
}
}
return nh;
}
-// return length of replacing table
-int AffixMgr::get_numrep() const {
- return numrep;
-}
-
// return replacing table
-struct replentry* AffixMgr::get_reptable() const {
- if (!reptable)
- return NULL;
+const std::vector<replentry>& AffixMgr::get_reptable() const {
return reptable;
}
// return iconv table
RepList* AffixMgr::get_iconvtable() const {
if (!iconvtable)
return NULL;
return iconvtable;
@@ -3565,45 +3438,31 @@ RepList* AffixMgr::get_oconvtable() cons
// return replacing table
struct phonetable* AffixMgr::get_phonetable() const {
if (!phone)
return NULL;
return phone;
}
-// return length of character map table
-int AffixMgr::get_nummap() const {
- return nummap;
+// return character map table
+const std::vector<mapentry>& AffixMgr::get_maptable() const {
+ return maptable;
}
// return character map table
-struct mapentry* AffixMgr::get_maptable() const {
- if (!maptable)
- return NULL;
- return maptable;
-}
-
-// return length of word break table
-int AffixMgr::get_numbreak() const {
- return numbreak;
-}
-
-// return character map table
-char** AffixMgr::get_breaktable() const {
- if (!breaktable)
- return NULL;
+const std::vector<std::string>& AffixMgr::get_breaktable() const {
return breaktable;
}
// return text encoding of dictionary
-char* AffixMgr::get_encoding() {
- if (!encoding)
- encoding = mystrdup(SPELL_ENCODING);
- return mystrdup(encoding);
+const std::string& AffixMgr::get_encoding() {
+ if (encoding.empty())
+ encoding = SPELL_ENCODING;
+ return encoding;
}
// return text encoding of dictionary
int AffixMgr::get_langnum() const {
return langnum;
}
// return double prefix option
@@ -3636,53 +3495,53 @@ int AffixMgr::get_checksharps() const {
return checksharps;
}
char* AffixMgr::encode_flag(unsigned short aflag) const {
return pHMgr->encode_flag(aflag);
}
// return the preferred ignore string for suggestions
-char* AffixMgr::get_ignore() const {
- if (!ignorechars)
+const char* AffixMgr::get_ignore() const {
+ if (ignorechars.empty())
return NULL;
- return ignorechars;
+ return ignorechars.c_str();
}
// return the preferred ignore string for suggestions
const std::vector<w_char>& AffixMgr::get_ignore_utf16() const {
return ignorechars_utf16;
}
// return the keyboard string for suggestions
char* AffixMgr::get_key_string() {
- if (!keystring)
- keystring = mystrdup(SPELL_KEYSTRING);
- return mystrdup(keystring);
+ if (keystring.empty())
+ keystring = SPELL_KEYSTRING;
+ return mystrdup(keystring.c_str());
}
// return the preferred try string for suggestions
char* AffixMgr::get_try_string() const {
- if (!trystring)
+ if (trystring.empty())
return NULL;
- return mystrdup(trystring);
+ return mystrdup(trystring.c_str());
}
// return the preferred try string for suggestions
-const char* AffixMgr::get_wordchars() const {
+const std::string& AffixMgr::get_wordchars() const {
return wordchars;
}
const std::vector<w_char>& AffixMgr::get_wordchars_utf16() const {
return wordchars_utf16;
}
// is there compounding?
int AffixMgr::get_compound() const {
- return compoundflag || compoundbegin || numdefcpd;
+ return compoundflag || compoundbegin || !defcpdtable.empty();
}
// return the compound words control flag
FLAG AffixMgr::get_compoundflag() const {
return compoundflag;
}
// return the forbidden words control flag
@@ -3705,59 +3564,26 @@ FLAG AffixMgr::get_needaffix() const {
return needaffix;
}
// return the onlyincompound flag
FLAG AffixMgr::get_onlyincompound() const {
return onlyincompound;
}
-// return the compound word signal flag
-FLAG AffixMgr::get_compoundroot() const {
- return compoundroot;
-}
-
-// return the compound begin signal flag
-FLAG AffixMgr::get_compoundbegin() const {
- return compoundbegin;
-}
-
-// return the value of checknum
-int AffixMgr::get_checknum() const {
- return checknum;
-}
-
-// return the value of prefix
-const char* AffixMgr::get_prefix() const {
- if (pfx)
- return pfx->getKey();
- return NULL;
-}
-
// return the value of suffix
-const char* AffixMgr::get_suffix() const {
- return sfxappnd;
-}
-
-// return the value of suffix
-const char* AffixMgr::get_version() const {
+const std::string& AffixMgr::get_version() const {
return version;
}
-// return lemma_present flag
-FLAG AffixMgr::get_lemma_present() const {
- return lemma_present;
-}
-
// utility method to look up root words in hash table
struct hentry* AffixMgr::lookup(const char* word) {
- int i;
struct hentry* he = NULL;
- for (i = 0; i < *maxdic && !he; i++) {
- he = (alldic[i])->lookup(word);
+ for (size_t i = 0; i < alldic.size() && !he; ++i) {
+ he = alldic[i]->lookup(word);
}
return he;
}
// return the value of suffix
int AffixMgr::have_contclass() const {
return havecontclass;
}
@@ -3789,849 +3615,761 @@ int AffixMgr::get_nosplitsugs(void) cons
}
// return sugswithdots
int AffixMgr::get_sugswithdots(void) const {
return sugswithdots;
}
/* parse flag */
-int AffixMgr::parse_flag(char* line, unsigned short* out, FileMgr* af) {
- char* s = NULL;
+bool AffixMgr::parse_flag(const std::string& line, unsigned short* out, FileMgr* af) {
if (*out != FLAG_NULL && !(*out >= DEFAULTFLAGS)) {
HUNSPELL_WARNING(
stderr,
"error: line %d: multiple definitions of an affix file parameter\n",
af->getlinenum());
- return 1;
+ return false;
}
- if (parse_string(line, &s, af->getlinenum()))
- return 1;
- *out = pHMgr->decode_flag(s);
- free(s);
- return 0;
+ std::string s;
+ if (!parse_string(line, s, af->getlinenum()))
+ return false;
+ *out = pHMgr->decode_flag(s.c_str());
+ return true;
}
/* parse num */
-int AffixMgr::parse_num(char* line, int* out, FileMgr* af) {
- char* s = NULL;
+bool AffixMgr::parse_num(const std::string& line, int* out, FileMgr* af) {
if (*out != -1) {
HUNSPELL_WARNING(
stderr,
"error: line %d: multiple definitions of an affix file parameter\n",
af->getlinenum());
- return 1;
+ return false;
}
- if (parse_string(line, &s, af->getlinenum()))
- return 1;
- *out = atoi(s);
- free(s);
- return 0;
+ std::string s;
+ if (!parse_string(line, s, af->getlinenum()))
+ return false;
+ *out = atoi(s.c_str());
+ return true;
}
/* parse in the max syllablecount of compound words and */
-int AffixMgr::parse_cpdsyllable(char* line, FileMgr* af) {
- char* tp = line;
- char* piece;
+bool AffixMgr::parse_cpdsyllable(const std::string& line, FileMgr* af) {
int i = 0;
int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- np++;
- break;
- }
- case 1: {
- cpdmaxsyllable = atoi(piece);
- np++;
- break;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ cpdmaxsyllable = atoi(std::string(start_piece, iter).c_str());
+ np++;
+ break;
+ }
+ case 2: {
+ if (!utf8) {
+ cpdvowels.assign(start_piece, iter);
+ std::sort(cpdvowels.begin(), cpdvowels.end());
+ } else {
+ std::string piece(start_piece, iter);
+ u8_u16(cpdvowels_utf16, piece);
+ std::sort(cpdvowels_utf16.begin(), cpdvowels_utf16.end());
}
- case 2: {
- if (!utf8) {
- cpdvowels = mystrdup(piece);
- } else {
- std::vector<w_char> w;
- u8_u16(w, piece);
- if (!w.empty()) {
- std::sort(w.begin(), w.end());
- cpdvowels_utf16 = (w_char*)malloc(w.size() * sizeof(w_char));
- if (!cpdvowels_utf16)
- return 1;
- memcpy(cpdvowels_utf16, &w[0], w.size());
- }
- cpdvowels_utf16_len = w.size();
- }
- np++;
- break;
- }
- default:
- break;
+ np++;
+ break;
}
- i++;
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np < 2) {
HUNSPELL_WARNING(stderr,
"error: line %d: missing compoundsyllable information\n",
af->getlinenum());
- return 1;
+ return false;
}
if (np == 2)
- cpdvowels = mystrdup("aeiouAEIOU");
- return 0;
+ cpdvowels = "AEIOUaeiou";
+ return true;
}
/* parse in the typical fault correcting table */
-int AffixMgr::parse_reptable(char* line, FileMgr* af) {
- if (numrep != 0) {
+bool AffixMgr::parse_reptable(const std::string& line, FileMgr* af) {
+ if (parsedrep) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
af->getlinenum());
- return 1;
+ return false;
}
- char* tp = line;
- char* piece;
+ parsedrep = true;
+ int numrep = -1;
int i = 0;
int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numrep = atoi(std::string(start_piece, iter).c_str());
+ if (numrep < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n",
+ af->getlinenum());
+ return false;
+ }
+ reptable.reserve(numrep);
+ np++;
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ start_piece = mystrsep(line, iter);
+ }
+ if (np != 2) {
+ HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
+ af->getlinenum());
+ return false;
+ }
+
+ /* now parse the numrep lines to read in the remainder of the table */
+ for (int j = 0; j < numrep; ++j) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
+ mychomp(nl);
+ reptable.push_back(replentry());
+ iter = nl.begin();
+ i = 0;
+ int type = 0;
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
switch (i) {
case 0: {
- np++;
+ if (nl.compare(start_piece - nl.begin(), 3, "REP", 3) != 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ reptable.clear();
+ return false;
+ }
break;
}
case 1: {
- numrep = atoi(piece);
- if (numrep < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n",
- af->getlinenum());
- return 1;
+ if (*start_piece == '^')
+ type = 1;
+ reptable.back().pattern.assign(start_piece + type, iter);
+ mystrrep(reptable.back().pattern, "_", " ");
+ if (!reptable.back().pattern.empty() && reptable.back().pattern[reptable.back().pattern.size() - 1] == '$') {
+ type += 2;
+ reptable.back().pattern.resize(reptable.back().pattern.size() - 1);
}
- reptable = (replentry*)malloc(numrep * sizeof(struct replentry));
- if (!reptable)
- return 1;
- np++;
+ break;
+ }
+ case 2: {
+ reptable.back().outstrings[type].assign(start_piece, iter);
+ mystrrep(reptable.back().outstrings[type], "_", " ");
break;
}
default:
break;
}
- i++;
+ ++i;
+ start_piece = mystrsep(nl, iter);
+ }
+ if (reptable.back().pattern.empty() || reptable.back().outstrings[type].empty()) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ reptable.clear();
+ return false;
}
- piece = mystrsep(&tp, 0);
+ }
+ return true;
+}
+
+/* parse in the typical fault correcting table */
+bool AffixMgr::parse_convtable(const std::string& line,
+ FileMgr* af,
+ RepList** rl,
+ const std::string& keyword) {
+ if (*rl) {
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
+ af->getlinenum());
+ return false;
+ }
+ int i = 0;
+ int np = 0;
+ int numrl = 0;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numrl = atoi(std::string(start_piece, iter).c_str());
+ if (numrl < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n",
+ af->getlinenum());
+ return false;
+ }
+ *rl = new RepList(numrl);
+ if (!*rl)
+ return false;
+ np++;
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
- /* now parse the numrep lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < numrep; j++) {
- if ((nl = af->getline()) == NULL)
- return 1;
+ /* now parse the num lines to read in the remainder of the table */
+ for (int j = 0; j < numrl; j++) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
i = 0;
- reptable[j].pattern = NULL;
- reptable[j].pattern2 = NULL;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ std::string pattern;
+ std::string pattern2;
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
+ {
switch (i) {
case 0: {
- if (strncmp(piece, "REP", 3) != 0) {
+ if (nl.compare(start_piece - nl.begin(), keyword.size(), keyword, 0, keyword.size()) != 0) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- numrep = 0;
- return 1;
+ delete *rl;
+ *rl = NULL;
+ return false;
}
break;
}
case 1: {
- if (*piece == '^')
- reptable[j].start = true;
- else
- reptable[j].start = false;
- reptable[j].pattern =
- mystrrep(mystrdup(piece + int(reptable[j].start)), "_", " ");
- int lr = strlen(reptable[j].pattern) - 1;
- if (reptable[j].pattern[lr] == '$') {
- reptable[j].end = true;
- reptable[j].pattern[lr] = '\0';
- } else
- reptable[j].end = false;
+ pattern.assign(start_piece, iter);
break;
}
case 2: {
- reptable[j].pattern2 = mystrrep(mystrdup(piece), "_", " ");
+ pattern2.assign(start_piece, iter);
break;
}
default:
break;
}
- i++;
+ ++i;
}
- piece = mystrsep(&tp, 0);
+ start_piece = mystrsep(nl, iter);
}
- if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) {
+ if (pattern.empty() || pattern2.empty()) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- numrep = 0;
- return 1;
+ return false;
}
+ (*rl)->add(pattern, pattern2);
}
- return 0;
+ return true;
}
/* parse in the typical fault correcting table */
-int AffixMgr::parse_convtable(char* line,
- FileMgr* af,
- RepList** rl,
- const char* keyword) {
- if (*rl) {
+bool AffixMgr::parse_phonetable(const std::string& line, FileMgr* af) {
+ if (phone) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
af->getlinenum());
- return 1;
+ return false;
}
- char* tp = line;
- char* piece;
+ int num = -1;
int i = 0;
int np = 0;
- int numrl = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- np++;
- break;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ num = atoi(std::string(start_piece, iter).c_str());
+ if (num < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
}
- case 1: {
- numrl = atoi(piece);
- if (numrl < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: incorrect entry number\n",
- af->getlinenum());
- return 1;
- }
- *rl = new RepList(numrl);
- if (!*rl)
- return 1;
- np++;
- break;
- }
- default:
- break;
+ phone = new phonetable;
+ phone->utf8 = (char)utf8;
+ np++;
+ break;
}
- i++;
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
- /* now parse the num lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < numrl; j++) {
- if (!(nl = af->getline()))
- return 1;
+ /* now parse the phone->num lines to read in the remainder of the table */
+ for (int j = 0; j < num; ++j) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
i = 0;
- char* pattern = NULL;
- char* pattern2 = NULL;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ const size_t old_size = phone->rules.size();
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
+ {
switch (i) {
case 0: {
- if (strncmp(piece, keyword, strlen(keyword)) != 0) {
+ if (nl.compare(start_piece - nl.begin(), 5, "PHONE", 5) != 0) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- delete *rl;
- *rl = NULL;
- return 1;
+ return false;
}
break;
}
case 1: {
- pattern = mystrrep(mystrdup(piece), "_", " ");
+ phone->rules.push_back(std::string(start_piece, iter));
break;
}
case 2: {
- pattern2 = mystrrep(mystrdup(piece), "_", " ");
+ phone->rules.push_back(std::string(start_piece, iter));
+ mystrrep(phone->rules.back(), "_", "");
break;
}
default:
break;
}
- i++;
+ ++i;
}
- piece = mystrsep(&tp, 0);
+ start_piece = mystrsep(nl, iter);
}
- if (!pattern || !pattern2) {
- if (pattern)
- free(pattern);
- if (pattern2)
- free(pattern2);
+ if (phone->rules.size() != old_size + 2) {
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- return 1;
+ phone->rules.clear();
+ return false;
}
- (*rl)->add(pattern, pattern2);
}
- return 0;
+ phone->rules.push_back("");
+ phone->rules.push_back("");
+ init_phonet_hash(*phone);
+ return true;
}
-/* parse in the typical fault correcting table */
-int AffixMgr::parse_phonetable(char* line, FileMgr* af) {
- if (phone) {
+/* parse in the checkcompoundpattern table */
+bool AffixMgr::parse_checkcpdtable(const std::string& line, FileMgr* af) {
+ if (parsedcheckcpd) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
af->getlinenum());
- return 1;
+ return false;
}
- char* tp = line;
- char* piece;
+ parsedcheckcpd = true;
+ int numcheckcpd = -1;
int i = 0;
int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numcheckcpd = atoi(std::string(start_piece, iter).c_str());
+ if (numcheckcpd < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
+ }
+ checkcpdtable.reserve(numcheckcpd);
+ np++;
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ start_piece = mystrsep(line, iter);
+ }
+ if (np != 2) {
+ HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
+ af->getlinenum());
+ return false;
+ }
+
+ /* now parse the numcheckcpd lines to read in the remainder of the table */
+ for (int j = 0; j < numcheckcpd; ++j) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
+ mychomp(nl);
+ i = 0;
+ checkcpdtable.push_back(patentry());
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
switch (i) {
case 0: {
- np++;
+ if (nl.compare(start_piece - nl.begin(), 20, "CHECKCOMPOUNDPATTERN", 20) != 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ return false;
+ }
break;
}
case 1: {
- phone = (phonetable*)malloc(sizeof(struct phonetable));
- if (!phone)
- return 1;
- phone->num = atoi(piece);
- phone->rules = NULL;
- phone->utf8 = (char)utf8;
- if (phone->num < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- return 1;
+ checkcpdtable.back().pattern.assign(start_piece, iter);
+ size_t slash_pos = checkcpdtable.back().pattern.find('/');
+ if (slash_pos != std::string::npos) {
+ std::string chunk(checkcpdtable.back().pattern, slash_pos + 1);
+ checkcpdtable.back().pattern.resize(slash_pos);
+ checkcpdtable.back().cond = pHMgr->decode_flag(chunk.c_str());
}
- phone->rules = (char**)malloc(2 * (phone->num + 1) * sizeof(char*));
- if (!phone->rules) {
- free(phone);
- phone = NULL;
- return 1;
+ break;
+ }
+ case 2: {
+ checkcpdtable.back().pattern2.assign(start_piece, iter);
+ size_t slash_pos = checkcpdtable.back().pattern2.find('/');
+ if (slash_pos != std::string::npos) {
+ std::string chunk(checkcpdtable.back().pattern2, slash_pos + 1);
+ checkcpdtable.back().pattern2.resize(slash_pos);
+ checkcpdtable.back().cond2 = pHMgr->decode_flag(chunk.c_str());
}
- np++;
+ break;
+ }
+ case 3: {
+ checkcpdtable.back().pattern3.assign(start_piece, iter);
+ simplifiedcpd = 1;
break;
}
default:
break;
}
i++;
+ start_piece = mystrsep(nl, iter);
}
- piece = mystrsep(&tp, 0);
+ }
+ return true;
+}
+
+/* parse in the compound rule table */
+bool AffixMgr::parse_defcpdtable(const std::string& line, FileMgr* af) {
+ if (parseddefcpd) {
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
+ af->getlinenum());
+ return false;
+ }
+ parseddefcpd = true;
+ int numdefcpd = -1;
+ int i = 0;
+ int np = 0;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numdefcpd = atoi(std::string(start_piece, iter).c_str());
+ if (numdefcpd < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
+ }
+ defcpdtable.reserve(numdefcpd);
+ np++;
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
- /* now parse the phone->num lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < phone->num; j++) {
- if (!(nl = af->getline()))
- return 1;
+ /* now parse the numdefcpd lines to read in the remainder of the table */
+ for (int j = 0; j < numdefcpd; ++j) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
i = 0;
- phone->rules[j * 2] = NULL;
- phone->rules[j * 2 + 1] = NULL;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "PHONE", 5) != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- phone->num = 0;
- return 1;
- }
- break;
- }
- case 1: {
- phone->rules[j * 2] = mystrrep(mystrdup(piece), "_", "");
- break;
- }
- case 2: {
- phone->rules[j * 2 + 1] = mystrrep(mystrdup(piece), "_", "");
- break;
- }
- default:
- break;
- }
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- phone->num = 0;
- return 1;
- }
- }
- phone->rules[phone->num * 2] = mystrdup("");
- phone->rules[phone->num * 2 + 1] = mystrdup("");
- init_phonet_hash(*phone);
- return 0;
-}
-
-/* parse in the checkcompoundpattern table */
-int AffixMgr::parse_checkcpdtable(char* line, FileMgr* af) {
- if (numcheckcpd != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
- af->getlinenum());
- return 1;
- }
- char* tp = line;
- char* piece;
- int i = 0;
- int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ defcpdtable.push_back(flagentry());
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
switch (i) {
case 0: {
- np++;
- break;
- }
- case 1: {
- numcheckcpd = atoi(piece);
- if (numcheckcpd < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ if (nl.compare(start_piece - nl.begin(), 12, "COMPOUNDRULE", 12) != 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- return 1;
+ numdefcpd = 0;
+ return false;
}
- checkcpdtable =
- (patentry*)malloc(numcheckcpd * sizeof(struct patentry));
- if (!checkcpdtable)
- return 1;
- np++;
break;
}
- default:
- break;
- }
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if (np != 2) {
- HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
- af->getlinenum());
- return 1;
- }
-
- /* now parse the numcheckcpd lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < numcheckcpd; j++) {
- if (!(nl = af->getline()))
- return 1;
- mychomp(nl);
- tp = nl;
- i = 0;
- checkcpdtable[j].pattern = NULL;
- checkcpdtable[j].pattern2 = NULL;
- checkcpdtable[j].pattern3 = NULL;
- checkcpdtable[j].cond = FLAG_NULL;
- checkcpdtable[j].cond2 = FLAG_NULL;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "CHECKCOMPOUNDPATTERN", 20) != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numcheckcpd = 0;
- return 1;
- }
- break;
- }
- case 1: {
- checkcpdtable[j].pattern = mystrdup(piece);
- char* p = strchr(checkcpdtable[j].pattern, '/');
- if (p) {
- *p = '\0';
- checkcpdtable[j].cond = pHMgr->decode_flag(p + 1);
- }
- break;
- }
- case 2: {
- checkcpdtable[j].pattern2 = mystrdup(piece);
- char* p = strchr(checkcpdtable[j].pattern2, '/');
- if (p) {
- *p = '\0';
- checkcpdtable[j].cond2 = pHMgr->decode_flag(p + 1);
+ case 1: { // handle parenthesized flags
+ if (std::find(start_piece, iter, '(') != iter) {
+ for (std::string::const_iterator k = start_piece; k != iter; ++k) {
+ std::string::const_iterator chb = k;
+ std::string::const_iterator che = k + 1;
+ if (*k == '(') {
+ std::string::const_iterator parpos = std::find(k, iter, ')');
+ if (parpos != iter) {
+ chb = k + 1;
+ che = parpos;
+ k = parpos;
+ }
+ }
+
+ if (*chb == '*' || *chb == '?') {
+ defcpdtable.back().push_back((FLAG)*chb);
+ } else {
+ pHMgr->decode_flags(defcpdtable.back(), std::string(chb, che), af);
+ }
}
- break;
- }
- case 3: {
- checkcpdtable[j].pattern3 = mystrdup(piece);
- simplifiedcpd = 1;
- break;
+ } else {
+ pHMgr->decode_flags(defcpdtable.back(), std::string(start_piece, iter), af);
}
- default:
- break;
- }
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numcheckcpd = 0;
- return 1;
- }
- }
- return 0;
-}
-
-/* parse in the compound rule table */
-int AffixMgr::parse_defcpdtable(char* line, FileMgr* af) {
- if (numdefcpd != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
- af->getlinenum());
- return 1;
- }
- char* tp = line;
- char* piece;
- int i = 0;
- int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- np++;
- break;
- }
- case 1: {
- numdefcpd = atoi(piece);
- if (numdefcpd < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- return 1;
- }
- defcpdtable = (flagentry*)malloc(numdefcpd * sizeof(flagentry));
- if (!defcpdtable)
- return 1;
- np++;
break;
}
default:
break;
}
- i++;
+ ++i;
+ start_piece = mystrsep(nl, iter);
+ }
+ if (defcpdtable.back().empty()) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ return false;
}
- piece = mystrsep(&tp, 0);
+ }
+ return true;
+}
+
+/* parse in the character map table */
+bool AffixMgr::parse_maptable(const std::string& line, FileMgr* af) {
+ if (parsedmaptable) {
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
+ af->getlinenum());
+ return false;
+ }
+ parsedmaptable = true;
+ int nummap = -1;
+ int i = 0;
+ int np = 0;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ nummap = atoi(std::string(start_piece, iter).c_str());
+ if (nummap < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
+ }
+ maptable.reserve(nummap);
+ np++;
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
- /* now parse the numdefcpd lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < numdefcpd; j++) {
- if (!(nl = af->getline()))
- return 1;
+ /* now parse the nummap lines to read in the remainder of the table */
+ for (int j = 0; j < nummap; ++j) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
i = 0;
- defcpdtable[j].def = NULL;
- defcpdtable[j].len = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "COMPOUNDRULE", 12) != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numdefcpd = 0;
- return 1;
- }
- break;
- }
- case 1: { // handle parenthesized flags
- if (strchr(piece, '(')) {
- defcpdtable[j].def = (FLAG*)malloc(strlen(piece) * sizeof(FLAG));
- defcpdtable[j].len = 0;
- int end = 0;
- FLAG* conv;
- while (!end) {
- char* par = piece + 1;
- while (*par != '(' && *par != ')' && *par != '\0')
- par++;
- if (*par == '\0')
- end = 1;
- else
- *par = '\0';
- if (*piece == '(')
- piece++;
- if (*piece == '*' || *piece == '?') {
- defcpdtable[j].def[defcpdtable[j].len++] = (FLAG)*piece;
- } else if (*piece != '\0') {
- int l = pHMgr->decode_flags(&conv, piece, af);
- for (int k = 0; k < l; k++)
- defcpdtable[j].def[defcpdtable[j].len++] = conv[k];
- free(conv);
- }
- piece = par + 1;
- }
- } else {
- defcpdtable[j].len =
- pHMgr->decode_flags(&(defcpdtable[j].def), piece, af);
- }
- break;
- }
- default:
- break;
- }
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if (!defcpdtable[j].len) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numdefcpd = 0;
- return 1;
- }
- }
- return 0;
-}
-
-/* parse in the character map table */
-int AffixMgr::parse_maptable(char* line, FileMgr* af) {
- if (nummap != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
- af->getlinenum());
- return 1;
- }
- char* tp = line;
- char* piece;
- int i = 0;
- int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ maptable.push_back(mapentry());
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
switch (i) {
case 0: {
- np++;
+ if (nl.compare(start_piece - nl.begin(), 3, "MAP", 3) != 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ nummap = 0;
+ return false;
+ }
break;
}
case 1: {
- nummap = atoi(piece);
- if (nummap < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- return 1;
+ for (std::string::const_iterator k = start_piece; k != iter; ++k) {
+ std::string::const_iterator chb = k;
+ std::string::const_iterator che = k + 1;
+ if (*k == '(') {
+ std::string::const_iterator parpos = std::find(k, iter, ')');
+ if (parpos != iter) {
+ chb = k + 1;
+ che = parpos;
+ k = parpos;
+ }
+ } else {
+ if (utf8 && (*k & 0xc0) == 0xc0) {
+ ++k;
+ while (k != iter && (*k & 0xc0) == 0x80)
+ ++k;
+ che = k;
+ --k;
+ }
+ }
+ maptable.back().push_back(std::string(chb, che));
}
- maptable = (mapentry*)malloc(nummap * sizeof(struct mapentry));
- if (!maptable)
- return 1;
- np++;
break;
}
default:
break;
}
- i++;
+ ++i;
+ start_piece = mystrsep(nl, iter);
+ }
+ if (maptable.back().empty()) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ return false;
}
- piece = mystrsep(&tp, 0);
+ }
+ return true;
+}
+
+/* parse in the word breakpoint table */
+bool AffixMgr::parse_breaktable(const std::string& line, FileMgr* af) {
+ if (parsedbreaktable) {
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
+ af->getlinenum());
+ return false;
+ }
+ parsedbreaktable = true;
+ int numbreak = -1;
+ int i = 0;
+ int np = 0;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numbreak = atoi(std::string(start_piece, iter).c_str());
+ if (numbreak < 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
+ }
+ if (numbreak == 0)
+ return true;
+ breaktable.reserve(numbreak);
+ np++;
+ break;
+ }
+ default:
+ break;
+ }
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
- /* now parse the nummap lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < nummap; j++) {
- if (!(nl = af->getline()))
- return 1;
+ /* now parse the numbreak lines to read in the remainder of the table */
+ for (int j = 0; j < numbreak; ++j) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
i = 0;
- maptable[j].set = NULL;
- maptable[j].len = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "MAP", 3) != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- nummap = 0;
- return 1;
- }
- break;
- }
- case 1: {
- int setn = 0;
- maptable[j].len = strlen(piece);
- maptable[j].set = (char**)malloc(maptable[j].len * sizeof(char*));
- if (!maptable[j].set)
- return 1;
- for (int k = 0; k < maptable[j].len; k++) {
- int chl = 1;
- int chb = k;
- if (piece[k] == '(') {
- char* parpos = strchr(piece + k, ')');
- if (parpos != NULL) {
- chb = k + 1;
- chl = (int)(parpos - piece) - k - 1;
- k = k + chl + 1;
- }
- } else {
- if (utf8 && (piece[k] & 0xc0) == 0xc0) {
- for (k++; utf8 && (piece[k] & 0xc0) == 0x80; k++)
- ;
- chl = k - chb;
- k--;
- }
- }
- maptable[j].set[setn] = (char*)malloc(chl + 1);
- if (!maptable[j].set[setn])
- return 1;
- strncpy(maptable[j].set[setn], piece + chb, chl);
- maptable[j].set[setn][chl] = '\0';
- setn++;
- }
- maptable[j].len = setn;
- break;
- }
- default:
- break;
- }
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if (!maptable[j].set || !maptable[j].len) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- nummap = 0;
- return 1;
- }
- }
- return 0;
-}
-
-/* parse in the word breakpoint table */
-int AffixMgr::parse_breaktable(char* line, FileMgr* af) {
- if (numbreak > -1) {
- HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
- af->getlinenum());
- return 1;
- }
- char* tp = line;
- char* piece;
- int i = 0;
- int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
switch (i) {
case 0: {
- np++;
+ if (nl.compare(start_piece - nl.begin(), 5, "BREAK", 5) != 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ numbreak = 0;
+ return false;
+ }
break;
}
case 1: {
- numbreak = atoi(piece);
- if (numbreak < 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- return 1;
- }
- if (numbreak == 0)
- return 0;
- breaktable = (char**)malloc(numbreak * sizeof(char*));
- if (!breaktable)
- return 1;
- np++;
+ breaktable.push_back(std::string(start_piece, iter));
break;
}
default:
break;
}
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if (np != 2) {
- HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
- af->getlinenum());
- return 1;
- }
-
- /* now parse the numbreak lines to read in the remainder of the table */
- char* nl;
- for (int j = 0; j < numbreak; j++) {
- if (!(nl = af->getline()))
- return 1;
- mychomp(nl);
- tp = nl;
- i = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "BREAK", 5) != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numbreak = 0;
- return 1;
- }
- break;
- }
- case 1: {
- breaktable[j] = mystrdup(piece);
- break;
- }
- default:
- break;
- }
- i++;
- }
- piece = mystrsep(&tp, 0);
- }
- if (!breaktable) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numbreak = 0;
- return 1;
+ ++i;
+ start_piece = mystrsep(nl, iter);
}
}
- return 0;
+
+ if (breaktable.size() != static_cast<size_t>(numbreak)) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ return false;
+ }
+
+ return true;
}
void AffixMgr::reverse_condition(std::string& piece) {
if (piece.empty())
return;
int neg = 0;
for (std::string::reverse_iterator k = piece.rbegin(); k != piece.rend(); ++k) {
@@ -4660,314 +4398,356 @@ void AffixMgr::reverse_condition(std::st
default: {
if (neg)
*(k - 1) = *k;
}
}
}
}
-int AffixMgr::parse_affix(char* line,
+class entries_container {
+ std::vector<AffEntry*> entries;
+ AffixMgr* m_mgr;
+ char m_at;
+public:
+ entries_container(char at, AffixMgr* mgr)
+ : m_mgr(mgr)
+ , m_at(at) {
+ }
+ void release() {
+ entries.clear();
+ }
+ void initialize(int numents,
+ char opts, unsigned short aflag) {
+ entries.reserve(numents);
+
+ if (m_at == 'P') {
+ entries.push_back(new PfxEntry(m_mgr));
+ } else {
+ entries.push_back(new SfxEntry(m_mgr));
+ }
+
+ entries.back()->opts = opts;
+ entries.back()->aflag = aflag;
+ }
+
+ AffEntry* add_entry(char opts) {
+ if (m_at == 'P') {
+ entries.push_back(new PfxEntry(m_mgr));
+ } else {
+ entries.push_back(new SfxEntry(m_mgr));
+ }
+ AffEntry* ret = entries.back();
+ ret->opts = entries[0]->opts & opts;
+ return ret;
+ }
+
+ AffEntry* first_entry() {
+ return entries.empty() ? NULL : entries[0];
+ }
+
+ ~entries_container() {
+ for (size_t i = 0; i < entries.size(); ++i) {
+ delete entries[i];
+ }
+ }
+
+ std::vector<AffEntry*>::iterator begin() { return entries.begin(); }
+ std::vector<AffEntry*>::iterator end() { return entries.end(); }
+};
+
+bool AffixMgr::parse_affix(const std::string& line,
const char at,
FileMgr* af,
char* dupflags) {
- int numents = 0; // number of affentry structures to parse
+ int numents = 0; // number of AffEntry structures to parse
unsigned short aflag = 0; // affix char identifier
char ff = 0;
- std::vector<affentry> affentries;
-
- char* tp = line;
- char* nl = line;
- char* piece;
+ entries_container affentries(at, this);
+
int i = 0;
// checking lines with bad syntax
#ifdef DEBUG
int basefieldnum = 0;
#endif
// split affix header line into pieces
int np = 0;
-
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- // piece 1 - is type of affix
- case 0: {
- np++;
- break;
- }
-
- // piece 2 - is affix char
- case 1: {
- np++;
- aflag = pHMgr->decode_flag(piece);
- if (((at == 'S') && (dupflags[aflag] & dupSFX)) ||
- ((at == 'P') && (dupflags[aflag] & dupPFX))) {
- HUNSPELL_WARNING(
- stderr,
- "error: line %d: multiple definitions of an affix flag\n",
- af->getlinenum());
- // return 1; XXX permissive mode for bad dictionaries
- }
- dupflags[aflag] += (char)((at == 'S') ? dupSFX : dupPFX);
- break;
- }
- // piece 3 - is cross product indicator
- case 2: {
- np++;
- if (*piece == 'Y')
- ff = aeXPRODUCT;
- break;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ // piece 1 - is type of affix
+ case 0: {
+ np++;
+ break;
+ }
+
+ // piece 2 - is affix char
+ case 1: {
+ np++;
+ aflag = pHMgr->decode_flag(std::string(start_piece, iter).c_str());
+ if (((at == 'S') && (dupflags[aflag] & dupSFX)) ||
+ ((at == 'P') && (dupflags[aflag] & dupPFX))) {
+ HUNSPELL_WARNING(
+ stderr,
+ "error: line %d: multiple definitions of an affix flag\n",
+ af->getlinenum());
}
-
- // piece 4 - is number of affentries
- case 3: {
- np++;
- numents = atoi(piece);
- if ((numents <= 0) || ((std::numeric_limits<size_t>::max() /
- sizeof(struct affentry)) < static_cast<size_t>(numents))) {
- char* err = pHMgr->encode_flag(aflag);
- if (err) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- free(err);
- }
- return 1;
+ dupflags[aflag] += (char)((at == 'S') ? dupSFX : dupPFX);
+ break;
+ }
+ // piece 3 - is cross product indicator
+ case 2: {
+ np++;
+ if (*start_piece == 'Y')
+ ff = aeXPRODUCT;
+ break;
+ }
+
+ // piece 4 - is number of affentries
+ case 3: {
+ np++;
+ numents = atoi(std::string(start_piece, iter).c_str());
+ if ((numents <= 0) || ((std::numeric_limits<size_t>::max() /
+ sizeof(AffEntry)) < static_cast<size_t>(numents))) {
+ char* err = pHMgr->encode_flag(aflag);
+ if (err) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ free(err);
}
- affentries.resize(numents);
- affentries[0].opts = ff;
- if (utf8)
- affentries[0].opts += aeUTF8;
- if (pHMgr->is_aliasf())
- affentries[0].opts += aeALIASF;
- if (pHMgr->is_aliasm())
- affentries[0].opts += aeALIASM;
- affentries[0].aflag = aflag;
+ return false;
}
- default:
- break;
+ char opts = ff;
+ if (utf8)
+ opts += aeUTF8;
+ if (pHMgr->is_aliasf())
+ opts += aeALIASF;
+ if (pHMgr->is_aliasm())
+ opts += aeALIASM;
+ affentries.initialize(numents, opts, aflag);
}
- i++;
+
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(line, iter);
}
// check to make sure we parsed enough pieces
if (np != 4) {
char* err = pHMgr->encode_flag(aflag);
if (err) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
free(err);
}
- return 1;
+ return false;
}
// now parse numents affentries for this affix
- std::vector<affentry>::iterator start = affentries.begin();
- std::vector<affentry>::iterator end = affentries.end();
- for (std::vector<affentry>::iterator entry = start; entry != end; ++entry) {
- if ((nl = af->getline()) == NULL)
- return 1;
+ AffEntry* entry = affentries.first_entry();
+ for (int ent = 0; ent < numents; ++ent) {
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
+
+ iter = nl.begin();
i = 0;
np = 0;
// split line into pieces
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- // piece 1 - is type
- case 0: {
- np++;
- if (entry != start)
- entry->opts = start->opts &
- (char)(aeXPRODUCT + aeUTF8 + aeALIASF + aeALIASM);
- break;
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
+ switch (i) {
+ // piece 1 - is type
+ case 0: {
+ np++;
+ if (ent != 0)
+ entry = affentries.add_entry((char)(aeXPRODUCT + aeUTF8 + aeALIASF + aeALIASM));
+ break;
+ }
+
+ // piece 2 - is affix char
+ case 1: {
+ np++;
+ std::string chunk(start_piece, iter);
+ if (pHMgr->decode_flag(chunk.c_str()) != aflag) {
+ char* err = pHMgr->encode_flag(aflag);
+ if (err) {
+ HUNSPELL_WARNING(stderr,
+ "error: line %d: affix %s is corrupt\n",
+ af->getlinenum(), err);
+ free(err);
+ }
+ return false;
+ }
+
+ if (ent != 0) {
+ AffEntry* start_entry = affentries.first_entry();
+ entry->aflag = start_entry->aflag;
}
-
- // piece 2 - is affix char
- case 1: {
- np++;
- if (pHMgr->decode_flag(piece) != aflag) {
- char* err = pHMgr->encode_flag(aflag);
- if (err) {
- HUNSPELL_WARNING(stderr,
- "error: line %d: affix %s is corrupt\n",
- af->getlinenum(), err);
- free(err);
+ break;
+ }
+
+ // piece 3 - is string to strip or 0 for null
+ case 2: {
+ np++;
+ entry->strip = std::string(start_piece, iter);
+ if (complexprefixes) {
+ if (utf8)
+ reverseword_utf(entry->strip);
+ else
+ reverseword(entry->strip);
+ }
+ if (entry->strip.compare("0") == 0) {
+ entry->strip.clear();
+ }
+ break;
+ }
+
+ // piece 4 - is affix string or 0 for null
+ case 3: {
+ entry->morphcode = NULL;
+ entry->contclass = NULL;
+ entry->contclasslen = 0;
+ np++;
+ std::string::const_iterator dash = std::find(start_piece, iter, '/');
+ if (dash != iter) {
+ entry->appnd = std::string(start_piece, dash);
+ std::string dash_str(dash + 1, iter);
+
+ if (!ignorechars.empty()) {
+ if (utf8) {
+ remove_ignored_chars_utf(entry->appnd, ignorechars_utf16);
+ } else {
+ remove_ignored_chars(entry->appnd, ignorechars);
}
- return 1;
}
- if (entry != start)
- entry->aflag = start->aflag;
- break;
- }
-
- // piece 3 - is string to strip or 0 for null
- case 2: {
- np++;
- entry->strip = piece;
if (complexprefixes) {
if (utf8)
- reverseword_utf(entry->strip);
+ reverseword_utf(entry->appnd);
else
- reverseword(entry->strip);
- }
- if (entry->strip.compare("0") == 0) {
- entry->strip.clear();
+ reverseword(entry->appnd);
}
- break;
- }
-
- // piece 4 - is affix string or 0 for null
- case 3: {
- char* dash;
- entry->morphcode = NULL;
- entry->contclass = NULL;
- entry->contclasslen = 0;
- np++;
- dash = strchr(piece, '/');
- if (dash) {
- *dash = '\0';
-
- entry->appnd = piece;
-
- if (ignorechars) {
- if (utf8) {
- remove_ignored_chars_utf(entry->appnd, ignorechars_utf16);
- } else {
- remove_ignored_chars(entry->appnd, ignorechars);
- }
- }
-
- if (complexprefixes) {
- if (utf8)
- reverseword_utf(entry->appnd);
- else
- reverseword(entry->appnd);
- }
-
- if (pHMgr->is_aliasf()) {
- int index = atoi(dash + 1);
- entry->contclasslen = (unsigned short)pHMgr->get_aliasf(
- index, &(entry->contclass), af);
- if (!entry->contclasslen)
- HUNSPELL_WARNING(stderr,
- "error: bad affix flag alias: \"%s\"\n",
- dash + 1);
+
+ if (pHMgr->is_aliasf()) {
+ int index = atoi(dash_str.c_str());
+ entry->contclasslen = (unsigned short)pHMgr->get_aliasf(
+ index, &(entry->contclass), af);
+ if (!entry->contclasslen)
+ HUNSPELL_WARNING(stderr,
+ "error: bad affix flag alias: \"%s\"\n",
+ dash_str.c_str());
+ } else {
+ entry->contclasslen = (unsigned short)pHMgr->decode_flags(
+ &(entry->contclass), dash_str.c_str(), af);
+ std::sort(entry->contclass, entry->contclass + entry->contclasslen);
+ }
+
+ havecontclass = 1;
+ for (unsigned short _i = 0; _i < entry->contclasslen; _i++) {
+ contclasses[(entry->contclass)[_i]] = 1;
+ }
+ } else {
+ entry->appnd = std::string(start_piece, iter);
+
+ if (!ignorechars.empty()) {
+ if (utf8) {
+ remove_ignored_chars_utf(entry->appnd, ignorechars_utf16);
} else {
- entry->contclasslen = (unsigned short)pHMgr->decode_flags(
- &(entry->contclass), dash + 1, af);
- std::sort(entry->contclass, entry->contclass + entry->contclasslen);
- }
- *dash = '/';
-
- havecontclass = 1;
- for (unsigned short _i = 0; _i < entry->contclasslen; _i++) {
- contclasses[(entry->contclass)[_i]] = 1;
- }
- } else {
- entry->appnd = piece;
-
- if (ignorechars) {
- if (utf8) {
- remove_ignored_chars_utf(entry->appnd, ignorechars_utf16);
- } else {
- remove_ignored_chars(entry->appnd, ignorechars);
- }
- }
-
- if (complexprefixes) {
- if (utf8)
- reverseword_utf(entry->appnd);
- else
- reverseword(entry->appnd);
+ remove_ignored_chars(entry->appnd, ignorechars);
}
}
- if (entry->appnd.compare("0") == 0) {
- entry->appnd.clear();
+ if (complexprefixes) {
+ if (utf8)
+ reverseword_utf(entry->appnd);
+ else
+ reverseword(entry->appnd);
}
- break;
+ }
+
+ if (entry->appnd.compare("0") == 0) {
+ entry->appnd.clear();
}
-
- // piece 5 - is the conditions descriptions
- case 4: {
- std::string chunk(piece);
- np++;
- if (complexprefixes) {
+ break;
+ }
+
+ // piece 5 - is the conditions descriptions
+ case 4: {
+ std::string chunk(start_piece, iter);
+ np++;
+ if (complexprefixes) {
+ if (utf8)
+ reverseword_utf(chunk);
+ else
+ reverseword(chunk);
+ reverse_condition(chunk);
+ }
+ if (!entry->strip.empty() && chunk != "." &&
+ redundant_condition(at, entry->strip.c_str(), entry->strip.size(), chunk.c_str(),
+ af->getlinenum()))
+ chunk = ".";
+ if (at == 'S') {
+ reverseword(chunk);
+ reverse_condition(chunk);
+ }
+ if (encodeit(*entry, chunk.c_str()))
+ return false;
+ break;
+ }
+
+ case 5: {
+ std::string chunk(start_piece, iter);
+ np++;
+ if (pHMgr->is_aliasm()) {
+ int index = atoi(chunk.c_str());
+ entry->morphcode = pHMgr->get_aliasm(index);
+ } else {
+ if (complexprefixes) { // XXX - fix me for morph. gen.
if (utf8)
reverseword_utf(chunk);
else
reverseword(chunk);
- reverse_condition(chunk);
}
- if (!entry->strip.empty() && chunk != "." &&
- redundant_condition(at, entry->strip.c_str(), entry->strip.size(), chunk.c_str(),
- af->getlinenum()))
- chunk = ".";
- if (at == 'S') {
- reverseword(chunk);
- reverse_condition(chunk);
+ // add the remaining of the line
+ std::string::const_iterator end = nl.end();
+ if (iter != end) {
+ chunk.append(iter, end);
}
- if (encodeit(*entry, chunk.c_str()))
- return 1;
- break;
+ entry->morphcode = mystrdup(chunk.c_str());
+ if (!entry->morphcode)
+ return false;
}
-
- case 5: {
- std::string chunk(piece);
- np++;
- if (pHMgr->is_aliasm()) {
- int index = atoi(chunk.c_str());
- entry->morphcode = pHMgr->get_aliasm(index);
- } else {
- if (complexprefixes) { // XXX - fix me for morph. gen.
- if (utf8)
- reverseword_utf(chunk);
- else
- reverseword(chunk);
- }
- // add the remaining of the line
- if (*tp) {
- *(tp - 1) = ' ';
- chunk.push_back(' ');
- chunk.append(tp);
- }
- entry->morphcode = mystrdup(chunk.c_str());
- if (!entry->morphcode)
- return 1;
- }
- break;
- }
- default:
- break;
+ break;
}
- i++;
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ i++;
+ start_piece = mystrsep(nl, iter);
}
// check to make sure we parsed enough pieces
if (np < 4) {
char* err = pHMgr->encode_flag(aflag);
if (err) {
HUNSPELL_WARNING(stderr, "error: line %d: affix %s is corrupt\n",
af->getlinenum(), err);
free(err);
}
- return 1;
+ return false;
}
#ifdef DEBUG
// detect unnecessary fields, excepting comments
if (basefieldnum) {
int fieldnum =
!(entry->morphcode) ? 5 : ((*(entry->morphcode) == '#') ? 5 : 6);
if (fieldnum != basefieldnum)
@@ -4977,26 +4757,30 @@ int AffixMgr::parse_affix(char* line,
basefieldnum =
!(entry->morphcode) ? 5 : ((*(entry->morphcode) == '#') ? 5 : 6);
}
#endif
}
// now create SfxEntry or PfxEntry objects and use links to
// build an ordered (sorted by affix string) list
- for (std::vector<affentry>::iterator entry = start; entry != end; ++entry) {
+ std::vector<AffEntry*>::iterator start = affentries.begin();
+ std::vector<AffEntry*>::iterator end = affentries.end();
+ for (std::vector<AffEntry*>::iterator affentry = start; affentry != end; ++affentry) {
if (at == 'P') {
- PfxEntry* pfxptr = new PfxEntry(this, &(*entry));
- build_pfxtree(pfxptr);
+ build_pfxtree(static_cast<PfxEntry*>(*affentry));
} else {
- SfxEntry* sfxptr = new SfxEntry(this, &(*entry));
- build_sfxtree(sfxptr);
+ build_sfxtree(static_cast<SfxEntry*>(*affentry));
}
}
- return 0;
+
+ //contents belong to AffixMgr now
+ affentries.release();
+
+ return true;
}
int AffixMgr::redundant_condition(char ft,
const char* strip,
int stripl,
const char* cond,
int linenum) {
int condl = strlen(cond);
@@ -5083,35 +4867,33 @@ int AffixMgr::redundant_condition(char f
}
if (j < 0)
return 1;
}
}
return 0;
}
-int AffixMgr::get_suffix_words(short unsigned* suff,
+std::vector<std::string> AffixMgr::get_suffix_words(short unsigned* suff,
int len,
- const char* root_word,
- char** slst) {
- int suff_words_cnt = 0;
+ const char* root_word) {
+ std::vector<std::string> slst;
short unsigned* start_ptr = suff;
for (int j = 0; j < SETSIZE; j++) {
SfxEntry* ptr = sStart[j];
while (ptr) {
suff = start_ptr;
for (int i = 0; i < len; i++) {
if ((*suff) == ptr->getFlag()) {
std::string nw(root_word);
nw.append(ptr->getAffix());
- hentry* ht = ptr->checkword(nw.c_str(), nw.size(), 0, NULL, NULL, 0,
- NULL, 0, 0, 0);
+ hentry* ht = ptr->checkword(nw.c_str(), nw.size(), 0, NULL, 0, 0, 0);
if (ht) {
- slst[suff_words_cnt++] = mystrdup(nw.c_str());
+ slst.push_back(nw);
}
}
suff++;
}
ptr = ptr->getNext();
}
}
- return suff_words_cnt;
+ return slst;
}
--- a/extensions/spellcheck/hunspell/src/affixmgr.hxx
+++ b/extensions/spellcheck/hunspell/src/affixmgr.hxx
@@ -66,49 +66,47 @@
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _AFFIXMGR_HXX_
-#define _AFFIXMGR_HXX_
-
-#include "hunvisapi.h"
+#ifndef AFFIXMGR_HXX_
+#define AFFIXMGR_HXX_
#include <stdio.h>
#include <string>
+#include <vector>
#include "atypes.hxx"
#include "baseaffix.hxx"
#include "hashmgr.hxx"
#include "phonet.hxx"
#include "replist.hxx"
// check flag duplication
#define dupSFX (1 << 0)
#define dupPFX (1 << 1)
class PfxEntry;
class SfxEntry;
-class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
+class AffixMgr {
PfxEntry* pStart[SETSIZE];
SfxEntry* sStart[SETSIZE];
PfxEntry* pFlag[SETSIZE];
SfxEntry* sFlag[SETSIZE];
- HashMgr* pHMgr;
- HashMgr** alldic;
- int* maxdic;
- char* keystring;
- char* trystring;
- char* encoding;
+ const std::vector<HashMgr*>& alldic;
+ const HashMgr* pHMgr;
+ std::string keystring;
+ std::string trystring;
+ std::string encoding;
struct cs_info* csconv;
int utf8;
int complexprefixes;
FLAG compoundflag;
FLAG compoundbegin;
FLAG compoundmiddle;
FLAG compoundend;
FLAG compoundroot;
@@ -120,56 +118,55 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr
int checkcompoundcase;
int checkcompoundtriple;
int simplifiedtriple;
FLAG forbiddenword;
FLAG nosuggest;
FLAG nongramsuggest;
FLAG needaffix;
int cpdmin;
- int numrep;
- replentry* reptable;
+ bool parsedrep;
+ std::vector<replentry> reptable;
RepList* iconvtable;
RepList* oconvtable;
- int nummap;
- mapentry* maptable;
- int numbreak;
- char** breaktable;
- int numcheckcpd;
- patentry* checkcpdtable;
+ bool parsedmaptable;
+ std::vector<mapentry> maptable;
+ bool parsedbreaktable;
+ std::vector<std::string> breaktable;
+ bool parsedcheckcpd;
+ std::vector<patentry> checkcpdtable;
int simplifiedcpd;
- int numdefcpd;
- flagentry* defcpdtable;
+ bool parseddefcpd;
+ std::vector<flagentry> defcpdtable;
phonetable* phone;
int maxngramsugs;
int maxcpdsugs;
int maxdiff;
int onlymaxdiff;
int nosplitsugs;
int sugswithdots;
int cpdwordmax;
int cpdmaxsyllable;
- char* cpdvowels;
- w_char* cpdvowels_utf16;
- int cpdvowels_utf16_len;
- char* cpdsyllablenum;
+ std::string cpdvowels; // vowels (for calculating of Hungarian compounding limit,
+ std::vector<w_char> cpdvowels_utf16; //vowels for UTF-8 encoding
+ std::string cpdsyllablenum; // syllable count incrementing flag
const char* pfxappnd; // BUG: not stateless
const char* sfxappnd; // BUG: not stateless
int sfxextra; // BUG: not stateless
FLAG sfxflag; // BUG: not stateless
char* derived; // BUG: not stateless
SfxEntry* sfx; // BUG: not stateless
PfxEntry* pfx; // BUG: not stateless
int checknum;
- char* wordchars;
+ std::string wordchars; // letters + spec. word characters
std::vector<w_char> wordchars_utf16;
- char* ignorechars;
+ std::string ignorechars; // letters + spec. word characters
std::vector<w_char> ignorechars_utf16;
- char* version;
- char* lang;
+ std::string version; // affix and dictionary file version string
+ std::string lang; // language
int langnum;
FLAG lemma_present;
FLAG circumfix;
FLAG onlyincompound;
FLAG keepcase;
FLAG forceucase;
FLAG warn;
int forbidwarn;
@@ -177,17 +174,17 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr
int checksharps;
int fullstrip;
int havecontclass; // boolean variable
char contclasses[CONTSIZE]; // flags of possible continuing classes (twofold
// affix)
public:
- AffixMgr(const char* affpath, HashMgr** ptr, int* md, const char* key = NULL);
+ AffixMgr(const char* affpath, const std::vector<HashMgr*>& ptr, const char* key = NULL);
~AffixMgr();
struct hentry* affix_check(const char* word,
int len,
const unsigned short needflag = (unsigned short)0,
char in_compound = IN_CPD_NOT);
struct hentry* prefix_check(const char* word,
int len,
char in_compound,
@@ -197,61 +194,58 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
inline int isRevSubset(const char* s1, const char* end_of_s2, int len);
struct hentry* suffix_check(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
- char** wlst,
- int maxSug,
- int* ns,
const FLAG cclass = FLAG_NULL,
const FLAG needflag = FLAG_NULL,
char in_compound = IN_CPD_NOT);
struct hentry* suffix_check_twosfx(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
- char* affix_check_morph(const char* word,
- int len,
- const FLAG needflag = FLAG_NULL,
- char in_compound = IN_CPD_NOT);
- char* prefix_check_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag = FLAG_NULL);
- char* suffix_check_morph(const char* word,
- int len,
- int sfxopts,
- PfxEntry* ppfx,
- const FLAG cclass = FLAG_NULL,
- const FLAG needflag = FLAG_NULL,
- char in_compound = IN_CPD_NOT);
+ std::string affix_check_morph(const char* word,
+ int len,
+ const FLAG needflag = FLAG_NULL,
+ char in_compound = IN_CPD_NOT);
+ std::string prefix_check_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag = FLAG_NULL);
+ std::string suffix_check_morph(const char* word,
+ int len,
+ int sfxopts,
+ PfxEntry* ppfx,
+ const FLAG cclass = FLAG_NULL,
+ const FLAG needflag = FLAG_NULL,
+ char in_compound = IN_CPD_NOT);
- char* prefix_check_twosfx_morph(const char* word,
- int len,
- char in_compound,
- const FLAG needflag = FLAG_NULL);
- char* suffix_check_twosfx_morph(const char* word,
- int len,
- int sfxopts,
- PfxEntry* ppfx,
- const FLAG needflag = FLAG_NULL);
+ std::string prefix_check_twosfx_morph(const char* word,
+ int len,
+ char in_compound,
+ const FLAG needflag = FLAG_NULL);
+ std::string suffix_check_twosfx_morph(const char* word,
+ int len,
+ int sfxopts,
+ PfxEntry* ppfx,
+ const FLAG needflag = FLAG_NULL);
- char* morphgen(const char* ts,
- int wl,
- const unsigned short* ap,
- unsigned short al,
- const char* morph,
- const char* targetmorph,
- int level);
+ std::string morphgen(const char* ts,
+ int wl,
+ const unsigned short* ap,
+ unsigned short al,
+ const char* morph,
+ const char* targetmorph,
+ int level);
int expand_rootword(struct guessword* wlst,
int maxn,
const char* ts,
int wl,
const unsigned short* ap,
unsigned short al,
const char* bad,
@@ -268,18 +262,17 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr
int defcpd_check(hentry*** words,
short wnum,
hentry* rv,
hentry** rwords,
char all);
int cpdcase_check(const char* word, int len);
inline int candidate_check(const char* word, int len);
void setcminmax(int* cmin, int* cmax, const char* word, int len);
- struct hentry* compound_check(const char* word,
- int len,
+ struct hentry* compound_check(const std::string& word,
short wordnum,
short numsyllable,
short maxwordnum,
short wnum,
hentry** words,
hentry** rwords,
char hu_mov_rule,
char is_sug,
@@ -289,57 +282,47 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr
int len,
short wordnum,
short numsyllable,
short maxwordnum,
short wnum,
hentry** words,
hentry** rwords,
char hu_mov_rule,
- char** result,
- char* partresult);
+ std::string& result,
+ const std::string* partresult);
- int get_suffix_words(short unsigned* suff,
+ std::vector<std::string> get_suffix_words(short unsigned* suff,
int len,
- const char* root_word,
- char** slst);
+ const char* root_word);
struct hentry* lookup(const char* word);
- int get_numrep() const;
- struct replentry* get_reptable() const;
+ const std::vector<replentry>& get_reptable() const;
RepList* get_iconvtable() const;
RepList* get_oconvtable() const;
struct phonetable* get_phonetable() const;
- int get_nummap() const;
- struct mapentry* get_maptable() const;
- int get_numbreak() const;
- char** get_breaktable() const;
- char* get_encoding();
+ const std::vector<mapentry>& get_maptable() const;
+ const std::vector<std::string>& get_breaktable() const;
+ const std::string& get_encoding();
int get_langnum() const;
char* get_key_string();
char* get_try_string() const;
- const char* get_wordchars() const;
+ const std::string& get_wordchars() const;
const std::vector<w_char>& get_wordchars_utf16() const;
- char* get_ignore() const;
+ const char* get_ignore() const;
const std::vector<w_char>& get_ignore_utf16() const;
int get_compound() const;
FLAG get_compoundflag() const;
- FLAG get_compoundbegin() const;
FLAG get_forbiddenword() const;
FLAG get_nosuggest() const;
FLAG get_nongramsuggest() const;
FLAG get_needaffix() const;
FLAG get_onlyincompound() const;
- FLAG get_compoundroot() const;
- FLAG get_lemma_present() const;
- int get_checknum() const;
- const char* get_prefix() const;
- const char* get_suffix() const;
const char* get_derived() const;
- const char* get_version() const;
+ const std::string& get_version() const;
int have_contclass() const;
int get_utf8() const;
int get_complexprefixes() const;
char* get_suffixed(char) const;
int get_maxngramsugs() const;
int get_maxcpdsugs() const;
int get_maxdiff() const;
int get_onlymaxdiff() const;
@@ -350,36 +333,35 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr
FLAG get_warn(void) const;
int get_forbidwarn(void) const;
int get_checksharps(void) const;
char* encode_flag(unsigned short aflag) const;
int get_fullstrip() const;
private:
int parse_file(const char* affpath, const char* key);
- int parse_flag(char* line, unsigned short* out, FileMgr* af);
- int parse_num(char* line, int* out, FileMgr* af);
- int parse_cpdsyllable(char* line, FileMgr* af);
- int parse_reptable(char* line, FileMgr* af);
- int parse_convtable(char* line,
+ bool parse_flag(const std::string& line, unsigned short* out, FileMgr* af);
+ bool parse_num(const std::string& line, int* out, FileMgr* af);
+ bool parse_cpdsyllable(const std::string& line, FileMgr* af);
+ bool parse_reptable(const std::string& line, FileMgr* af);
+ bool parse_convtable(const std::string& line,
FileMgr* af,
RepList** rl,
- const char* keyword);
- int parse_phonetable(char* line, FileMgr* af);
- int parse_maptable(char* line, FileMgr* af);
- int parse_breaktable(char* line, FileMgr* af);
- int parse_checkcpdtable(char* line, FileMgr* af);
- int parse_defcpdtable(char* line, FileMgr* af);
- int parse_affix(char* line, const char at, FileMgr* af, char* dupflags);
+ const std::string& keyword);
+ bool parse_phonetable(const std::string& line, FileMgr* af);
+ bool parse_maptable(const std::string& line, FileMgr* af);
+ bool parse_breaktable(const std::string& line, FileMgr* af);
+ bool parse_checkcpdtable(const std::string& line, FileMgr* af);
+ bool parse_defcpdtable(const std::string& line, FileMgr* af);
+ bool parse_affix(const std::string& line, const char at, FileMgr* af, char* dupflags);
void reverse_condition(std::string&);
- void debugflag(char* result, unsigned short flag);
std::string& debugflag(std::string& result, unsigned short flag);
int condlen(const char*);
- int encodeit(affentry& entry, const char* cs);
+ int encodeit(AffEntry& entry, const char* cs);
int build_pfxtree(PfxEntry* pfxptr);
int build_sfxtree(SfxEntry* sfxptr);
int process_pfx_order();
int process_sfx_order();
PfxEntry* process_pfx_in_order(PfxEntry* ptr, PfxEntry* nptr);
SfxEntry* process_sfx_in_order(SfxEntry* ptr, SfxEntry* nptr);
int process_pfx_tree_to_list();
int process_sfx_tree_to_list();
--- a/extensions/spellcheck/hunspell/src/atypes.hxx
+++ b/extensions/spellcheck/hunspell/src/atypes.hxx
@@ -33,42 +33,42 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#ifndef _ATYPES_HXX_
-#define _ATYPES_HXX_
+#ifndef ATYPES_HXX_
+#define ATYPES_HXX_
#ifndef HUNSPELL_WARNING
#include <stdio.h>
#ifdef HUNSPELL_WARNING_ON
#define HUNSPELL_WARNING fprintf
#else
// empty inline function to switch off warnings (instead of the C99 standard
// variadic macros)
static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
#endif
#endif
// HUNSTEM def.
#define HUNSTEM
-#include "hashmgr.hxx"
#include "w_char.hxx"
#include <algorithm>
#include <string>
+#include <vector>
#define SETSIZE 256
#define CONTSIZE 65536
-// affentry options
+// AffEntry options
#define aeXPRODUCT (1 << 0)
#define aeUTF8 (1 << 1)
#define aeALIASF (1 << 2)
#define aeALIASM (1 << 3)
#define aeLONGCOND (1 << 4)
// compound options
#define IN_CPD_NOT 0
@@ -80,66 +80,43 @@ static inline void HUNSPELL_WARNING(FILE
#define SPELL_COMPOUND (1 << 0)
#define SPELL_FORBIDDEN (1 << 1)
#define SPELL_ALLCAP (1 << 2)
#define SPELL_NOCAP (1 << 3)
#define SPELL_INITCAP (1 << 4)
#define SPELL_ORIGCAP (1 << 5)
#define SPELL_WARN (1 << 6)
-#define MAXLNLEN 8192
-
#define MINCPDLEN 3
#define MAXCOMPOUND 10
#define MAXCONDLEN 20
#define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char*))
#define MAXACC 1000
#define FLAG unsigned short
#define FLAG_NULL 0x00
#define FREE_FLAG(a) a = 0
#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
-struct affentry {
- std::string strip;
- std::string appnd;
- char numconds;
- char opts;
- unsigned short aflag;
- unsigned short* contclass;
- short contclasslen;
- union {
- char conds[MAXCONDLEN];
- struct {
- char conds1[MAXCONDLEN_1];
- char* conds2;
- } l;
- } c;
- char* morphcode;
-};
-
struct guessword {
char* word;
bool allow;
char* orig;
};
-struct mapentry {
- char** set;
- int len;
-};
-
-struct flagentry {
- FLAG* def;
- int len;
-};
+typedef std::vector<std::string> mapentry;
+typedef std::vector<FLAG> flagentry;
struct patentry {
- char* pattern;
- char* pattern2;
- char* pattern3;
+ std::string pattern;
+ std::string pattern2;
+ std::string pattern3;
FLAG cond;
FLAG cond2;
+ patentry()
+ : cond(FLAG_NULL)
+ , cond2(FLAG_NULL) {
+ }
};
#endif
--- a/extensions/spellcheck/hunspell/src/baseaffix.hxx
+++ b/extensions/spellcheck/hunspell/src/baseaffix.hxx
@@ -33,35 +33,35 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#ifndef _BASEAFF_HXX_
-#define _BASEAFF_HXX_
+#ifndef BASEAFF_HXX_
+#define BASEAFF_HXX_
-#include "hunvisapi.h"
#include <string>
-class LIBHUNSPELL_DLL_EXPORTED AffEntry {
+class AffEntry {
private:
AffEntry(const AffEntry&);
AffEntry& operator=(const AffEntry&);
- protected:
+ public:
AffEntry()
: numconds(0),
opts(0),
aflag(0),
morphcode(0),
contclass(NULL),
contclasslen(0) {}
+ virtual ~AffEntry();
std::string appnd;
std::string strip;
unsigned char numconds;
char opts;
unsigned short aflag;
union {
char conds[MAXCONDLEN];
struct {
--- a/extensions/spellcheck/hunspell/src/csutil.cxx
+++ b/extensions/spellcheck/hunspell/src/csutil.cxx
@@ -71,16 +71,17 @@
* SUCH DAMAGE.
*/
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
+#include <sstream>
#include "csutil.hxx"
#include "atypes.hxx"
#include "langnum.hxx"
// Unicode character encoding information
struct unicode_info {
unsigned short c;
@@ -117,36 +118,34 @@ struct unicode_info2 {
unsigned short cupper;
unsigned short clower;
};
static struct unicode_info2* utf_tbl = NULL;
static int utf_tbl_count =
0; // utf_tbl can be used by multiple Hunspell instances
-FILE* myfopen(const char* path, const char* mode) {
-#ifdef _WIN32
+void myopen(std::ifstream& stream, const char* path, std::ios_base::openmode mode)
+{
+#if defined(_WIN32) && defined(_MSC_VER)
#define WIN32_LONG_PATH_PREFIX "\\\\?\\"
if (strncmp(path, WIN32_LONG_PATH_PREFIX, 4) == 0) {
int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
- wchar_t* buff = (wchar_t*)malloc(len * sizeof(wchar_t));
- wchar_t* buff2 = (wchar_t*)malloc(len * sizeof(wchar_t));
- FILE* f = NULL;
- if (buff && buff2) {
- MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
- if (_wfullpath(buff2, buff, len) != NULL) {
- f = _wfopen(buff2, (strcmp(mode, "r") == 0) ? L"r" : L"rb");
- }
- free(buff);
- free(buff2);
+ wchar_t* buff = new wchar_t[len];
+ wchar_t* buff2 = new wchar_t[len];
+ MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
+ if (_wfullpath(buff2, buff, len) != NULL) {
+ stream.open(buff2, mode);
}
- return f;
+ delete [] buff;
+ delete [] buff2;
}
+ else
#endif
- return fopen(path, mode);
+ stream.open(path, mode);
}
std::string& u16_u8(std::string& dest, const std::vector<w_char>& src) {
dest.clear();
std::vector<w_char>::const_iterator u2 = src.begin();
std::vector<w_char>::const_iterator u2_max = src.end();
while (u2 < u2_max) {
signed char u8;
@@ -213,17 +212,17 @@ int u8_u16(std::vector<w_char>& dest, co
u2.h = 0xff;
u2.l = 0xfd;
break;
}
case 0xc0:
case 0xd0: { // 2-byte UTF-8 codes
if ((*(u8 + 1) & 0xc0) == 0x80) {
u2.h = (*u8 & 0x1f) >> 2;
- u2.l = (*u8 << 6) + (*(u8 + 1) & 0x3f);
+ u2.l = (static_cast<unsigned char>(*u8) << 6) + (*(u8 + 1) & 0x3f);
++u8;
} else {
HUNSPELL_WARNING(stderr,
"UTF-8 encoding error. Missing continuation byte in "
"%ld. character position:\n%s\n",
static_cast<long>(std::distance(src.begin(), u8)),
src.c_str());
u2.h = 0xff;
@@ -270,44 +269,45 @@ int u8_u16(std::vector<w_char>& dest, co
}
dest.push_back(u2);
++u8;
}
return dest.size();
}
-// strip strings into token based on single char delimiter
-// acts like strsep() but only uses a delim char and not
-// a delim string
-// default delimiter: white space characters
+namespace {
+class is_any_of {
+ public:
+ explicit is_any_of(const std::string& in) : chars(in) {}
+
+ bool operator()(char c) { return chars.find(c) != std::string::npos; }
+
+ private:
+ std::string chars;
+};
+}
-char* mystrsep(char** stringp, const char delim) {
- char* mp = *stringp;
- if (*mp != '\0') {
- char* dp;
- if (delim) {
- dp = strchr(mp, delim);
- } else {
- // don't use isspace() here, the string can be in some random charset
- // that's way different than the locale's
- for (dp = mp; (*dp && *dp != ' ' && *dp != '\t'); dp++)
- ;
- if (!*dp)
- dp = NULL;
- }
- if (dp) {
- *stringp = dp + 1;
- *dp = '\0';
- } else {
- *stringp = mp + strlen(mp);
- }
- return mp;
- }
- return NULL;
+std::string::const_iterator mystrsep(const std::string &str,
+ std::string::const_iterator& start) {
+ std::string::const_iterator end = str.end();
+
+ is_any_of op(" \t");
+ // don't use isspace() here, the string can be in some random charset
+ // that's way different than the locale's
+ std::string::const_iterator sp = start;
+ while (sp != end && op(*sp))
+ ++sp;
+
+ std::string::const_iterator dp = sp;
+ while (dp != end && !op(*dp))
+ ++dp;
+
+ start = dp;
+ return sp;
}
// replaces strdup with ansi version
char* mystrdup(const char* s) {
char* d = NULL;
if (s) {
size_t sl = strlen(s) + 1;
d = (char*)malloc(sl);
@@ -315,270 +315,121 @@ char* mystrdup(const char* s) {
memcpy(d, s, sl);
} else {
HUNSPELL_WARNING(stderr, "Can't allocate memory.\n");
}
}
return d;
}
-// strcat for limited length destination string
-char* mystrcat(char* dest, const char* st, int max) {
- int len;
- int len2;
- if (dest == NULL || st == NULL)
- return dest;
- len = strlen(dest);
- len2 = strlen(st);
- if (len + len2 + 1 > max)
- return dest;
- strcpy(dest + len, st);
- return dest;
-}
-
// remove cross-platform text line end characters
-void mychomp(char* s) {
- size_t k = strlen(s);
- if ((k > 0) && ((*(s + k - 1) == '\r') || (*(s + k - 1) == '\n')))
- *(s + k - 1) = '\0';
- if ((k > 1) && (*(s + k - 2) == '\r'))
- *(s + k - 2) = '\0';
+void mychomp(std::string& s) {
+ size_t k = s.size();
+ size_t newsize = k;
+ if ((k > 0) && ((s[k - 1] == '\r') || (s[k - 1] == '\n')))
+ --newsize;
+ if ((k > 1) && (s[k - 2] == '\r'))
+ --newsize;
+ s.resize(newsize);
}
// break text to lines
-// return number of lines
-int line_tok(const char* text, char*** lines, char breakchar) {
- int linenum = 0;
- if (!text) {
- return linenum;
- }
- char* dup = mystrdup(text);
- char* p = strchr(dup, breakchar);
- while (p) {
- linenum++;
- *p = '\0';
- p++;
- p = strchr(p, breakchar);
- }
- linenum++;
- *lines = (char**)malloc(linenum * sizeof(char*));
- if (!(*lines)) {
- free(dup);
- return 0;
+std::vector<std::string> line_tok(const std::string& text, char breakchar) {
+ std::vector<std::string> ret;
+ if (text.empty()) {
+ return ret;
}
- p = dup;
- int l = 0;
- for (int i = 0; i < linenum; i++) {
- if (*p != '\0') {
- (*lines)[l] = mystrdup(p);
- if (!(*lines)[l]) {
- for (i = 0; i < l; i++)
- free((*lines)[i]);
- free(dup);
- return 0;
- }
- l++;
+ std::stringstream ss(text);
+ std::string tok;
+ while(std::getline(ss, tok, breakchar)) {
+ if (!tok.empty()) {
+ ret.push_back(tok);
}
- p += strlen(p) + 1;
}
- free(dup);
- if (!l) {
- free(*lines);
- *lines = NULL;
- }
- return l;
+
+ return ret;
}
// uniq line in place
-char* line_uniq(char* text, char breakchar) {
- char** lines;
- int linenum = line_tok(text, &lines, breakchar);
- int i;
- strcpy(text, lines[0]);
- for (i = 1; i < linenum; i++) {
- int dup = 0;
- for (int j = 0; j < i; j++) {
- if (strcmp(lines[i], lines[j]) == 0) {
- dup = 1;
+void line_uniq(std::string& text, char breakchar)
+{
+ std::vector<std::string> lines = line_tok(text, breakchar);
+ text.clear();
+ if (lines.empty()) {
+ return;
+ }
+ text = lines[0];
+ for (size_t i = 1; i < lines.size(); ++i) {
+ bool dup = false;
+ for (size_t j = 0; j < i; ++j) {
+ if (lines[i] == lines[j]) {
+ dup = true;
break;
}
}
if (!dup) {
- if ((i > 1) || (*(lines[0]) != '\0')) {
- sprintf(text + strlen(text), "%c", breakchar);
- }
- strcat(text, lines[i]);
+ if (!text.empty())
+ text.push_back(breakchar);
+ text.append(lines[i]);
}
}
- for (i = 0; i < linenum; i++) {
- free(lines[i]);
- }
- free(lines);
- return text;
}
// uniq and boundary for compound analysis: "1\n\2\n\1" -> " ( \1 | \2 ) "
-char* line_uniq_app(char** text, char breakchar) {
- if (!strchr(*text, breakchar)) {
- return *text;
+void line_uniq_app(std::string& text, char breakchar) {
+ if (text.find(breakchar) == std::string::npos) {
+ return;
}
- char** lines;
- int i;
- int linenum = line_tok(*text, &lines, breakchar);
- int dup = 0;
- for (i = 0; i < linenum; i++) {
- for (int j = 0; j < (i - 1); j++) {
- if (strcmp(lines[i], lines[j]) == 0) {
- *(lines[i]) = '\0';
- dup++;
+ std::vector<std::string> lines = line_tok(text, breakchar);
+ text.clear();
+ if (lines.empty()) {
+ return;
+ }
+ text = lines[0];
+ for (size_t i = 1; i < lines.size(); ++i) {
+ bool dup = false;
+ for (size_t j = 0; j < i; ++j) {
+ if (lines[i] == lines[j]) {
+ dup = true;
break;
}
}
- }
- if ((linenum - dup) == 1) {
- strcpy(*text, lines[0]);
- freelist(&lines, linenum);
- return *text;
+ if (!dup) {
+ if (!text.empty())
+ text.push_back(breakchar);
+ text.append(lines[i]);
+ }
}
- char* newtext = (char*)malloc(strlen(*text) + 2 * linenum + 3 + 1);
- if (newtext) {
- free(*text);
- *text = newtext;
- } else {
- freelist(&lines, linenum);
- return *text;
+
+ if (lines.size() == 1) {
+ text = lines[0];
+ return;
}
- strcpy(*text, " ( ");
- for (i = 0; i < linenum; i++)
- if (*(lines[i])) {
- sprintf(*text + strlen(*text), "%s%s", lines[i], " | ");
- }
- (*text)[strlen(*text) - 2] = ')'; // " ) "
- freelist(&lines, linenum);
- return *text;
+
+ text.assign(" ( ");
+ for (size_t i = 0; i < lines.size(); ++i) {
+ text.append(lines[i]);
+ text.append(" | ");
+ }
+ text[text.size() - 2] = ')'; // " ) "
}
// append s to ends of every lines in text
std::string& strlinecat(std::string& str, const std::string& apd) {
size_t pos = 0;
while ((pos = str.find('\n', pos)) != std::string::npos) {
str.insert(pos, apd);
pos += apd.length() + 1;
}
str.append(apd);
return str;
}
-// morphcmp(): compare MORPH_DERI_SFX, MORPH_INFL_SFX and MORPH_TERM_SFX fields
-// in the first line of the inputs
-// return 0, if inputs equal
-// return 1, if inputs may equal with a secondary suffix
-// otherwise return -1
-int morphcmp(const char* s, const char* t) {
- int se = 0;
- int te = 0;
- const char* sl;
- const char* tl;
- const char* olds;
- const char* oldt;
- if (!s || !t)
- return 1;
- olds = s;
- sl = strchr(s, '\n');
- s = strstr(s, MORPH_DERI_SFX);
- if (!s || (sl && sl < s))
- s = strstr(olds, MORPH_INFL_SFX);
- if (!s || (sl && sl < s)) {
- s = strstr(olds, MORPH_TERM_SFX);
- olds = NULL;
- }
- oldt = t;
- tl = strchr(t, '\n');
- t = strstr(t, MORPH_DERI_SFX);
- if (!t || (tl && tl < t))
- t = strstr(oldt, MORPH_INFL_SFX);
- if (!t || (tl && tl < t)) {
- t = strstr(oldt, MORPH_TERM_SFX);
- oldt = NULL;
- }
- while (s && t && (!sl || sl > s) && (!tl || tl > t)) {
- s += MORPH_TAG_LEN;
- t += MORPH_TAG_LEN;
- se = 0;
- te = 0;
- while ((*s == *t) && !se && !te) {
- s++;
- t++;
- switch (*s) {
- case ' ':
- case '\n':
- case '\t':
- case '\0':
- se = 1;
- }
- switch (*t) {
- case ' ':
- case '\n':
- case '\t':
- case '\0':
- te = 1;
- }
- }
- if (!se || !te) {
- // not terminal suffix difference
- if (olds)
- return -1;
- return 1;
- }
- olds = s;
- s = strstr(s, MORPH_DERI_SFX);
- if (!s || (sl && sl < s))
- s = strstr(olds, MORPH_INFL_SFX);
- if (!s || (sl && sl < s)) {
- s = strstr(olds, MORPH_TERM_SFX);
- olds = NULL;
- }
- oldt = t;
- t = strstr(t, MORPH_DERI_SFX);
- if (!t || (tl && tl < t))
- t = strstr(oldt, MORPH_INFL_SFX);
- if (!t || (tl && tl < t)) {
- t = strstr(oldt, MORPH_TERM_SFX);
- oldt = NULL;
- }
- }
- if (!s && !t && se && te)
- return 0;
- return 1;
-}
-
-int get_sfxcount(const char* morph) {
- if (!morph || !*morph)
- return 0;
- int n = 0;
- const char* old = morph;
- morph = strstr(morph, MORPH_DERI_SFX);
- if (!morph)
- morph = strstr(old, MORPH_INFL_SFX);
- if (!morph)
- morph = strstr(old, MORPH_TERM_SFX);
- while (morph) {
- n++;
- old = morph;
- morph = strstr(morph + 1, MORPH_DERI_SFX);
- if (!morph)
- morph = strstr(old + 1, MORPH_INFL_SFX);
- if (!morph)
- morph = strstr(old + 1, MORPH_TERM_SFX);
- }
- return n;
-}
-
int fieldlen(const char* r) {
int n = 0;
while (r && *r != ' ' && *r != '\t' && *r != '\0' && *r != '\n') {
r++;
n++;
}
return n;
}
@@ -610,87 +461,44 @@ std::string& mystrrep(std::string& str,
size_t pos = 0;
while ((pos = str.find(search, pos)) != std::string::npos) {
str.replace(pos, search.length(), replace);
pos += replace.length();
}
return str;
}
-char* mystrrep(char* word, const char* pat, const char* rep) {
- char* pos = strstr(word, pat);
- if (pos) {
- int replen = strlen(rep);
- int patlen = strlen(pat);
- while (pos) {
- if (replen < patlen) {
- char* end = word + strlen(word);
- char* next = pos + replen;
- char* prev = pos + strlen(pat);
- for (; prev < end;* next = *prev, prev++, next++)
- ;
- *next = '\0';
- } else if (replen > patlen) {
- char* end = pos + patlen;
- char* next = word + strlen(word) + replen - patlen;
- char* prev = next - replen + patlen;
- for (; prev >= end;* next = *prev, prev--, next--)
- ;
- }
- strncpy(pos, rep, replen);
- pos = strstr(word, pat);
- }
- }
- return word;
-}
-
// reverse word
size_t reverseword(std::string& word) {
std::reverse(word.begin(), word.end());
return word.size();
}
// reverse word
size_t reverseword_utf(std::string& word) {
std::vector<w_char> w;
u8_u16(w, word);
std::reverse(w.begin(), w.end());
u16_u8(word, w);
return w.size();
}
-int uniqlist(char** list, int n) {
- int i;
- if (n < 2)
- return n;
- for (i = 0; i < n; i++) {
- for (int j = 0; j < i; j++) {
- if (list[j] && list[i] && (strcmp(list[j], list[i]) == 0)) {
- free(list[i]);
- list[i] = NULL;
- break;
- }
- }
+void uniqlist(std::vector<std::string>& list) {
+ if (list.size() < 2)
+ return;
+
+ std::vector<std::string> ret;
+ ret.push_back(list[0]);
+
+ for (size_t i = 1; i < list.size(); ++i) {
+ if (std::find(ret.begin(), ret.end(), list[i]) == ret.end())
+ ret.push_back(list[i]);
}
- int m = 1;
- for (i = 1; i < n; i++)
- if (list[i]) {
- list[m] = list[i];
- m++;
- }
- return m;
-}
-void freelist(char*** list, int n) {
- if (list && *list) {
- for (int i = 0; i < n; i++)
- free((*list)[i]);
- free(*list);
- *list = NULL;
- }
+ list.swap(ret);
}
namespace {
unsigned char cupper(const struct cs_info* csconv, int nIndex) {
if (nIndex < 0 || nIndex > 255)
return nIndex;
return csconv[nIndex].cupper;
}
@@ -2452,60 +2260,60 @@ static void toAsciiLowerAndRemoveNonAlph
}
pName++;
}
*pBuf = '\0';
}
-struct cs_info* get_current_cs(const char* es) {
- char* normalized_encoding = new char[strlen(es) + 1];
- toAsciiLowerAndRemoveNonAlphanumeric(es, normalized_encoding);
+struct cs_info* get_current_cs(const std::string& es) {
+ char* normalized_encoding = new char[es.size() + 1];
+ toAsciiLowerAndRemoveNonAlphanumeric(es.c_str(), normalized_encoding);
struct cs_info* ccs = NULL;
int n = sizeof(encds) / sizeof(encds[0]);
for (int i = 0; i < n; i++) {
if (strcmp(normalized_encoding, encds[i].enc_name) == 0) {
ccs = encds[i].cs_table;
break;
}
}
delete[] normalized_encoding;
if (!ccs) {
HUNSPELL_WARNING(stderr,
- "error: unknown encoding %s: using %s as fallback\n", es,
+ "error: unknown encoding %s: using %s as fallback\n", es.c_str(),
encds[0].enc_name);
ccs = encds[0].cs_table;
}
return ccs;
}
#else
// XXX This function was rewritten for mozilla. Instead of storing the
// conversion tables static in this file, create them when needed
// with help the mozilla backend.
-struct cs_info* get_current_cs(const char* es) {
+struct cs_info* get_current_cs(const std::string& es) {
struct cs_info* ccs = new cs_info[256];
// Initialze the array with dummy data so that we wouldn't need
// to return null in case of failures.
for (int i = 0; i <= 0xff; ++i) {
ccs[i].ccase = false;
ccs[i].clower = i;
ccs[i].cupper = i;
}
nsCOMPtr<nsIUnicodeEncoder> encoder;
nsCOMPtr<nsIUnicodeDecoder> decoder;
nsresult rv;
- nsAutoCString label(es);
+ nsAutoCString label(es.c_str());
nsAutoCString encoding;
if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
return ccs;
}
encoder = EncodingUtils::EncoderForEncoding(encoding);
decoder = EncodingUtils::DecoderForEncoding(encoding);
encoder->SetOutputErrorBehavior(encoder->kOnError_Signal, nullptr, '?');
decoder->SetInputErrorBehavior(decoder->kOnError_Signal);
@@ -2560,31 +2368,28 @@ struct cs_info* get_current_cs(const cha
ccs[i].ccase = false;
}
return ccs;
}
#endif
// primitive isalpha() replacement for tokenization
-char* get_casechars(const char* enc) {
+std::string get_casechars(const char* enc) {
struct cs_info* csconv = get_current_cs(enc);
- char expw[MAXLNLEN];
- char* p = expw;
- for (int i = 0; i <= 255; i++) {
+ std::string expw;
+ for (int i = 0; i <= 255; ++i) {
if (cupper(csconv, i) != clower(csconv, i)) {
- *p = static_cast<char>(i);
- p++;
+ expw.push_back(static_cast<char>(i));
}
}
- *p = '\0';
#ifdef MOZILLA_CLIENT
delete[] csconv;
#endif
- return mystrdup(expw);
+ return expw;
}
// language to encoding default map
struct lang_map {
const char* lang;
int num;
};
@@ -2601,57 +2406,52 @@ static struct lang_map lang2enc[] =
{"hu", LANG_hu}, {"hu_HU", LANG_hu}, // for back-compatibility
{"it", LANG_it}, {"la", LANG_la},
{"lv", LANG_lv}, {"nl", LANG_nl},
{"pl", LANG_pl}, {"pt", LANG_pt},
{"sv", LANG_sv}, {"tr", LANG_tr},
{"tr_TR", LANG_tr}, // for back-compatibility
{"ru", LANG_ru}, {"uk", LANG_uk}};
-int get_lang_num(const char* lang) {
+int get_lang_num(const std::string& lang) {
int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
for (int i = 0; i < n; i++) {
- if (strcmp(lang, lang2enc[i].lang) == 0) {
+ if (strcmp(lang.c_str(), lang2enc[i].lang) == 0) {
return lang2enc[i].num;
}
}
return LANG_xx;
}
#ifndef OPENOFFICEORG
#ifndef MOZILLA_CLIENT
-int initialize_utf_tbl() {
+void initialize_utf_tbl() {
utf_tbl_count++;
if (utf_tbl)
- return 0;
- utf_tbl = (unicode_info2*)malloc(CONTSIZE * sizeof(unicode_info2));
- if (utf_tbl) {
- size_t j;
- for (j = 0; j < CONTSIZE; j++) {
- utf_tbl[j].cletter = 0;
- utf_tbl[j].clower = (unsigned short)j;
- utf_tbl[j].cupper = (unsigned short)j;
- }
- for (j = 0; j < UTF_LST_LEN; j++) {
- utf_tbl[utf_lst[j].c].cletter = 1;
- utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
- utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
- }
- } else
- return 1;
- return 0;
+ return;
+ utf_tbl = new unicode_info2[CONTSIZE];
+ for (size_t j = 0; j < CONTSIZE; ++j) {
+ utf_tbl[j].cletter = 0;
+ utf_tbl[j].clower = (unsigned short)j;
+ utf_tbl[j].cupper = (unsigned short)j;
+ }
+ for (size_t j = 0; j < UTF_LST_LEN; ++j) {
+ utf_tbl[utf_lst[j].c].cletter = 1;
+ utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
+ utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
+ }
}
#endif
#endif
void free_utf_tbl() {
if (utf_tbl_count > 0)
utf_tbl_count--;
if (utf_tbl && (utf_tbl_count == 0)) {
- free(utf_tbl);
+ delete[] utf_tbl;
utf_tbl = NULL;
}
}
unsigned short unicodetoupper(unsigned short c, int langnum) {
// In Azeri and Turkish, I and i dictinct letters:
// There are a dotless lower case i pair of upper `I',
// and an upper I with dot pair of lower `i'.
@@ -2770,81 +2570,63 @@ size_t remove_ignored_chars_utf(std::str
w2.push_back(w[i]);
}
}
u16_u8(word, w2);
return w2.size();
}
-namespace {
-class is_any_of {
- public:
- is_any_of(const std::string& in) : chars(in) {}
-
- bool operator()(char c) { return chars.find(c) != std::string::npos; }
-
- private:
- std::string chars;
-};
-}
-
// strip all ignored characters in the string
size_t remove_ignored_chars(std::string& word,
const std::string& ignored_chars) {
word.erase(
std::remove_if(word.begin(), word.end(), is_any_of(ignored_chars)),
word.end());
return word.size();
}
-int parse_string(char* line, char** out, int ln) {
- char* tp = line;
- char* piece;
+bool parse_string(const std::string& line, std::string& out, int ln) {
+ if (!out.empty()) {
+ HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
+ return false;
+ }
int i = 0;
int np = 0;
- if (*out) {
- HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
- return 1;
- }
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- np++;
- break;
- }
- case 1: {
- *out = mystrdup(piece);
- if (!*out)
- return 1;
- np++;
- break;
- }
- default:
- break;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
}
- i++;
+ case 1: {
+ out.assign(start_piece, iter);
+ np++;
+ break;
+ }
+ default:
+ break;
}
- // free(piece);
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", ln);
- return 1;
+ return false;
}
- return 0;
+ return true;
}
-bool parse_array(char* line,
- char** out,
+bool parse_array(const std::string& line,
+ std::string& out,
std::vector<w_char>& out_utf16,
int utf8,
int ln) {
- if (parse_string(line, out, ln))
+ if (!parse_string(line, out, ln))
return false;
if (utf8) {
- u8_u16(out_utf16, *out);
+ u8_u16(out_utf16, out);
std::sort(out_utf16.begin(), out_utf16.end());
}
return true;
}
--- a/extensions/spellcheck/hunspell/src/csutil.hxx
+++ b/extensions/spellcheck/hunspell/src/csutil.hxx
@@ -66,23 +66,24 @@
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef __CSUTILHXX__
-#define __CSUTILHXX__
+#ifndef CSUTIL_HXX_
+#define CSUTIL_HXX_
#include "hunvisapi.h"
// First some base level utility routines
+#include <fstream>
#include <string>
#include <vector>
#include <string.h>
#include "w_char.hxx"
#include "htypes.hxx"
#ifdef MOZILLA_CLIENT
#include "nscore.h" // for mozalloc headers
@@ -122,96 +123,89 @@
#define MSEP_REC '\n'
#define MSEP_ALT '\v'
// default flags
#define DEFAULTFLAGS 65510
#define FORBIDDENWORD 65510
#define ONLYUPCASEFLAG 65511
-// fopen or optional _wfopen to fix long pathname problem of WIN32
-LIBHUNSPELL_DLL_EXPORTED FILE* myfopen(const char* path, const char* mode);
+// fix long pathname problem of WIN32 by using w_char std::fstream::open override
+LIBHUNSPELL_DLL_EXPORTED void myopen(std::ifstream& stream, const char* path,
+ std::ios_base::openmode mode);
// convert UTF-16 characters to UTF-8
LIBHUNSPELL_DLL_EXPORTED std::string& u16_u8(std::string& dest,
const std::vector<w_char>& src);
// convert UTF-8 characters to UTF-16
LIBHUNSPELL_DLL_EXPORTED int u8_u16(std::vector<w_char>& dest,
const std::string& src);
// remove end of line char(s)
-LIBHUNSPELL_DLL_EXPORTED void mychomp(char* s);
+LIBHUNSPELL_DLL_EXPORTED void mychomp(std::string& s);
// duplicate string
LIBHUNSPELL_DLL_EXPORTED char* mystrdup(const char* s);
-// strcat for limited length destination string
-LIBHUNSPELL_DLL_EXPORTED char* mystrcat(char* dest, const char* st, int max);
-
// parse into tokens with char delimiter
-LIBHUNSPELL_DLL_EXPORTED char* mystrsep(char** sptr, const char delim);
+LIBHUNSPELL_DLL_EXPORTED std::string::const_iterator mystrsep(const std::string &str,
+ std::string::const_iterator& start);
// replace pat by rep in word and return word
-LIBHUNSPELL_DLL_EXPORTED char* mystrrep(char* word,
- const char* pat,
- const char* rep);
LIBHUNSPELL_DLL_EXPORTED std::string& mystrrep(std::string& str,
const std::string& search,
const std::string& replace);
// append s to ends of every lines in text
LIBHUNSPELL_DLL_EXPORTED std::string& strlinecat(std::string& str,
const std::string& apd);
// tokenize into lines with new line
-LIBHUNSPELL_DLL_EXPORTED int line_tok(const char* text,
- char*** lines,
- char breakchar);
+LIBHUNSPELL_DLL_EXPORTED std::vector<std::string> line_tok(const std::string& text,
+ char breakchar);
// tokenize into lines with new line and uniq in place
-LIBHUNSPELL_DLL_EXPORTED char* line_uniq(char* text, char breakchar);
-LIBHUNSPELL_DLL_EXPORTED char* line_uniq_app(char** text, char breakchar);
+LIBHUNSPELL_DLL_EXPORTED void line_uniq(std::string& text, char breakchar);
+
+LIBHUNSPELL_DLL_EXPORTED void line_uniq_app(std::string& text, char breakchar);
// reverse word
LIBHUNSPELL_DLL_EXPORTED size_t reverseword(std::string& word);
// reverse word
LIBHUNSPELL_DLL_EXPORTED size_t reverseword_utf(std::string&);
// remove duplicates
-LIBHUNSPELL_DLL_EXPORTED int uniqlist(char** list, int n);
-
-// free character array list
-LIBHUNSPELL_DLL_EXPORTED void freelist(char*** list, int n);
+LIBHUNSPELL_DLL_EXPORTED void uniqlist(std::vector<std::string>& list);
// character encoding information
struct cs_info {
unsigned char ccase;
unsigned char clower;
unsigned char cupper;
};
-LIBHUNSPELL_DLL_EXPORTED int initialize_utf_tbl();
+LIBHUNSPELL_DLL_EXPORTED void initialize_utf_tbl();
LIBHUNSPELL_DLL_EXPORTED void free_utf_tbl();
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetoupper(unsigned short c,
int langnum);
LIBHUNSPELL_DLL_EXPORTED w_char upper_utf(w_char u, int langnum);
LIBHUNSPELL_DLL_EXPORTED w_char lower_utf(w_char u, int langnum);
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c,
int langnum);
LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c);
-LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const char* es);
+LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const std::string& es);
// get language identifiers of language codes
-LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const char* lang);
+LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const std::string& lang);
// get characters of the given 8bit encoding with lower- and uppercase forms
-LIBHUNSPELL_DLL_EXPORTED char* get_casechars(const char* enc);
+LIBHUNSPELL_DLL_EXPORTED std::string get_casechars(const char* enc);
// convert std::string to all caps
LIBHUNSPELL_DLL_EXPORTED std::string& mkallcap(std::string& s,
const struct cs_info* csconv);
// convert null terminated string to all little
LIBHUNSPELL_DLL_EXPORTED std::string& mkallsmall(std::string& s,
const struct cs_info* csconv);
@@ -251,34 +245,32 @@ LIBHUNSPELL_DLL_EXPORTED size_t remove_i
std::string& word,
const std::vector<w_char>& ignored_chars);
// strip all ignored characters in the string
LIBHUNSPELL_DLL_EXPORTED size_t remove_ignored_chars(
std::string& word,
const std::string& ignored_chars);
-LIBHUNSPELL_DLL_EXPORTED int parse_string(char* line, char** out, int ln);
+LIBHUNSPELL_DLL_EXPORTED bool parse_string(const std::string& line,
+ std::string& out,
+ int ln);
-LIBHUNSPELL_DLL_EXPORTED bool parse_array(char* line,
- char** out,
+LIBHUNSPELL_DLL_EXPORTED bool parse_array(const std::string& line,
+ std::string& out,
std::vector<w_char>& out_utf16,
int utf8,
int ln);
LIBHUNSPELL_DLL_EXPORTED int fieldlen(const char* r);
LIBHUNSPELL_DLL_EXPORTED bool copy_field(std::string& dest,
const std::string& morph,
const std::string& var);
-LIBHUNSPELL_DLL_EXPORTED int morphcmp(const char* s, const char* t);
-
-LIBHUNSPELL_DLL_EXPORTED int get_sfxcount(const char* morph);
-
// conversion function for protected memory
LIBHUNSPELL_DLL_EXPORTED void store_pointer(char* dest, char* source);
// conversion function for protected memory
LIBHUNSPELL_DLL_EXPORTED char* get_stored_pointer(const char* s);
// hash entry macros
LIBHUNSPELL_DLL_EXPORTED inline char* HENTRY_DATA(struct hentry* h) {
--- a/extensions/spellcheck/hunspell/src/filemgr.cxx
+++ b/extensions/spellcheck/hunspell/src/filemgr.cxx
@@ -81,40 +81,40 @@
int FileMgr::fail(const char* err, const char* par) {
fprintf(stderr, err, par);
return -1;
}
FileMgr::FileMgr(const char* file, const char* key) : hin(NULL), linenum(0) {
in[0] = '\0';
- fin = myfopen(file, "r");
- if (!fin) {
+ myopen(fin, file, std::ios_base::in);
+ if (!fin.is_open()) {
// check hzipped file
std::string st(file);
st.append(HZIP_EXTENSION);
hin = new Hunzip(st.c_str(), key);
}
- if (!fin && !hin)
+ if (!fin.is_open() && !hin->is_open())
fail(MSG_OPEN, file);
}
FileMgr::~FileMgr() {
- if (fin)
- fclose(fin);
- if (hin)
- delete hin;
+ delete hin;
}
-char* FileMgr::getline() {
- const char* l;
- linenum++;
- if (fin)
- return fgets(in, BUFSIZE - 1, fin);
- if (hin && ((l = hin->getline()) != NULL))
- return strcpy(in, l);
- linenum--;
- return NULL;
+bool FileMgr::getline(std::string& dest) {
+ bool ret = false;
+ ++linenum;
+ if (fin.is_open()) {
+ ret = static_cast<bool>(std::getline(fin, dest));
+ } else if (hin->is_open()) {
+ ret = hin->getline(dest);
+ }
+ if (!ret) {
+ --linenum;
+ }
+ return ret;
}
int FileMgr::getlinenum() {
return linenum;
}
--- a/extensions/spellcheck/hunspell/src/filemgr.hxx
+++ b/extensions/spellcheck/hunspell/src/filemgr.hxx
@@ -67,35 +67,35 @@
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* file manager class - read lines of files [filename] OR [filename.hz] */
-#ifndef _FILEMGR_HXX_
-#define _FILEMGR_HXX_
-
-#include "hunvisapi.h"
+#ifndef FILEMGR_HXX_
+#define FILEMGR_HXX_
#include "hunzip.hxx"
#include <stdio.h>
+#include <string>
+#include <fstream>
-class LIBHUNSPELL_DLL_EXPORTED FileMgr {
+class FileMgr {
private:
FileMgr(const FileMgr&);
FileMgr& operator=(const FileMgr&);
protected:
- FILE* fin;
+ std::ifstream fin;
Hunzip* hin;
char in[BUFSIZE + 50]; // input buffer
int fail(const char* err, const char* par);
int linenum;
public:
FileMgr(const char* filename, const char* key = NULL);
~FileMgr();
- char* getline();
+ bool getline(std::string&);
int getlinenum();
};
#endif
--- a/extensions/spellcheck/hunspell/src/hashmgr.cxx
+++ b/extensions/spellcheck/hunspell/src/hashmgr.cxx
@@ -93,30 +93,29 @@ HashMgr::HashMgr(const char* tpath, cons
forbiddenword(FORBIDDENWORD) // forbidden word signing flag
,
numaliasf(0),
aliasf(NULL),
aliasflen(0),
numaliasm(0),
aliasm(NULL) {
langnum = 0;
- lang = NULL;
- enc = NULL;
csconv = 0;
- ignorechars = NULL;
load_config(apath, key);
int ec = load_tables(tpath, key);
if (ec) {
/* error condition - what should we do here */
HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n", ec);
- if (tableptr) {
- free(tableptr);
- tableptr = NULL;
+ free(tableptr);
+ //keep tablesize to 1 to fix possible division with zero
+ tablesize = 1;
+ tableptr = (struct hentry**)calloc(tablesize, sizeof(struct hentry*));
+ if (!tableptr) {
+ tablesize = 0;
}
- tablesize = 0;
}
}
HashMgr::~HashMgr() {
if (tableptr) {
// now pass through hash table freeing up everything
// go through column by column of the table
for (int i = 0; i < tablesize; i++) {
@@ -154,24 +153,16 @@ HashMgr::~HashMgr() {
#ifndef OPENOFFICEORG
#ifndef MOZILLA_CLIENT
if (utf8)
free_utf_tbl();
#endif
#endif
- if (enc)
- free(enc);
- if (lang)
- free(lang);
-
- if (ignorechars)
- free(ignorechars);
-
#ifdef MOZILLA_CLIENT
delete[] csconv;
#endif
}
// lookup a root word in the hashtable
struct hentry* HashMgr::lookup(const char* word) const {
@@ -184,91 +175,91 @@ struct hentry* HashMgr::lookup(const cha
if (strcmp(word, dp->word) == 0)
return dp;
}
}
return NULL;
}
// add a word to the hash table (private)
-int HashMgr::add_word(const char* word,
- int wbl,
+int HashMgr::add_word(const std::string& in_word,
int wcl,
unsigned short* aff,
int al,
- const char* desc,
+ const std::string* in_desc,
bool onlyupcase) {
+ const std::string* word = &in_word;
+ const std::string* desc = in_desc;
std::string *word_copy = NULL;
std::string *desc_copy = NULL;
- if (ignorechars || complexprefixes) {
- word_copy = new std::string(word, wbl);
+ if (!ignorechars.empty() || complexprefixes) {
+ word_copy = new std::string(in_word);
- if (ignorechars != NULL) {
+ if (!ignorechars.empty()) {
if (utf8) {
wcl = remove_ignored_chars_utf(*word_copy, ignorechars_utf16);
} else {
remove_ignored_chars(*word_copy, ignorechars);
}
}
if (complexprefixes) {
if (utf8)
wcl = reverseword_utf(*word_copy);
else
reverseword(*word_copy);
- if (desc && !aliasm) {
- desc_copy = new std::string(desc);
+ if (in_desc && !aliasm) {
+ desc_copy = new std::string(*in_desc);
if (complexprefixes) {
if (utf8)
reverseword_utf(*desc_copy);
else
reverseword(*desc_copy);
}
- desc = desc_copy->c_str();
+ desc = desc_copy;
}
}
- wbl = word_copy->size();
- word = word_copy->c_str();
+ word = word_copy;
}
bool upcasehomonym = false;
- int descl = desc ? (aliasm ? sizeof(char*) : strlen(desc) + 1) : 0;
+ int descl = desc ? (aliasm ? sizeof(char*) : desc->size() + 1) : 0;
// variable-length hash record with word and optional fields
struct hentry* hp =
- (struct hentry*)malloc(sizeof(struct hentry) + wbl + descl);
+ (struct hentry*)malloc(sizeof(struct hentry) + word->size() + descl);
if (!hp) {
delete desc_copy;
delete word_copy;
return 1;
}
char* hpw = hp->word;
- strcpy(hpw, word);
+ strcpy(hpw, word->c_str());
int i = hash(hpw);
- hp->blen = (unsigned char)wbl;
+ hp->blen = (unsigned char)word->size();
hp->clen = (unsigned char)wcl;
hp->alen = (short)al;
hp->astr = aff;
hp->next = NULL;
hp->next_homonym = NULL;
// store the description string or its pointer
if (desc) {
hp->var = H_OPT;
if (aliasm) {
hp->var += H_OPT_ALIASM;
- store_pointer(hpw + wbl + 1, get_aliasm(atoi(desc)));
+ store_pointer(hpw + word->size() + 1, get_aliasm(atoi(desc->c_str())));
} else {
- strcpy(hpw + wbl + 1, desc);
+ strcpy(hpw + word->size() + 1, desc->c_str());
}
if (strstr(HENTRY_DATA(hp), MORPH_PHON))
hp->var += H_OPT_PHON;
} else
hp->var = 0;
struct hentry* dp = tableptr[i];
if (!dp) {
@@ -329,17 +320,17 @@ int HashMgr::add_word(const char* word,
delete word_copy;
return 0;
}
int HashMgr::add_hidden_capitalized_word(const std::string& word,
int wcl,
unsigned short* flags,
int flagslen,
- char* dp,
+ const std::string* dp,
int captype) {
if (flags == NULL)
flagslen = 0;
// add inner capitalized forms to handle the following allcap forms:
// Mixed caps: OpenOffice.org -> OPENOFFICE.ORG
// Allcaps with suffixes: CIA's -> CIA'S
if (((captype == HUHCAP) || (captype == HUHINITCAP) ||
@@ -354,22 +345,22 @@ int HashMgr::add_hidden_capitalized_word
flags2[flagslen] = ONLYUPCASEFLAG;
if (utf8) {
std::string st;
std::vector<w_char> w;
u8_u16(w, word);
mkallsmall_utf(w, langnum);
mkinitcap_utf(w, langnum);
u16_u8(st, w);
- return add_word(st.c_str(), st.size(), wcl, flags2, flagslen + 1, dp, true);
+ return add_word(st, wcl, flags2, flagslen + 1, dp, true);
} else {
std::string new_word(word);
mkallsmall(new_word, csconv);
mkinitcap(new_word, csconv);
- int ret = add_word(new_word.c_str(), new_word.size(), wcl, flags2, flagslen + 1, dp, true);
+ int ret = add_word(new_word, wcl, flags2, flagslen + 1, dp, true);
return ret;
}
}
return 0;
}
// detect captype and modify word length for UTF-8 encoding
int HashMgr::get_clen_and_captype(const std::string& word, int* captype) {
@@ -381,27 +372,28 @@ int HashMgr::get_clen_and_captype(const
} else {
len = word.size();
*captype = get_captype(word, csconv);
}
return len;
}
// remove word (personal dictionary function for standalone applications)
-int HashMgr::remove(const char* word) {
- struct hentry* dp = lookup(word);
+int HashMgr::remove(const std::string& word) {
+ struct hentry* dp = lookup(word.c_str());
while (dp) {
if (dp->alen == 0 || !TESTAFF(dp->astr, forbiddenword, dp->alen)) {
unsigned short* flags =
(unsigned short*)malloc(sizeof(unsigned short) * (dp->alen + 1));
if (!flags)
return 1;
for (int i = 0; i < dp->alen; i++)
flags[i] = dp->astr[i];
flags[dp->alen] = forbiddenword;
+ free(dp->astr);
dp->astr = flags;
dp->alen++;
std::sort(flags, flags + dp->alen);
}
dp = dp->next_homonym;
}
return 0;
}
@@ -421,56 +413,55 @@ int HashMgr::remove_forbidden_flag(const
if (!flags2)
return 1;
int i, j = 0;
for (i = 0; i < dp->alen; i++) {
if (dp->astr[i] != forbiddenword)
flags2[j++] = dp->astr[i];
}
dp->alen--;
+ free(dp->astr);
dp->astr = flags2; // XXX allowed forbidden words
}
}
dp = dp->next_homonym;
}
return 0;
}
// add a custom dic. word to the hash table (public)
int HashMgr::add(const std::string& word) {
- unsigned short* flags = NULL;
- int al = 0;
if (remove_forbidden_flag(word)) {
int captype;
- int wbl = word.size();
+ int al = 0;
+ unsigned short* flags = NULL;
int wcl = get_clen_and_captype(word, &captype);
- add_word(word.c_str(), wbl, wcl, flags, al, NULL, false);
+ add_word(word, wcl, flags, al, NULL, false);
return add_hidden_capitalized_word(word, wcl, flags, al, NULL,
captype);
}
return 0;
}
-int HashMgr::add_with_affix(const char* word, const char* example) {
+int HashMgr::add_with_affix(const std::string& word, const std::string& example) {
// detect captype and modify word length for UTF-8 encoding
- struct hentry* dp = lookup(example);
+ struct hentry* dp = lookup(example.c_str());
remove_forbidden_flag(word);
if (dp && dp->astr) {
int captype;
- int wbl = strlen(word);
int wcl = get_clen_and_captype(word, &captype);
if (aliasf) {
- add_word(word, wbl, wcl, dp->astr, dp->alen, NULL, false);
+ add_word(word, wcl, dp->astr, dp->alen, NULL, false);
} else {
unsigned short* flags =
(unsigned short*)malloc(dp->alen * sizeof(unsigned short));
if (flags) {
memcpy((void*)flags, (void*)dp->astr,
dp->alen * sizeof(unsigned short));
- add_word(word, wbl, wcl, flags, dp->alen, NULL, false);
+ add_word(word, wcl, flags, dp->alen, NULL, false);
} else
return 1;
}
return add_hidden_capitalized_word(word, wcl, dp->astr,
dp->alen, NULL, captype);
}
return 1;
}
@@ -486,44 +477,36 @@ struct hentry* HashMgr::walk_hashtable(i
}
// null at end and reset to start
col = -1;
return NULL;
}
// load a munched word list and build a hash table on the fly
int HashMgr::load_tables(const char* tpath, const char* key) {
- int al;
- char* ap;
- char* dp;
- char* dp2;
- unsigned short* flags;
- char* ts;
-
// open dictionary file
FileMgr* dict = new FileMgr(tpath, key);
if (dict == NULL)
return 1;
// first read the first line of file to get hash table size */
- if ((ts = dict->getline()) == NULL) {
+ std::string ts;
+ if (!dict->getline(ts)) {
HUNSPELL_WARNING(stderr, "error: empty dic file %s\n", tpath);
delete dict;
return 2;
}
mychomp(ts);
/* remove byte order mark */
- if (strncmp(ts, "\xEF\xBB\xBF", 3) == 0) {
- memmove(ts, ts + 3, strlen(ts + 3) + 1);
- // warning: dic file begins with byte order mark: possible incompatibility
- // with old Hunspell versions
+ if (ts.compare(0, 3, "\xEF\xBB\xBF", 3) == 0) {
+ ts.erase(0, 3);
}
- tablesize = atoi(ts);
+ tablesize = atoi(ts.c_str());
int nExtra = 5 + USERWORD;
if (tablesize <= 0 ||
(tablesize >= (std::numeric_limits<int>::max() - 1 - nExtra) /
int(sizeof(struct hentry*)))) {
HUNSPELL_WARNING(
stderr, "error: line 1: missing or bad word count in the dic file\n");
@@ -539,89 +522,93 @@ int HashMgr::load_tables(const char* tpa
if (!tableptr) {
delete dict;
return 3;
}
// loop through all words on much list and add to hash
// table and create word and affix strings
- while ((ts = dict->getline()) != NULL) {
+ while (dict->getline(ts)) {
mychomp(ts);
// split each line into word and morphological description
- dp = ts;
- while ((dp = strchr(dp, ':')) != NULL) {
- if ((dp > ts + 3) && (*(dp - 3) == ' ' || *(dp - 3) == '\t')) {
- for (dp -= 4; dp >= ts && (*dp == ' ' || *dp == '\t'); dp--)
+ size_t dp_pos = 0;
+ while ((dp_pos = ts.find(':', dp_pos)) != std::string::npos) {
+ if ((dp_pos > 3) && (ts[dp_pos - 3] == ' ' || ts[dp_pos - 3] == '\t')) {
+ for (dp_pos -= 3; dp_pos > 0 && (ts[dp_pos-1] == ' ' || ts[dp_pos-1] == '\t'); --dp_pos)
;
- if (dp < ts) { // missing word
- dp = NULL;
+ if (dp_pos == 0) { // missing word
+ dp_pos = std::string::npos;
} else {
- *(dp + 1) = '\0';
- dp = dp + 2;
+ ++dp_pos;
}
break;
}
- dp++;
+ ++dp_pos;
}
// tabulator is the old morphological field separator
- dp2 = strchr(ts, '\t');
- if (dp2 && (!dp || dp2 < dp)) {
- *dp2 = '\0';
- dp = dp2 + 1;
+ size_t dp2_pos = ts.find('\t');
+ if (dp2_pos != std::string::npos && (dp_pos == std::string::npos || dp2_pos < dp_pos)) {
+ dp_pos = dp2_pos + 1;
+ }
+
+ std::string dp;
+ if (dp_pos != std::string::npos) {
+ dp.assign(ts.substr(dp_pos));
+ ts.resize(dp_pos - 1);
}
// split each line into word and affix char strings
// "\/" signs slash in words (not affix separator)
// "/" at beginning of the line is word character (not affix separator)
- ap = strchr(ts, '/');
- while (ap) {
- if (ap == ts) {
- ap++;
+ size_t ap_pos = ts.find('/');
+ while (ap_pos != std::string::npos) {
+ if (ap_pos == 0) {
+ ++ap_pos;
continue;
- } else if (*(ap - 1) != '\\')
+ } else if (ts[ap_pos - 1] != '\\')
break;
// replace "\/" with "/"
- for (char *sp = ap - 1; *sp; *sp = *(sp + 1), sp++)
- ;
- ap = strchr(ap, '/');
+ ts.erase(ap_pos - 1, 1);
+ ap_pos = ts.find('/', ap_pos);
}
- if (ap) {
- *ap = '\0';
+ unsigned short* flags;
+ int al;
+ if (ap_pos != std::string::npos && ap_pos != ts.size()) {
+ std::string ap(ts.substr(ap_pos + 1));
+ ts.resize(ap_pos);
if (aliasf) {
- int index = atoi(ap + 1);
+ int index = atoi(ap.c_str());
al = get_aliasf(index, &flags, dict);
if (!al) {
HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n",
dict->getlinenum());
- *ap = '\0';
}
} else {
- al = decode_flags(&flags, ap + 1, dict);
+ al = decode_flags(&flags, ap.c_str(), dict);
if (al == -1) {
HUNSPELL_WARNING(stderr, "Can't allocate memory.\n");
delete dict;
return 6;
}
std::sort(flags, flags + al);
}
} else {
al = 0;
- ap = NULL;
flags = NULL;
}
int captype;
- int wbl = strlen(ts);
int wcl = get_clen_and_captype(ts, &captype);
+ const std::string *dp_str = dp.empty() ? NULL : &dp;
// add the word and its index plus its capitalized form optionally
- if (add_word(ts, wbl, wcl, flags, al, dp, false) ||
- add_hidden_capitalized_word(ts, wcl, flags, al, dp, captype)) {
+ if (add_word(ts, wcl, flags, al, dp_str, false) ||
+ add_hidden_capitalized_word(ts, wcl, flags, al, dp_str, captype)) {
delete dict;
return 5;
}
}
delete dict;
return 0;
}
@@ -634,69 +621,67 @@ int HashMgr::hash(const char* word) cons
hv = (hv << 8) | (*word++);
while (*word != 0) {
ROTATE(hv, ROTATE_LEN);
hv ^= (*word++);
}
return (unsigned long)hv % tablesize;
}
-int HashMgr::decode_flags(unsigned short** result, char* flags, FileMgr* af) {
+int HashMgr::decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const {
int len;
- if (*flags == '\0') {
+ if (flags.empty()) {
*result = NULL;
return 0;
}
switch (flag_mode) {
case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
- len = strlen(flags);
+ len = flags.size();
if (len % 2 == 1)
HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n",
af->getlinenum());
len /= 2;
*result = (unsigned short*)malloc(len * sizeof(unsigned short));
if (!*result)
return -1;
for (int i = 0; i < len; i++) {
- (*result)[i] = (((unsigned short)flags[i * 2]) << 8) +
- (unsigned short)flags[i * 2 + 1];
+ (*result)[i] = ((unsigned short)((unsigned char)flags[i * 2]) << 8) +
+ (unsigned char)flags[i * 2 + 1];
}
break;
}
case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521
// 23 233)
- int i;
len = 1;
- char* src = flags;
unsigned short* dest;
- char* p;
- for (p = flags; *p; p++) {
- if (*p == ',')
+ for (size_t i = 0; i < flags.size(); ++i) {
+ if (flags[i] == ',')
len++;
}
*result = (unsigned short*)malloc(len * sizeof(unsigned short));
if (!*result)
return -1;
dest = *result;
- for (p = flags; *p; p++) {
+ const char* src = flags.c_str();
+ for (const char* p = src; *p; p++) {
if (*p == ',') {
- i = atoi(src);
+ int i = atoi(src);
if (i >= DEFAULTFLAGS)
HUNSPELL_WARNING(
stderr, "error: line %d: flag id %d is too large (max: %d)\n",
af->getlinenum(), i, DEFAULTFLAGS - 1);
*dest = (unsigned short)i;
if (*dest == 0)
HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
af->getlinenum());
src = p + 1;
dest++;
}
}
- i = atoi(src);
+ int i = atoi(src);
if (i >= DEFAULTFLAGS)
HUNSPELL_WARNING(stderr,
"error: line %d: flag id %d is too large (max: %d)\n",
af->getlinenum(), i, DEFAULTFLAGS - 1);
*dest = (unsigned short)i;
if (*dest == 0)
HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
af->getlinenum());
@@ -709,60 +694,125 @@ int HashMgr::decode_flags(unsigned short
*result = (unsigned short*)malloc(len * sizeof(unsigned short));
if (!*result)
return -1;
memcpy(*result, &w[0], len * sizeof(short));
break;
}
default: { // Ispell's one-character flags (erfg -> e r f g)
unsigned short* dest;
- len = strlen(flags);
+ len = flags.size();
*result = (unsigned short*)malloc(len * sizeof(unsigned short));
if (!*result)
return -1;
dest = *result;
- for (unsigned char* p = (unsigned char*)flags; *p; p++) {
- *dest = (unsigned short)*p;
+ for (size_t i = 0; i < flags.size(); ++i) {
+ *dest = (unsigned char)flags[i];
dest++;
}
}
}
return len;
}
-unsigned short HashMgr::decode_flag(const char* f) {
+bool HashMgr::decode_flags(std::vector<unsigned short>& result, const std::string& flags, FileMgr* af) const {
+ if (flags.empty()) {
+ return false;
+ }
+ switch (flag_mode) {
+ case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
+ size_t len = flags.size();
+ if (len % 2 == 1)
+ HUNSPELL_WARNING(stderr, "error: line %d: bad flagvector\n",
+ af->getlinenum());
+ len /= 2;
+ result.reserve(result.size() + len);
+ for (size_t i = 0; i < len; ++i) {
+ result.push_back(((unsigned short)((unsigned char)flags[i * 2]) << 8) +
+ (unsigned char)flags[i * 2 + 1]);
+ }
+ break;
+ }
+ case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521
+ // 23 233)
+ const char* src = flags.c_str();
+ for (const char* p = src; *p; p++) {
+ if (*p == ',') {
+ int i = atoi(src);
+ if (i >= DEFAULTFLAGS)
+ HUNSPELL_WARNING(
+ stderr, "error: line %d: flag id %d is too large (max: %d)\n",
+ af->getlinenum(), i, DEFAULTFLAGS - 1);
+ result.push_back((unsigned short)i);
+ if (result.back() == 0)
+ HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
+ af->getlinenum());
+ src = p + 1;
+ }
+ }
+ int i = atoi(src);
+ if (i >= DEFAULTFLAGS)
+ HUNSPELL_WARNING(stderr,
+ "error: line %d: flag id %d is too large (max: %d)\n",
+ af->getlinenum(), i, DEFAULTFLAGS - 1);
+ result.push_back((unsigned short)i);
+ if (result.back() == 0)
+ HUNSPELL_WARNING(stderr, "error: line %d: 0 is wrong flag id\n",
+ af->getlinenum());
+ break;
+ }
+ case FLAG_UNI: { // UTF-8 characters
+ std::vector<w_char> w;
+ u8_u16(w, flags);
+ size_t len = w.size();
+ size_t origsize = result.size();
+ result.resize(origsize + len);
+ memcpy(&result[origsize], &w[0], len * sizeof(short));
+ break;
+ }
+ default: { // Ispell's one-character flags (erfg -> e r f g)
+ result.reserve(flags.size());
+ for (size_t i = 0; i < flags.size(); ++i) {
+ result.push_back((unsigned char)flags[i]);
+ }
+ }
+ }
+ return true;
+}
+
+unsigned short HashMgr::decode_flag(const char* f) const {
unsigned short s = 0;
int i;
switch (flag_mode) {
case FLAG_LONG:
- s = ((unsigned short)f[0] << 8) + (unsigned short)f[1];
+ s = ((unsigned short)((unsigned char)f[0]) << 8) + (unsigned char)f[1];
break;
case FLAG_NUM:
i = atoi(f);
if (i >= DEFAULTFLAGS)
HUNSPELL_WARNING(stderr, "error: flag id %d is too large (max: %d)\n",
i, DEFAULTFLAGS - 1);
s = (unsigned short)i;
break;
case FLAG_UNI: {
std::vector<w_char> w;
u8_u16(w, f);
if (!w.empty())
memcpy(&s, &w[0], 1 * sizeof(short));
break;
}
default:
- s = (unsigned short)*((unsigned char*)f);
+ s = *(unsigned char*)f;
}
if (s == 0)
HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
return s;
}
-char* HashMgr::encode_flag(unsigned short f) {
+char* HashMgr::encode_flag(unsigned short f) const {
if (f == 0)
return mystrdup("(NULL)");
std::string ch;
if (flag_mode == FLAG_LONG) {
ch.push_back((unsigned char)(f >> 8));
ch.push_back((unsigned char)(f - ((f >> 8) << 8)));
} else if (flag_mode == FLAG_NUM) {
std::ostringstream stream;
@@ -775,373 +825,366 @@ char* HashMgr::encode_flag(unsigned shor
} else {
ch.push_back((unsigned char)(f));
}
return mystrdup(ch.c_str());
}
// read in aff file and set flag mode
int HashMgr::load_config(const char* affpath, const char* key) {
- char* line; // io buffers
int firstline = 1;
// open the affix file
FileMgr* afflst = new FileMgr(affpath, key);
if (!afflst) {
HUNSPELL_WARNING(
stderr, "Error - could not open affix description file %s\n", affpath);
return 1;
}
// read in each line ignoring any that do not
// start with a known line type indicator
- while ((line = afflst->getline()) != NULL) {
+ std::string line;
+ while (afflst->getline(line)) {
mychomp(line);
/* remove byte order mark */
if (firstline) {
firstline = 0;
- if (strncmp(line, "\xEF\xBB\xBF", 3) == 0)
- memmove(line, line + 3, strlen(line + 3) + 1);
+ if (line.compare(0, 3, "\xEF\xBB\xBF", 3) == 0) {
+ line.erase(0, 3);
+ }
}
/* parse in the try string */
- if ((strncmp(line, "FLAG", 4) == 0) && isspace(line[4])) {
+ if ((line.compare(0, 4, "FLAG", 4) == 0) && line.size() > 4 && isspace(line[4])) {
if (flag_mode != FLAG_CHAR) {
HUNSPELL_WARNING(stderr,
"error: line %d: multiple definitions of the FLAG "
"affix file parameter\n",
afflst->getlinenum());
}
- if (strstr(line, "long"))
+ if (line.find("long") != std::string::npos)
flag_mode = FLAG_LONG;
- if (strstr(line, "num"))
+ if (line.find("num") != std::string::npos)
flag_mode = FLAG_NUM;
- if (strstr(line, "UTF-8"))
+ if (line.find("UTF-8") != std::string::npos)
flag_mode = FLAG_UNI;
if (flag_mode == FLAG_CHAR) {
HUNSPELL_WARNING(
stderr,
"error: line %d: FLAG needs `num', `long' or `UTF-8' parameter\n",
afflst->getlinenum());
}
}
- if (strncmp(line, "FORBIDDENWORD", 13) == 0) {
- char* st = NULL;
- if (parse_string(line, &st, afflst->getlinenum())) {
+
+ if (line.compare(0, 13, "FORBIDDENWORD", 13) == 0) {
+ std::string st;
+ if (!parse_string(line, st, afflst->getlinenum())) {
delete afflst;
return 1;
}
- forbiddenword = decode_flag(st);
- free(st);
+ forbiddenword = decode_flag(st.c_str());
}
- if (strncmp(line, "SET", 3) == 0) {
- if (parse_string(line, &enc, afflst->getlinenum())) {
+
+ if (line.compare(0, 3, "SET", 3) == 0) {
+ if (!parse_string(line, enc, afflst->getlinenum())) {
delete afflst;
return 1;
}
- if (strcmp(enc, "UTF-8") == 0) {
+ if (enc == "UTF-8") {
utf8 = 1;
#ifndef OPENOFFICEORG
#ifndef MOZILLA_CLIENT
initialize_utf_tbl();
#endif
#endif
} else
csconv = get_current_cs(enc);
}
- if (strncmp(line, "LANG", 4) == 0) {
- if (parse_string(line, &lang, afflst->getlinenum())) {
+
+ if (line.compare(0, 4, "LANG", 4) == 0) {
+ if (!parse_string(line, lang, afflst->getlinenum())) {
delete afflst;
return 1;
}
langnum = get_lang_num(lang);
}
/* parse in the ignored characters (for example, Arabic optional diacritics
* characters */
- if (strncmp(line, "IGNORE", 6) == 0) {
- if (!parse_array(line, &ignorechars, ignorechars_utf16,
+ if (line.compare(0, 6, "IGNORE", 6) == 0) {
+ if (!parse_array(line, ignorechars, ignorechars_utf16,
utf8, afflst->getlinenum())) {
delete afflst;
return 1;
}
}
- if ((strncmp(line, "AF", 2) == 0) && isspace(line[2])) {
- if (parse_aliasf(line, afflst)) {
+ if ((line.compare(0, 2, "AF", 2) == 0) && line.size() > 2 && isspace(line[2])) {
+ if (!parse_aliasf(line, afflst)) {
delete afflst;
return 1;
}
}
- if ((strncmp(line, "AM", 2) == 0) && isspace(line[2])) {
- if (parse_aliasm(line, afflst)) {
+ if ((line.compare(0, 2, "AM", 2) == 0) && line.size() > 2 && isspace(line[2])) {
+ if (!parse_aliasm(line, afflst)) {
delete afflst;
return 1;
}
}
- if (strncmp(line, "COMPLEXPREFIXES", 15) == 0)
+ if (line.compare(0, 15, "COMPLEXPREFIXES", 15) == 0)
complexprefixes = 1;
- if (((strncmp(line, "SFX", 3) == 0) || (strncmp(line, "PFX", 3) == 0)) &&
- isspace(line[3]))
+
+ if (((line.compare(0, 3, "SFX", 3) == 0) ||
+ (line.compare(0, 3, "PFX", 3) == 0)) && line.size() > 3 && isspace(line[3]))
break;
}
+
if (csconv == NULL)
csconv = get_current_cs(SPELL_ENCODING);
delete afflst;
return 0;
}
/* parse in the ALIAS table */
-int HashMgr::parse_aliasf(char* line, FileMgr* af) {
+bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) {
if (numaliasf != 0) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
af->getlinenum());
- return 1;
+ return false;
}
- char* tp = line;
- char* piece;
int i = 0;
int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- np++;
- break;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numaliasf = atoi(std::string(start_piece, iter).c_str());
+ if (numaliasf < 1) {
+ numaliasf = 0;
+ aliasf = NULL;
+ aliasflen = NULL;
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
}
- case 1: {
- numaliasf = atoi(piece);
- if (numaliasf < 1) {
- numaliasf = 0;
- aliasf = NULL;
- aliasflen = NULL;
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- return 1;
- }
- aliasf =
- (unsigned short**)malloc(numaliasf * sizeof(unsigned short*));
- aliasflen =
- (unsigned short*)malloc(numaliasf * sizeof(unsigned short));
- if (!aliasf || !aliasflen) {
- numaliasf = 0;
- if (aliasf)
- free(aliasf);
- if (aliasflen)
- free(aliasflen);
- aliasf = NULL;
- aliasflen = NULL;
- return 1;
- }
- np++;
- break;
+ aliasf =
+ (unsigned short**)malloc(numaliasf * sizeof(unsigned short*));
+ aliasflen =
+ (unsigned short*)malloc(numaliasf * sizeof(unsigned short));
+ if (!aliasf || !aliasflen) {
+ numaliasf = 0;
+ if (aliasf)
+ free(aliasf);
+ if (aliasflen)
+ free(aliasflen);
+ aliasf = NULL;
+ aliasflen = NULL;
+ return false;
}
- default:
- break;
+ np++;
+ break;
}
- i++;
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
numaliasf = 0;
free(aliasf);
free(aliasflen);
aliasf = NULL;
aliasflen = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
/* now parse the numaliasf lines to read in the remainder of the table */
- char* nl;
for (int j = 0; j < numaliasf; j++) {
- if ((nl = af->getline()) == NULL)
- return 1;
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
i = 0;
aliasf[j] = NULL;
aliasflen[j] = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "AF", 2) != 0) {
- numaliasf = 0;
- free(aliasf);
- free(aliasflen);
- aliasf = NULL;
- aliasflen = NULL;
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- return 1;
- }
- break;
+ iter = nl.begin();
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
+ switch (i) {
+ case 0: {
+ if (nl.compare(start_piece - nl.begin(), 2, "AF", 2) != 0) {
+ numaliasf = 0;
+ free(aliasf);
+ free(aliasflen);
+ aliasf = NULL;
+ aliasflen = NULL;
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ return false;
}
- case 1: {
- aliasflen[j] =
- (unsigned short)decode_flags(&(aliasf[j]), piece, af);
- std::sort(aliasf[j], aliasf[j] + aliasflen[j]);
- break;
- }
- default:
- break;
+ break;
}
- i++;
+ case 1: {
+ std::string piece(start_piece, iter);
+ aliasflen[j] =
+ (unsigned short)decode_flags(&(aliasf[j]), piece, af);
+ std::sort(aliasf[j], aliasf[j] + aliasflen[j]);
+ break;
+ }
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(nl, iter);
}
if (!aliasf[j]) {
free(aliasf);
free(aliasflen);
aliasf = NULL;
aliasflen = NULL;
numaliasf = 0;
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- return 1;
+ return false;
}
}
- return 0;
+ return true;
}
-int HashMgr::is_aliasf() {
+int HashMgr::is_aliasf() const {
return (aliasf != NULL);
}
-int HashMgr::get_aliasf(int index, unsigned short** fvec, FileMgr* af) {
+int HashMgr::get_aliasf(int index, unsigned short** fvec, FileMgr* af) const {
if ((index > 0) && (index <= numaliasf)) {
*fvec = aliasf[index - 1];
return aliasflen[index - 1];
}
HUNSPELL_WARNING(stderr, "error: line %d: bad flag alias index: %d\n",
af->getlinenum(), index);
*fvec = NULL;
return 0;
}
/* parse morph alias definitions */
-int HashMgr::parse_aliasm(char* line, FileMgr* af) {
+bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) {
if (numaliasm != 0) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n",
af->getlinenum());
- return 1;
+ return false;
}
- char* tp = line;
- char* piece;
int i = 0;
int np = 0;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- np++;
- break;
+ std::string::const_iterator iter = line.begin();
+ std::string::const_iterator start_piece = mystrsep(line, iter);
+ while (start_piece != line.end()) {
+ switch (i) {
+ case 0: {
+ np++;
+ break;
+ }
+ case 1: {
+ numaliasm = atoi(std::string(start_piece, iter).c_str());
+ if (numaliasm < 1) {
+ HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
+ af->getlinenum());
+ return false;
}
- case 1: {
- numaliasm = atoi(piece);
- if (numaliasm < 1) {
- HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n",
- af->getlinenum());
- return 1;
- }
- aliasm = (char**)malloc(numaliasm * sizeof(char*));
- if (!aliasm) {
- numaliasm = 0;
- return 1;
- }
- np++;
- break;
+ aliasm = (char**)malloc(numaliasm * sizeof(char*));
+ if (!aliasm) {
+ numaliasm = 0;
+ return false;
}
- default:
- break;
+ np++;
+ break;
}
- i++;
+ default:
+ break;
}
- piece = mystrsep(&tp, 0);
+ ++i;
+ start_piece = mystrsep(line, iter);
}
if (np != 2) {
numaliasm = 0;
free(aliasm);
aliasm = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n",
af->getlinenum());
- return 1;
+ return false;
}
/* now parse the numaliasm lines to read in the remainder of the table */
- char* nl = line;
for (int j = 0; j < numaliasm; j++) {
- if ((nl = af->getline()) == NULL)
- return 1;
+ std::string nl;
+ if (!af->getline(nl))
+ return false;
mychomp(nl);
- tp = nl;
- i = 0;
aliasm[j] = NULL;
- piece = mystrsep(&tp, ' ');
- while (piece) {
- if (*piece != '\0') {
- switch (i) {
- case 0: {
- if (strncmp(piece, "AM", 2) != 0) {
- HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
- af->getlinenum());
- numaliasm = 0;
- free(aliasm);
- aliasm = NULL;
- return 1;
- }
- break;
+ iter = nl.begin();
+ i = 0;
+ start_piece = mystrsep(nl, iter);
+ while (start_piece != nl.end()) {
+ switch (i) {
+ case 0: {
+ if (nl.compare(start_piece - nl.begin(), 2, "AM", 2) != 0) {
+ HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
+ af->getlinenum());
+ numaliasm = 0;
+ free(aliasm);
+ aliasm = NULL;
+ return false;
}
- case 1: {
- // add the remaining of the line
- if (*tp) {
- *(tp - 1) = ' ';
- tp = tp + strlen(tp);
- }
- std::string chunk(piece);
- if (complexprefixes) {
- if (utf8)
- reverseword_utf(chunk);
- else
- reverseword(chunk);
- }
- aliasm[j] = mystrdup(chunk.c_str());
- break;
+ break;
+ }
+ case 1: {
+ // add the remaining of the line
+ std::string::const_iterator end = nl.end();
+ std::string chunk(start_piece, end);
+ if (complexprefixes) {
+ if (utf8)
+ reverseword_utf(chunk);
+ else
+ reverseword(chunk);
}
- default:
- break;
+ aliasm[j] = mystrdup(chunk.c_str());
+ break;
}
- i++;
+ default:
+ break;
}
- piece = mystrsep(&tp, ' ');
+ ++i;
+ start_piece = mystrsep(nl, iter);
}
if (!aliasm[j]) {
numaliasm = 0;
free(aliasm);
aliasm = NULL;
HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n",
af->getlinenum());
- return 1;
+ return false;
}
}
- return 0;
+ return true;
}
-int HashMgr::is_aliasm() {
+int HashMgr::is_aliasm() const {
return (aliasm != NULL);
}
-char* HashMgr::get_aliasm(int index) {
+char* HashMgr::get_aliasm(int index) const {
if ((index > 0) && (index <= numaliasm))
return aliasm[index - 1];
HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index);
return NULL;
}
--- a/extensions/spellcheck/hunspell/src/hashmgr.hxx
+++ b/extensions/spellcheck/hunspell/src/hashmgr.hxx
@@ -66,84 +66,82 @@
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifndef _HASHMGR_HXX_
-#define _HASHMGR_HXX_
-
-#include "hunvisapi.h"
+#ifndef HASHMGR_HXX_
+#define HASHMGR_HXX_
#include <stdio.h>
#include <string>
#include <vector>
#include "htypes.hxx"
#include "filemgr.hxx"
#include "w_char.hxx"
enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
-class LIBHUNSPELL_DLL_EXPORTED HashMgr {
+class HashMgr {
int tablesize;
struct hentry** tableptr;
flag flag_mode;
int complexprefixes;
int utf8;
unsigned short forbiddenword;
int langnum;
- char* enc;
- char* lang;
+ std::string enc;
+ std::string lang;
struct cs_info* csconv;
- char* ignorechars;
+ std::string ignorechars;
std::vector<w_char> ignorechars_utf16;
int numaliasf; // flag vector `compression' with aliases
unsigned short** aliasf;
unsigned short* aliasflen;
int numaliasm; // morphological desciption `compression' with aliases
char** aliasm;
public:
HashMgr(const char* tpath, const char* apath, const char* key = NULL);
~HashMgr();
struct hentry* lookup(const char*) const;
int hash(const char*) const;
struct hentry* walk_hashtable(int& col, struct hentry* hp) const;
int add(const std::string& word);
- int add_with_affix(const char* word, const char* pattern);
- int remove(const char* word);
- int decode_flags(unsigned short** result, char* flags, FileMgr* af);
- unsigned short decode_flag(const char* flag);
- char* encode_flag(unsigned short flag);
- int is_aliasf();
- int get_aliasf(int index, unsigned short** fvec, FileMgr* af);
- int is_aliasm();
- char* get_aliasm(int index);
+ int add_with_affix(const std::string& word, const std::string& pattern);
+ int remove(const std::string& word);
+ int decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const;
+ bool decode_flags(std::vector<unsigned short>& result, const std::string& flags, FileMgr* af) const;
+ unsigned short decode_flag(const char* flag) const;
+ char* encode_flag(unsigned short flag) const;
+ int is_aliasf() const;
+ int get_aliasf(int index, unsigned short** fvec, FileMgr* af) const;
+ int is_aliasm() const;
+ char* get_aliasm(int index) const;
private:
int get_clen_and_captype(const std::string& word, int* captype);
int load_tables(const char* tpath, const char* key);
- int add_word(const char* word,
- int wbl,
+ int add_word(const std::string& word,
int wcl,
unsigned short* ap,
int al,
- const char* desc,
+ const std::string* desc,
bool onlyupcase);
int load_config(const char* affpath, const char* key);
- int parse_aliasf(char* line, FileMgr* af);
+ bool parse_aliasf(const std::string& line, FileMgr* af);
int add_hidden_capitalized_word(const std::string& word,
int wcl,
unsigned short* flags,
int al,
- char* dp,
+ const std::string* dp,
int captype);
- int parse_aliasm(char* line, FileMgr* af);
+ bool parse_aliasm(const std::string& line, FileMgr* af);
int remove_forbidden_flag(const std::string& word);
};
#endif
--- a/extensions/spellcheck/hunspell/src/htypes.hxx
+++ b/extensions/spellcheck/hunspell/src/htypes.hxx
@@ -33,18 +33,18 @@
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-#ifndef _HTYPES_HXX_
-#define _HTYPES_HXX_
+#ifndef HTYPES_HXX_
+#define HTYPES_HXX_
#define ROTATE_LEN 5
#define ROTATE(v, q) \
(v) = ((v) << (q)) | (((v) >> (32 - q)) & ((1 << (q)) - 1));
// hentry options
#define H_OPT (1 << 0)
--- a/extensions/spellcheck/hunspell/src/hunspell.cxx
+++ b/extensions/spellcheck/hunspell/src/hunspell.cxx
@@ -70,112 +70,180 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include "affixmgr.hxx"
#include "hunspell.hxx"
+#include "suggestmgr.hxx"
#include "hunspell.h"
-#ifndef MOZILLA_CLIENT
-#include "config.h"
-#endif
#include "csutil.hxx"
#include <limits>
#include <string>
-#define MAXWORDLEN 176
#define MAXWORDUTF8LEN (MAXWORDLEN * 3)
-Hunspell::Hunspell(const char* affpath, const char* dpath, const char* key) {
- encoding = NULL;
+class HunspellImpl
+{
+public:
+ HunspellImpl(const char* affpath, const char* dpath, const char* key);
+ ~HunspellImpl();
+ int add_dic(const char* dpath, const char* key);
+ std::vector<std::string> suffix_suggest(const std::string& root_word);
+ std::vector<std::string> generate(const std::string& word, const std::vector<std::string>& pl);
+ std::vector<std::string> generate(const std::string& word, const std::string& pattern);
+ std::vector<std::string> stem(const std::string& word);
+ std::vector<std::string> stem(const std::vector<std::string>& morph);
+ std::vector<std::string> analyze(const std::string& word);
+ int get_langnum() const;
+ bool input_conv(const std::string& word, std::string& dest);
+ bool spell(const std::string& word, int* info = NULL, std::string* root = NULL);
+ std::vector<std::string> suggest(const std::string& word);
+ const std::string& get_wordchars() const;
+ const std::vector<w_char>& get_wordchars_utf16() const;
+ const std::string& get_dict_encoding() const;
+ int add(const std::string& word);
+ int add_with_affix(const std::string& word, const std::string& example);
+ int remove(const std::string& word);
+ const std::string& get_version() const;
+ struct cs_info* get_csconv();
+ std::vector<char> dic_encoding_vec;
+
+private:
+ AffixMgr* pAMgr;
+ std::vector<HashMgr*> m_HMgrs;
+ SuggestMgr* pSMgr;
+ char* affixpath;
+ std::string encoding;
+ struct cs_info* csconv;
+ int langnum;
+ int utf8;
+ int complexprefixes;
+ std::vector<std::string> wordbreak;
+
+private:
+ void cleanword(std::string& dest, const std::string&, int* pcaptype, int* pabbrev);
+ size_t cleanword2(std::string& dest,
+ std::vector<w_char>& dest_u,
+ const std::string& src,
+ int* pcaptype,
+ size_t* pabbrev);
+ void mkinitcap(std::string& u8);
+ int mkinitcap2(std::string& u8, std::vector<w_char>& u16);
+ int mkinitsmall2(std::string& u8, std::vector<w_char>& u16);
+ void mkallcap(std::string& u8);
+ int mkallsmall2(std::string& u8, std::vector<w_char>& u16);
+ struct hentry* checkword(const std::string& source, int* info, std::string* root);
+ std::string sharps_u8_l1(const std::string& source);
+ hentry*
+ spellsharps(std::string& base, size_t start_pos, int, int, int* info, std::string* root);
+ int is_keepcase(const hentry* rv);
+ void insert_sug(std::vector<std::string>& slst, const std::string& word);
+ void cat_result(std::string& result, const std::string& st);
+ std::vector<std::string> spellml(const std::string& word);
+ std::string get_xml_par(const char* par);
+ const char* get_xml_pos(const char* s, const char* attr);
+ std::vector<std::string> get_xml_list(const char* list, const char* tag);
+ int check_xml_par(const char* q, const char* attr, const char* value);
+private:
+ HunspellImpl(const HunspellImpl&);
+ HunspellImpl& operator=(const HunspellImpl&);
+};
+
+Hunspell::Hunspell(const char* affpath, const char* dpath, const char* key)
+ : m_Impl(new HunspellImpl(affpath, dpath, key)) {
+}
+
+HunspellImpl::HunspellImpl(const char* affpath, const char* dpath, const char* key) {
csconv = NULL;
utf8 = 0;
complexprefixes = 0;
affixpath = mystrdup(affpath);
- maxdic = 0;
/* first set up the hash manager */
- pHMgr[0] = new HashMgr(dpath, affpath, key);
- if (pHMgr[0])
- maxdic = 1;
+ m_HMgrs.push_back(new HashMgr(dpath, affpath, key));
/* next set up the affix manager */
/* it needs access to the hash manager lookup methods */
- pAMgr = new AffixMgr(affpath, pHMgr, &maxdic, key);
+ pAMgr = new AffixMgr(affpath, m_HMgrs, key);
/* get the preferred try string and the dictionary */
/* encoding from the Affix Manager for that dictionary */
char* try_string = pAMgr->get_try_string();
encoding = pAMgr->get_encoding();
langnum = pAMgr->get_langnum();
utf8 = pAMgr->get_utf8();
if (!utf8)
csconv = get_current_cs(encoding);
complexprefixes = pAMgr->get_complexprefixes();
wordbreak = pAMgr->get_breaktable();
+ dic_encoding_vec.resize(encoding.size()+1);
+ strcpy(&dic_encoding_vec[0], encoding.c_str());
+
/* and finally set up the suggestion manager */
pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr);
if (try_string)
free(try_string);
}
Hunspell::~Hunspell() {
+ delete m_Impl;
+}
+
+HunspellImpl::~HunspellImpl() {
delete pSMgr;
delete pAMgr;
- for (int i = 0; i < maxdic; i++)
- delete pHMgr[i];
- maxdic = 0;
+ for (size_t i = 0; i < m_HMgrs.size(); ++i)
+ delete m_HMgrs[i];
pSMgr = NULL;
pAMgr = NULL;
#ifdef MOZILLA_CLIENT
delete[] csconv;
#endif
csconv = NULL;
- if (encoding)
- free(encoding);
- encoding = NULL;
if (affixpath)
free(affixpath);
affixpath = NULL;
}
// load extra dictionaries
int Hunspell::add_dic(const char* dpath, const char* key) {
- if (maxdic == MAXDIC || !affixpath)
+ return m_Impl->add_dic(dpath, key);
+}
+
+// load extra dictionaries
+int HunspellImpl::add_dic(const char* dpath, const char* key) {
+ if (!affixpath)
return 1;
- pHMgr[maxdic] = new HashMgr(dpath, affixpath, key);
- if (pHMgr[maxdic])
- maxdic++;
- else
- return 1;
+ m_HMgrs.push_back(new HashMgr(dpath, affixpath, key));
return 0;
}
// make a copy of src at destination while removing all leading
// blanks and removing any trailing periods after recording
// their presence with the abbreviation flag
// also since already going through character by character,
// set the capitalization type
// return the length of the "cleaned" (and UTF-8 encoded) word
-size_t Hunspell::cleanword2(std::string& dest,
+size_t HunspellImpl::cleanword2(std::string& dest,
std::vector<w_char>& dest_utf,
- const char* src,
- int* nc,
+ const std::string& src,
int* pcaptype,
size_t* pabbrev) {
dest.clear();
dest_utf.clear();
- const char* q = src;
+ const char* q = src.c_str();
// first skip over any leading blanks
while ((*q != '\0') && (*q == ' '))
q++;
// now strip off any trailing periods (recording their presence)
*pabbrev = 0;
int nl = strlen(q);
@@ -188,31 +256,30 @@ size_t Hunspell::cleanword2(std::string&
if (nl <= 0) {
*pcaptype = NOCAP;
return 0;
}
dest.append(q, nl);
nl = dest.size();
if (utf8) {
- *nc = u8_u16(dest_utf, dest);
+ u8_u16(dest_utf, dest);
*pcaptype = get_captype_utf8(dest_utf, langnum);
} else {
*pcaptype = get_captype(dest, csconv);
- *nc = nl;
}
return nl;
}
-void Hunspell::cleanword(std::string& dest,
- const char* src,
+void HunspellImpl::cleanword(std::string& dest,
+ const std::string& src,
int* pcaptype,
int* pabbrev) {
dest.clear();
- const unsigned char* q = (const unsigned char*)src;
+ const unsigned char* q = (const unsigned char*)src.c_str();
int firstcap = 0;
// first skip over any leading blanks
while ((*q != '\0') && (*q == ' '))
q++;
// now strip off any trailing periods (recording their presence)
*pabbrev = 0;
@@ -272,145 +339,134 @@ void Hunspell::cleanword(std::string& de
*pcaptype = ALLCAP;
} else if ((ncap > 1) && firstcap) {
*pcaptype = HUHINITCAP;
} else {
*pcaptype = HUHCAP;
}
}
-void Hunspell::mkallcap(std::string& u8) {
+void HunspellImpl::mkallcap(std::string& u8) {
if (utf8) {
std::vector<w_char> u16;
u8_u16(u16, u8);
::mkallcap_utf(u16, langnum);
u16_u8(u8, u16);
} else {
::mkallcap(u8, csconv);
}
}
-int Hunspell::mkallsmall2(std::string& u8, std::vector<w_char>& u16) {
+int HunspellImpl::mkallsmall2(std::string& u8, std::vector<w_char>& u16) {
if (utf8) {
::mkallsmall_utf(u16, langnum);
u16_u8(u8, u16);
} else {
::mkallsmall(u8, csconv);
}
return u8.size();
}
// convert UTF-8 sharp S codes to latin 1
-std::string Hunspell::sharps_u8_l1(const std::string& source) {
+std::string HunspellImpl::sharps_u8_l1(const std::string& source) {
std::string dest(source);
mystrrep(dest, "\xC3\x9F", "\xDF");
return dest;
}
// recursive search for right ss - sharp s permutations
-hentry* Hunspell::spellsharps(std::string& base,
+hentry* HunspellImpl::spellsharps(std::string& base,
size_t n_pos,
int n,
int repnum,
int* info,
- char** root) {
+ std::string* root) {
size_t pos = base.find("ss", n_pos);
if (pos != std::string::npos && (n < MAXSHARPS)) {
base[pos] = '\xC3';
base[pos + 1] = '\x9F';
hentry* h = spellsharps(base, pos + 2, n + 1, repnum + 1, info, root);
if (h)
return h;
base[pos] = 's';
base[pos + 1] = 's';
h = spellsharps(base, pos + 2, n + 1, repnum, info, root);
if (h)
return h;
} else if (repnum > 0) {
if (utf8)
- return checkword(base.c_str(), info, root);
+ return checkword(base, info, root);
std::string tmp(sharps_u8_l1(base));
- return checkword(tmp.c_str(), info, root);
+ return checkword(tmp, info, root);
}
return NULL;
}
-int Hunspell::is_keepcase(const hentry* rv) {
+int HunspellImpl::is_keepcase(const hentry* rv) {
return pAMgr && rv->astr && pAMgr->get_keepcase() &&
TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen);
}
-/* insert a word to the beginning of the suggestion array and return ns */
-int Hunspell::insert_sug(char*** slst, const char* word, int ns) {
- if (!*slst)
- return ns;
- char* dup = mystrdup(word);
- if (!dup)
- return ns;
- if (ns == MAXSUGGESTION) {
- ns--;
- free((*slst)[ns]);
- }
- for (int k = ns; k > 0; k--)
- (*slst)[k] = (*slst)[k - 1];
- (*slst)[0] = dup;
- return ns + 1;
+/* insert a word to the beginning of the suggestion array */
+void HunspellImpl::insert_sug(std::vector<std::string>& slst, const std::string& word) {
+ slst.insert(slst.begin(), word);
}
-int Hunspell::spell(const char* word, int* info, char** root) {
+bool Hunspell::spell(const std::string& word, int* info, std::string* root) {
+ return m_Impl->spell(word, info, root);
+}
+
+bool HunspellImpl::spell(const std::string& word, int* info, std::string* root) {
struct hentry* rv = NULL;
int info2 = 0;
if (!info)
info = &info2;
else
*info = 0;
// Hunspell supports XML input of the simplified API (see manual)
- if (strcmp(word, SPELL_XML) == 0)
- return 1;
- int nc = strlen(word);
+ if (word == SPELL_XML)
+ return true;
if (utf8) {
- if (nc >= MAXWORDUTF8LEN)
- return 0;
+ if (word.size() >= MAXWORDUTF8LEN)
+ return false;
} else {
- if (nc >= MAXWORDLEN)
- return 0;
+ if (word.size() >= MAXWORDLEN)
+ return false;
}
int captype = NOCAP;
size_t abbv = 0;
size_t wl = 0;
std::string scw;
std::vector<w_char> sunicw;
// input conversion
- RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
+ RepList* rl = pAMgr ? pAMgr->get_iconvtable() : NULL;
{
std::string wspace;
- int convstatus = rl ? rl->conv(word, wspace) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- wl = cleanword2(scw, sunicw, wspace.c_str(), &nc, &captype, &abbv);
+ bool convstatus = rl ? rl->conv(word, wspace) : false;
+ if (convstatus)
+ wl = cleanword2(scw, sunicw, wspace, &captype, &abbv);
else
- wl = cleanword2(scw, sunicw, word, &nc, &captype, &abbv);
+ wl = cleanword2(scw, sunicw, word, &captype, &abbv);
}
#ifdef MOZILLA_CLIENT
// accept the abbreviated words without dots
// workaround for the incomplete tokenization of Mozilla
abbv = 1;
#endif
- if (wl == 0 || maxdic == 0)
- return 1;
+ if (wl == 0 || m_HMgrs.empty())
+ return true;
if (root)
- *root = NULL;
+ root->clear();
// allow numbers with dots, dashes and commas (but forbid double separators:
// "..", "--" etc.)
enum { NBEGIN, NNUM, NSEP };
int nstate = NBEGIN;
size_t i;
for (i = 0; (i < wl); i++) {
@@ -419,41 +475,41 @@ int Hunspell::spell(const char* word, in
} else if ((scw[i] == ',') || (scw[i] == '.') || (scw[i] == '-')) {
if ((nstate == NSEP) || (i == 0))
break;
nstate = NSEP;
} else
break;
}
if ((i == wl) && (nstate == NNUM))
- return 1;
+ return true;
switch (captype) {
case HUHCAP:
/* FALLTHROUGH */
case HUHINITCAP:
*info += SPELL_ORIGCAP;
/* FALLTHROUGH */
case NOCAP:
- rv = checkword(scw.c_str(), info, root);
+ rv = checkword(scw, info, root);
if ((abbv) && !(rv)) {
std::string u8buffer(scw);
u8buffer.push_back('.');
- rv = checkword(u8buffer.c_str(), info, root);
+ rv = checkword(u8buffer, info, root);
}
break;
case ALLCAP: {
*info += SPELL_ORIGCAP;
- rv = checkword(scw.c_str(), info, root);
+ rv = checkword(scw, info, root);
if (rv)
break;
if (abbv) {
std::string u8buffer(scw);
u8buffer.push_back('.');
- rv = checkword(u8buffer.c_str(), info, root);
+ rv = checkword(u8buffer, info, root);
if (rv)
break;
}
// Spec. prefix handling for Catalan, French, Italian:
// prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia).
size_t apos = pAMgr ? scw.find('\'') : std::string::npos;
if (apos != std::string::npos) {
mkallsmall2(scw, sunicw);
@@ -465,28 +521,28 @@ int Hunspell::spell(const char* word, in
if (utf8) {
std::vector<w_char> part1u, part2u;
u8_u16(part1u, part1);
u8_u16(part2u, part2);
mkinitcap2(part2, part2u);
scw = part1 + part2;
sunicw = part1u;
sunicw.insert(sunicw.end(), part2u.begin(), part2u.end());
- rv = checkword(scw.c_str(), info, root);
+ rv = checkword(scw, info, root);
if (rv)
break;
} else {
mkinitcap2(part2, sunicw);
scw = part1 + part2;
- rv = checkword(scw.c_str(), info, root);
+ rv = checkword(scw, info, root);
if (rv)
break;
}
mkinitcap2(scw, sunicw);
- rv = checkword(scw.c_str(), info, root);
+ rv = checkword(scw, info, root);
if (rv)
break;
}
}
if (pAMgr && pAMgr->get_checksharps() && scw.find("SS") != std::string::npos) {
mkallsmall2(scw, sunicw);
std::string u8buffer(scw);
@@ -511,41 +567,41 @@ int Hunspell::spell(const char* word, in
case INITCAP: {
*info += SPELL_ORIGCAP;
mkallsmall2(scw, sunicw);
std::string u8buffer(scw);
mkinitcap2(scw, sunicw);
if (captype == INITCAP)
*info += SPELL_INITCAP;
- rv = checkword(scw.c_str(), info, root);
+ rv = checkword(scw, info, root);
if (captype == INITCAP)
*info -= SPELL_INITCAP;
// forbid bad capitalization
// (for example, ijs -> Ijs instead of IJs in Dutch)
// use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
if (*info & SPELL_FORBIDDEN) {
rv = NULL;
break;
}
if (rv && is_keepcase(rv) && (captype == ALLCAP))
rv = NULL;
if (rv)
break;
- rv = checkword(u8buffer.c_str(), info, root);
+ rv = checkword(u8buffer, info, root);
if (abbv && !rv) {
u8buffer.push_back('.');
- rv = checkword(u8buffer.c_str(), info, root);
+ rv = checkword(u8buffer, info, root);
if (!rv) {
u8buffer = scw;
u8buffer.push_back('.');
if (captype == INITCAP)
*info += SPELL_INITCAP;
- rv = checkword(u8buffer.c_str(), info, root);
+ rv = checkword(u8buffer, info, root);
if (captype == INITCAP)
*info -= SPELL_INITCAP;
if (rv && is_keepcase(rv) && (captype == ALLCAP))
rv = NULL;
break;
}
}
if (rv && is_keepcase(rv) &&
@@ -560,114 +616,112 @@ int Hunspell::spell(const char* word, in
}
}
if (rv) {
if (pAMgr && pAMgr->get_warn() && rv->astr &&
TESTAFF(rv->astr, pAMgr->get_warn(), rv->alen)) {
*info += SPELL_WARN;
if (pAMgr->get_forbidwarn())
- return 0;
- return HUNSPELL_OK_WARN;
+ return false;
+ return true;
}
- return HUNSPELL_OK;
+ return true;
}
// recursive breaking at break points
- if (wordbreak) {
+ if (!wordbreak.empty()) {
int nbr = 0;
wl = scw.size();
- int numbreak = pAMgr ? pAMgr->get_numbreak() : 0;
// calculate break points for recursion limit
- for (int j = 0; j < numbreak; j++) {
- size_t len = strlen(wordbreak[j]);
+ for (size_t j = 0; j < wordbreak.size(); ++j) {
size_t pos = 0;
- while ((pos = scw.find(wordbreak[j], pos, len)) != std::string::npos) {
+ while ((pos = scw.find(wordbreak[j], pos)) != std::string::npos) {
++nbr;
- pos += len;
+ pos += wordbreak[j].size();
}
}
if (nbr >= 10)
- return 0;
+ return false;
// check boundary patterns (^begin and end$)
- for (int j = 0; j < numbreak; j++) {
- size_t plen = strlen(wordbreak[j]);
+ for (size_t j = 0; j < wordbreak.size(); ++j) {
+ size_t plen = wordbreak[j].size();
if (plen == 1 || plen > wl)
continue;
if (wordbreak[j][0] == '^' &&
- scw.compare(0, plen - 1, wordbreak[j] + 1, plen -1) == 0 && spell(scw.c_str() + plen - 1))
- return 1;
+ scw.compare(0, plen - 1, wordbreak[j], 1, plen -1) == 0 && spell(scw.substr(plen - 1)))
+ return true;
if (wordbreak[j][plen - 1] == '$' &&
- scw.compare(wl - plen + 1, plen - 1, wordbreak[j], plen - 1) == 0) {
- char r = scw[wl - plen + 1];
- scw[wl - plen + 1] = '\0';
- if (spell(scw.c_str()))
- return 1;
- scw[wl - plen + 1] = r;
+ scw.compare(wl - plen + 1, plen - 1, wordbreak[j], 0, plen - 1) == 0) {
+ std::string suffix(scw.substr(wl - plen + 1));
+ scw.resize(wl - plen + 1);
+ if (spell(scw))
+ return true;
+ scw.append(suffix);
}
}
// other patterns
- for (int j = 0; j < numbreak; j++) {
- size_t plen = strlen(wordbreak[j]);
+ for (size_t j = 0; j < wordbreak.size(); ++j) {
+ size_t plen = wordbreak[j].size();
size_t found = scw.find(wordbreak[j]);
if ((found > 0) && (found < wl - plen)) {
- if (!spell(scw.c_str() + found + plen))
+ if (!spell(scw.substr(found + plen)))
continue;
- char r = scw[found];
- scw[found] = '\0';
+ std::string suffix(scw.substr(found));
+ scw.resize(found);
// examine 2 sides of the break point
- if (spell(scw.c_str()))
- return 1;
- scw[found] = r;
+ if (spell(scw))
+ return true;
+ scw.append(suffix);
// LANG_hu: spec. dash rule
- if (langnum == LANG_hu && strcmp(wordbreak[j], "-") == 0) {
- r = scw[found + 1];
- scw[found + 1] = '\0';
- if (spell(scw.c_str()))
- return 1; // check the first part with dash
- scw[found + 1] = r;
+ if (langnum == LANG_hu && wordbreak[j] == "-") {
+ suffix = scw.substr(found + 1);
+ scw.resize(found + 1);
+ if (spell(scw))
+ return true; // check the first part with dash
+ scw.append(suffix);
}
// end of LANG specific region
}
}
}
- return 0;
+ return false;
}
-struct hentry* Hunspell::checkword(const char* w, int* info, char** root) {
- struct hentry* he = NULL;
+struct hentry* HunspellImpl::checkword(const std::string& w, int* info, std::string* root) {
bool usebuffer = false;
- int len, i;
std::string w2;
const char* word;
+ int len;
- char* ignoredchars = pAMgr ? pAMgr->get_ignore() : NULL;
+ const char* ignoredchars = pAMgr ? pAMgr->get_ignore() : NULL;
if (ignoredchars != NULL) {
w2.assign(w);
if (utf8) {
const std::vector<w_char>& ignoredchars_utf16 =
pAMgr->get_ignore_utf16();
remove_ignored_chars_utf(w2, ignoredchars_utf16);
} else {
remove_ignored_chars(w2, ignoredchars);
}
word = w2.c_str();
+ len = w2.size();
usebuffer = true;
- } else
- word = w;
-
- len = strlen(word);
+ } else {
+ word = w.c_str();
+ len = w.size();
+ }
if (!len)
return NULL;
// word reversing wrapper for complex prefixes
if (complexprefixes) {
if (!usebuffer) {
w2.assign(word);
@@ -679,18 +733,19 @@ struct hentry* Hunspell::checkword(const
reverseword(w2);
}
if (usebuffer) {
word = w2.c_str();
}
// look word in hash table
- for (i = 0; (i < maxdic) && !he; i++) {
- he = (pHMgr[i])->lookup(word);
+ struct hentry* he = NULL;
+ for (size_t i = 0; (i < m_HMgrs.size()) && !he; ++i) {
+ he = m_HMgrs[i]->lookup(word);
// check forbidden and onlyincompound words
if ((he) && (he->astr) && (pAMgr) &&
TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
if (info)
*info += SPELL_FORBIDDEN;
// LANG_hu section: set dash information for suggestions
if (langnum == LANG_hu) {
@@ -731,806 +786,783 @@ struct hentry* Hunspell::checkword(const
if (he) {
if ((he->astr) && (pAMgr) &&
TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) {
if (info)
*info += SPELL_FORBIDDEN;
return NULL;
}
if (root) {
- std::string word_root(he->word);
+ root->assign(he->word);
if (complexprefixes) {
if (utf8)
- reverseword_utf(word_root);
+ reverseword_utf(*root);
else
- reverseword(word_root);
+ reverseword(*root);
}
- *root = mystrdup(word_root.c_str());
}
// try check compound word
} else if (pAMgr->get_compound()) {
struct hentry* rwords[100]; // buffer for COMPOUND pattern checking
- he = pAMgr->compound_check(word, len, 0, 0, 100, 0, NULL, (hentry**)&rwords, 0, 0, info);
+ he = pAMgr->compound_check(word, 0, 0, 100, 0, NULL, (hentry**)&rwords, 0, 0, info);
// LANG_hu section: `moving rule' with last dash
if ((!he) && (langnum == LANG_hu) && (word[len - 1] == '-')) {
- char* dup = mystrdup(word);
- if (!dup)
- return NULL;
- dup[len - 1] = '\0';
- he = pAMgr->compound_check(dup, len - 1, -5, 0, 100, 0, NULL, (hentry**)&rwords, 1, 0,
- info);
- free(dup);
+ std::string dup(word, len - 1);
+ he = pAMgr->compound_check(dup, -5, 0, 100, 0, NULL, (hentry**)&rwords, 1, 0, info);
}
// end of LANG specific region
if (he) {
if (root) {
- std::string word_root(he->word);
+ root->assign(he->word);
if (complexprefixes) {
if (utf8)
- reverseword_utf(word_root);
+ reverseword_utf(*root);
else
- reverseword(word_root);
+ reverseword(*root);
}
- *root = mystrdup(word_root.c_str());
}
if (info)
*info += SPELL_COMPOUND;
}
}
}
return he;
}
-int Hunspell::suggest(char*** slst, const char* word) {
+std::vector<std::string> Hunspell::suggest(const std::string& word) {
+ return m_Impl->suggest(word);
+}
+
+std::vector<std::string> HunspellImpl::suggest(const std::string& word) {
+ std::vector<std::string> slst;
+
int onlycmpdsug = 0;
- if (!pSMgr || maxdic == 0)
- return 0;
- *slst = NULL;
+ if (!pSMgr || m_HMgrs.empty())
+ return slst;
+
// process XML input of the simplified API (see manual)
- if (strncmp(word, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
- return spellml(slst, word);
+ if (word.compare(0, sizeof(SPELL_XML) - 3, SPELL_XML, sizeof(SPELL_XML) - 3) == 0) {
+ return spellml(word);
}
- int nc = strlen(word);
if (utf8) {
- if (nc >= MAXWORDUTF8LEN)
- return 0;
+ if (word.size() >= MAXWORDUTF8LEN)
+ return slst;
} else {
- if (nc >= MAXWORDLEN)
- return 0;
+ if (word.size() >= MAXWORDLEN)
+ return slst;
}
int captype = NOCAP;
size_t abbv = 0;
size_t wl = 0;
std::string scw;
std::vector<w_char> sunicw;
// input conversion
RepList* rl = (pAMgr) ? pAMgr->get_iconvtable() : NULL;
{
std::string wspace;
- int convstatus = rl ? rl->conv(word, wspace) : 0;
- if (convstatus < 0)
- return 0;
- else if (convstatus > 0)
- wl = cleanword2(scw, sunicw, wspace.c_str(), &nc, &captype, &abbv);
+ bool convstatus = rl ? rl->conv(word, wspace) : false;
+ if (convstatus)
+ wl = cleanword2(scw, sunicw, wspace, &captype, &abbv);
else
- wl = cleanword2(scw, sunicw, word, &nc, &captype, &abbv);
+ wl = cleanword2(scw, sunicw, word, &captype, &abbv);
if (wl == 0)
- return 0;
+ return slst;
}
- int ns = 0;
int capwords = 0;
// check capitalized form for FORCEUCASE
if (pAMgr && captype == NOCAP && pAMgr->get_forceucase()) {
int info = SPELL_ORIGCAP;
- if (checkword(scw.c_str(), &info, NULL)) {
+ if (checkword(scw, &info, NULL)) {
std::string form(scw);
mkinitcap(form);
-
- char** wlst = (char**)malloc(MAXSUGGESTION * sizeof(char*));
- if (wlst == NULL)
- return -1;
- *slst = wlst;
- wlst[0] = mystrdup(form.c_str());
- for (int i = 1; i < MAXSUGGESTION; ++i) {
- wlst[i] = NULL;
- }
-
- return 1;
+ slst.push_back(form);
+ return slst;
}
}
switch (captype) {
case NOCAP: {
- ns = pSMgr->suggest(slst, scw.c_str(), ns, &onlycmpdsug);
+ pSMgr->suggest(slst, scw.c_str(), &onlycmpdsug);
break;
}
case INITCAP: {
capwords = 1;
- ns = pSMgr->suggest(slst, scw.c_str(), ns, &onlycmpdsug);
- if (ns == -1)
- break;
+ pSMgr->suggest(slst, scw.c_str(), &onlycmpdsug);
std::string wspace(scw);
mkallsmall2(wspace, sunicw);
- ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
+ pSMgr->suggest(slst, wspace.c_str(), &onlycmpdsug);
break;
}
case HUHINITCAP:
capwords = 1;
case HUHCAP: {
- ns = pSMgr->suggest(slst, scw.c_str(), ns, &onlycmpdsug);
- if (ns != -1) {
- // something.The -> something. The
- size_t dot_pos = scw.find('.');
- if (dot_pos != std::string::npos) {
- std::string postdot = scw.substr(dot_pos + 1);
- int captype_;
- if (utf8) {
- std::vector<w_char> postdotu;
- u8_u16(postdotu, postdot);
- captype_ = get_captype_utf8(postdotu, langnum);
- } else {
- captype_ = get_captype(postdot, csconv);
- }
- if (captype_ == INITCAP) {
- std::string str(scw);
- str.insert(dot_pos + 1, 1, ' ');
- ns = insert_sug(slst, str.c_str(), ns);
- }
+ pSMgr->suggest(slst, scw.c_str(), &onlycmpdsug);
+ // something.The -> something. The
+ size_t dot_pos = scw.find('.');
+ if (dot_pos != std::string::npos) {
+ std::string postdot = scw.substr(dot_pos + 1);
+ int captype_;
+ if (utf8) {
+ std::vector<w_char> postdotu;
+ u8_u16(postdotu, postdot);
+ captype_ = get_captype_utf8(postdotu, langnum);
+ } else {
+ captype_ = get_captype(postdot, csconv);
}
-
- std::string wspace;
+ if (captype_ == INITCAP) {
+ std::string str(scw);
+ str.insert(dot_pos + 1, 1, ' ');
+ insert_sug(slst, str);
+ }
+ }
- if (captype == HUHINITCAP) {
- // TheOpenOffice.org -> The OpenOffice.org
- wspace = scw;
- mkinitsmall2(wspace, sunicw);
- ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
- }
+ std::string wspace;
+
+ if (captype == HUHINITCAP) {
+ // TheOpenOffice.org -> The OpenOffice.org
wspace = scw;
- mkallsmall2(wspace, sunicw);
+ mkinitsmall2(wspace, sunicw);
+ pSMgr->suggest(slst, wspace.c_str(), &onlycmpdsug);
+ }
+ wspace = scw;
+ mkallsmall2(wspace, sunicw);
+ if (spell(wspace.c_str()))
+ insert_sug(slst, wspace);
+ size_t prevns = slst.size();
+ pSMgr->suggest(slst, wspace.c_str(), &onlycmpdsug);
+ if (captype == HUHINITCAP) {
+ mkinitcap2(wspace, sunicw);
if (spell(wspace.c_str()))
- ns = insert_sug(slst, wspace.c_str(), ns);
- int prevns = ns;
- ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
- if (captype == HUHINITCAP) {
- mkinitcap2(wspace, sunicw);
- if (spell(wspace.c_str()))
- ns = insert_sug(slst, wspace.c_str(), ns);
- ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
- }
- // aNew -> "a New" (instead of "a new")
- for (int j = prevns; j < ns; j++) {
- char* space = strchr((*slst)[j], ' ');
- if (space) {
- size_t slen = strlen(space + 1);
- // different case after space (need capitalisation)
- if ((slen < wl) && strcmp(scw.c_str() + wl - slen, space + 1)) {
- std::string first((*slst)[j], space + 1);
- std::string second(space + 1);
- std::vector<w_char> w;
- if (utf8)
- u8_u16(w, second);
- mkinitcap2(second, w);
- // set as first suggestion
- char* r = (*slst)[j];
- for (int k = j; k > 0; k--)
- (*slst)[k] = (*slst)[k - 1];
- free(r);
- (*slst)[0] = mystrdup((first + second).c_str());
- }
+ insert_sug(slst, wspace);
+ pSMgr->suggest(slst, wspace.c_str(), &onlycmpdsug);
+ }
+ // aNew -> "a New" (instead of "a new")
+ for (size_t j = prevns; j < slst.size(); ++j) {
+ const char* space = strchr(slst[j].c_str(), ' ');
+ if (space) {
+ size_t slen = strlen(space + 1);
+ // different case after space (need capitalisation)
+ if ((slen < wl) && strcmp(scw.c_str() + wl - slen, space + 1)) {
+ std::string first(slst[j].c_str(), space + 1);
+ std::string second(space + 1);
+ std::vector<w_char> w;
+ if (utf8)
+ u8_u16(w, second);
+ mkinitcap2(second, w);
+ // set as first suggestion
+ slst.erase(slst.begin() + j);
+ slst.insert(slst.begin(), first + second);
}
}
}
break;
}
case ALLCAP: {
std::string wspace(scw);
mkallsmall2(wspace, sunicw);
- ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
- if (ns == -1)
- break;
+ pSMgr->suggest(slst, wspace.c_str(), &onlycmpdsug);
if (pAMgr && pAMgr->get_keepcase() && spell(wspace.c_str()))
- ns = insert_sug(slst, wspace.c_str(), ns);
+ insert_sug(slst, wspace);
mkinitcap2(wspace, sunicw);
- ns = pSMgr->suggest(slst, wspace.c_str(), ns, &onlycmpdsug);
- for (int j = 0; j < ns; j++) {
- std::string form((*slst)[j]);
- mkallcap(form);
-
+ pSMgr->suggest(slst, wspace.c_str(), &onlycmpdsug);
+ for (size_t j = 0; j < slst.size(); ++j) {
+ mkallcap(slst[j]);
if (pAMgr && pAMgr->get_checksharps()) {
if (utf8) {
- mystrrep(form, "\xC3\x9F", "SS");
+ mystrrep(slst[j], "\xC3\x9F", "SS");
} else {
- mystrrep(form, "\xDF", "SS");
+ mystrrep(slst[j], "\xDF", "SS");
}
}
-
- free((*slst)[j]);
- (*slst)[j] = mystrdup(form.c_str());
-
}
break;
}
}
// LANG_hu section: replace '-' with ' ' in Hungarian
if (langnum == LANG_hu) {
- for (int j = 0; j < ns; j++) {
- char* pos = strchr((*slst)[j], '-');
- if (pos) {
+ for (size_t j = 0; j < slst.size(); ++j) {
+ size_t pos = slst[j].find('-');
+ if (pos != std::string::npos) {
int info;
- *pos = '\0';
- std::string w((*slst)[j]);
- w.append(pos + 1);
- (void)spell(w.c_str(), &info, NULL);
+ std::string w(slst[j].substr(0, pos));
+ w.append(slst[j].substr(pos + 1));
+ (void)spell(w, &info, NULL);
if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) {
- *pos = ' ';
+ slst[j][pos] = ' ';
} else
- *pos = '-';
+ slst[j][pos] = '-';
}
}
}
// END OF LANG_hu section
// try ngram approach since found nothing or only compound words
- if (pAMgr && (ns == 0 || onlycmpdsug) && (pAMgr->get_maxngramsugs() != 0) &&
- (*slst)) {
+ if (pAMgr && (slst.empty() || onlycmpdsug) && (pAMgr->get_maxngramsugs() != 0)) {
switch (captype) {
case NOCAP: {
- ns = pSMgr->ngsuggest(*slst, scw.c_str(), ns, pHMgr, maxdic);
+ pSMgr->ngsuggest(slst, scw.c_str(), m_HMgrs);
break;
}
case HUHINITCAP:
capwords = 1;
case HUHCAP: {
std::string wspace(scw);
mkallsmall2(wspace, sunicw);
- ns = pSMgr->ngsuggest(*slst, wspace.c_str(), ns, pHMgr, maxdic);
+ pSMgr->ngsuggest(slst, wspace.c_str(), m_HMgrs);
break;
}
case INITCAP: {
capwords = 1;
std::string wspace(scw);
mkallsmall2(wspace, sunicw);
- ns = pSMgr->ngsuggest(*slst, wspace.c_str(), ns, pHMgr, maxdic);
+ pSMgr->ngsuggest(slst, wspace.c_str(), m_HMgrs);
break;
}
case ALLCAP: {
std::string wspace(scw);
mkallsmall2(wspace, sunicw);
- int oldns = ns;
- ns = pSMgr->ngsuggest(*slst, wspace.c_str(), ns, pHMgr, maxdic);
- for (int j = oldns; j < ns; j++) {
- std::string form((*slst)[j]);
- mkallcap(form);
- free((*slst)[j]);
- (*slst)[j] = mystrdup(form.c_str());
+ size_t oldns = slst.size();
+ pSMgr->ngsuggest(slst, wspace.c_str(), m_HMgrs);
+ for (size_t j = oldns; j < slst.size(); ++j) {
+ mkallcap(slst[j]);
}
break;
}
}
}
// try dash suggestion (Afo-American -> Afro-American)
size_t dash_pos = scw.find('-');
if (dash_pos != std::string::npos) {
int nodashsug = 1;
- for (int j = 0; j < ns && nodashsug == 1; j++) {
- if (strchr((*slst)[j], '-'))
+ for (size_t j = 0; j < slst.size() && nodashsug == 1; ++j) {
+ if (slst[j].find('-') != std::string::npos)
nodashsug = 0;
}
size_t prev_pos = 0;
bool last = false;
while (nodashsug && !last) {
if (dash_pos == scw.size())
last = 1;
std::string chunk = scw.substr(prev_pos, dash_pos - prev_pos);
if (!spell(chunk.c_str())) {
- char** nlst = NULL;
- int nn = suggest(&nlst, chunk.c_str());
- for (int j = nn - 1; j >= 0; j--) {
+ std::vector<std::string> nlst = suggest(chunk.c_str());
+ for (std::vector<std::string>::reverse_iterator j = nlst.rbegin(); j != nlst.rend(); ++j) {
std::string wspace = scw.substr(0, prev_pos);
- wspace.append(nlst[j]);
+ wspace.append(*j);
if (!last) {
wspace.append("-");
wspace.append(scw.substr(dash_pos + 1));
}
- ns = insert_sug(slst, wspace.c_str(), ns);
- free(nlst[j]);
+ insert_sug(slst, wspace);
}
- if (nlst != NULL)
- free(nlst);
nodashsug = 0;
}
if (!last) {
prev_pos = dash_pos + 1;
dash_pos = scw.find('-', prev_pos);
}
if (dash_pos == std::string::npos)
dash_pos = scw.size();
}
}
// word reversing wrapper for complex prefixes
if (complexprefixes) {
- for (int j = 0; j < ns; j++) {
- std::string root((*slst)[j]);
- free((*slst)[j]);
+ for (size_t j = 0; j < slst.size(); ++j) {
if (utf8)
- reverseword_utf(root);
+ reverseword_utf(slst[j]);
else
- reverseword(root);
- (*slst)[j] = mystrdup(root.c_str());
+ reverseword(slst[j]);
}
}
// capitalize
if (capwords)
- for (int j = 0; j < ns; j++) {
- std::string form((*slst)[j]);
- free((*slst)[j]);
- mkinitcap(form);
- (*slst)[j] = mystrdup(form.c_str());
+ for (size_t j = 0; j < slst.size(); ++j) {
+ mkinitcap(slst[j]);
}
// expand suggestions with dot(s)
if (abbv && pAMgr && pAMgr->get_sugswithdots()) {
- for (int j = 0; j < ns; j++) {
- (*slst)[j] = (char*)realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv);
- strcat((*slst)[j], word + strlen(word) - abbv);
+ for (size_t j = 0; j < slst.size(); ++j) {
+ slst[j].append(word.substr(word.size() - abbv));
}
}
// remove bad capitalized and forbidden forms
if (pAMgr && (pAMgr->get_keepcase() || pAMgr->get_forbiddenword())) {
switch (captype) {
case INITCAP:
case ALLCAP: {
- int l = 0;
- for (int j = 0; j < ns; j++) {
- if (!strchr((*slst)[j], ' ') && !spell((*slst)[j])) {
+ size_t l = 0;
+ for (size_t j = 0; j < slst.size(); ++j) {
+ if (slst[j].find(' ') == std::string::npos && !spell(slst[j])) {
std::string s;
std::vector<w_char> w;
if (utf8) {
- u8_u16(w, (*slst)[j]);
+ u8_u16(w, slst[j]);
} else {
- s = (*slst)[j];
+ s = slst[j];
}
mkallsmall2(s, w);
- free((*slst)[j]);
- if (spell(s.c_str())) {
- (*slst)[l] = mystrdup(s.c_str());
- if ((*slst)[l])
- l++;
+ if (spell(s)) {
+ slst[l] = s;
+ ++l;
} else {
mkinitcap2(s, w);
- if (spell(s.c_str())) {
- (*slst)[l] = mystrdup(s.c_str());
- if ((*slst)[l])
- l++;
+ if (spell(s)) {
+ slst[l] = s;
+ ++l;
}
}
} else {
- (*slst)[l] = (*slst)[j];
- l++;
+ slst[l] = slst[j];
+ ++l;
}
}
- ns = l;
+ slst.resize(l);
}
}
}
// remove duplications
- int l = 0;
- for (int j = 0; j < ns; j++) {
- (*slst)[l] = (*slst)[j];
- for (int k = 0; k < l; k++) {
- if (strcmp((*slst)[k], (*slst)[j]) == 0) {
- free((*slst)[j]);
- l--;
+ size_t l = 0;
+ for (size_t j = 0; j < slst.size(); ++j) {
+ slst[l] = slst[j];
+ for (size_t k = 0; k < l; ++k) {
+ if (slst[k] == slst[j]) {
+ --l;
break;
}
}
- l++;
+ ++l;
}
- ns = l;
+ slst.resize(l);
// output conversion
rl = (pAMgr) ? pAMgr->get_oconvtable() : NULL;
- for (int j = 0; rl && j < ns; j++) {
+ for (size_t j = 0; rl && j < slst.size(); ++j) {
std::string wspace;
- if (rl->conv((*slst)[j], wspace) > 0) {
- free((*slst)[j]);
- (*slst)[j] = mystrdup(wspace.c_str());
+ if (rl->conv(slst[j], wspace)) {
+ slst[j] = wspace;
}
}
- // if suggestions removed by nosuggest, onlyincompound parameters
- if (l == 0 && *slst) {
- free(*slst);
- *slst = NULL;
- }
- return l;
+ return slst;
}
-void Hunspell::free_list(char*** slst, int n) {
- freelist(slst, n);
+const std::string& Hunspell::get_dict_encoding() const {
+ return m_Impl->get_dict_encoding();
}
-char* Hunspell::get_dic_encoding() {
+const std::string& HunspellImpl::get_dict_encoding() const {
return encoding;
}
-int Hunspell::stem(char*** slst, char** desc, int n) {
+std::vector<std::string> Hunspell::stem(const std::vector<std::string>& desc) {
+ return m_Impl->stem(desc);
+}
+
+std::vector<std::string> HunspellImpl::stem(const std::vector<std::string>& desc) {
+ std::vector<std::string> slst;
std::string result2;
- *slst = NULL;
- if (n == 0)
- return 0;
- for (int i = 0; i < n; i++) {
+ if (desc.empty())
+ return slst;
+ for (size_t i = 0; i < desc.size(); ++i) {
std::string result;
// add compound word parts (except the last one)
- char* s = (char*)desc[i];
- char* part = strstr(s, MORPH_PART);
+ const char* s = desc[i].c_str();
+ const char* part = strstr(s, MORPH_PART);
if (part) {
- char* nextpart = strstr(part + 1, MORPH_PART);
+ const char* nextpart = strstr(part + 1, MORPH_PART);
while (nextpart) {
std::string field;
copy_field(field, part, MORPH_PART);
result.append(field);
part = nextpart;
nextpart = strstr(part + 1, MORPH_PART);
}
s = part;
}
- char** pl;
std::string tok(s);
size_t alt = 0;
while ((alt = tok.find(" | ", alt)) != std::string::npos) {
tok[alt + 1] = MSEP_ALT;
}
- int pln = line_tok(tok.c_str(), &pl, MSEP_ALT);
- for (int k = 0; k < pln; k++) {
+ std::vector<std::string> pl = line_tok(tok, MSEP_ALT);
+ for (size_t k = 0; k < pl.size(); ++k) {
// add derivational suffixes
- if (strstr(pl[k], MORPH_DERI_SFX)) {
+ if (pl[k].find(MORPH_DERI_SFX) != std::string::npos) {
// remove inflectional suffixes
- char* is = strstr(pl[k], MORPH_INFL_SFX);
- if (is)
- *is = '\0';
- char* sg = pSMgr->suggest_gen(&(pl[k]), 1, pl[k]);
- if (sg) {
- char** gen;
- int genl = line_tok(sg, &gen, MSEP_REC);
- free(sg);
- for (int j = 0; j < genl; j++) {
+ const size_t is = pl[k].find(MORPH_INFL_SFX);
+ if (is != std::string::npos)
+ pl[k].resize(is);
+ std::vector<std::string> singlepl;
+ singlepl.push_back(pl[k]);
+ std::string sg = pSMgr->suggest_gen(singlepl, pl[k]);
+ if (!sg.empty()) {
+ std::vector<std::string> gen = line_tok(sg, MSEP_REC);
+ for (size_t j = 0; j < gen.size(); ++j) {
result2.push_back(MSEP_REC);
result2.append(result);
result2.append(gen[j]);
}
- freelist(&gen, genl);
}
} else {
result2.push_back(MSEP_REC);
result2.append(result);
- if (strstr(pl[k], MORPH_SURF_PFX)) {
+ if (pl[k].find(MORPH_SURF_PFX) != std::string::npos) {
std::string field;
copy_field(field, pl[k], MORPH_SURF_PFX);
result2.append(field);
}
std::string field;
copy_field(field, pl[k], MORPH_STEM);
result2.append(field);
}
}
- freelist(&pl, pln);
}
- int sln = line_tok(result2.c_str(), slst, MSEP_REC);
- return uniqlist(*slst, sln);
+ slst = line_tok(result2, MSEP_REC);
+ uniqlist(slst);
+ return slst;
+}
+
+std::vector<std::string> Hunspell::stem(const std::string& word) {
+ return m_Impl->stem(word);
}
-int Hunspell::stem(char*** slst, const char* word) {
- char** pl;
- int pln = analyze(&pl, word);
- int pln2 = stem(slst, pl, pln);
- freelist(&pl, pln);
- return pln2;
+std::vector<std::string> HunspellImpl::stem(const std::string& word) {
+ return stem(analyze(word));
}
-const char* Hunspell::get_wordchars() {
+const char* Hunspell::get_wordchars() const {
+ return m_Impl->get_wordchars().c_str();
+}
+
+const std::string& Hunspell::get_wordchars_cpp() const {
+ return m_Impl->get_wordchars();
+}
+
+const std::string& HunspellImpl::get_wordchars() const {
return pAMgr->get_wordchars();
}
-const std::vector<w_char>& Hunspell::get_wordchars_utf16() {
+const std::vector<w_char>& Hunspell::get_wordchars_utf16() const {
+ return m_Impl->get_wordchars_utf16();
+}
+
+const std::vector<w_char>& HunspellImpl::get_wordchars_utf16() const {
return pAMgr->get_wordchars_utf16();
}
-void Hunspell::mkinitcap(std::string& u8) {
+void HunspellImpl::mkinitcap(std::string& u8) {
if (utf8) {
std::vector<w_char> u16;
u8_u16(u16, u8);
::mkinitcap_utf(u16, langnum);
u16_u8(u