summaryrefslogtreecommitdiffstats
path: root/chrome/third_party
diff options
context:
space:
mode:
authorhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-03 03:53:44 +0000
committerhbono@chromium.org <hbono@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-03 03:53:44 +0000
commit08e6413a6565ba434e1054a1df1c9fb778dad352 (patch)
tree425f5fefcb1f725c64f28a8e300cc5be565fe5f9 /chrome/third_party
parent1de71a4f741bc78e00dbb1da2b6419ce1b619562 (diff)
downloadchromium_src-08e6413a6565ba434e1054a1df1c9fb778dad352.zip
chromium_src-08e6413a6565ba434e1054a1df1c9fb778dad352.tar.gz
chromium_src-08e6413a6565ba434e1054a1df1c9fb778dad352.tar.bz2
Replacing CRLF line endings with LF and add svn:eol-style to LF.
Your Revision 2322 somehow changed the line endings of a file to CRLF. So, this change replaces its line endings back to LF and adds svn:eol-style to LF. Review URL: http://codereview.chromium.org/19702 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9068 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/third_party')
-rw-r--r--chrome/third_party/hunspell/src/hunspell/hashmgr.cxx1912
1 files changed, 956 insertions, 956 deletions
diff --git a/chrome/third_party/hunspell/src/hunspell/hashmgr.cxx b/chrome/third_party/hunspell/src/hunspell/hashmgr.cxx
index 71f2964..1926c852 100644
--- a/chrome/third_party/hunspell/src/hunspell/hashmgr.cxx
+++ b/chrome/third_party/hunspell/src/hunspell/hashmgr.cxx
@@ -1,956 +1,956 @@
-#include "license.hunspell"
-#include "license.myspell"
-
-#ifndef MOZILLA_CLIENT
-#include <cstdlib>
-#include <cstring>
-#include <cstdio>
-#include <cctype>
-#else
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#endif
-
-#include "hashmgr.hxx"
-#include "csutil.hxx"
-#include "atypes.hxx"
-
-#ifdef MOZILLA_CLIENT
-#ifdef __SUNPRO_CC // for SunONE Studio compiler
-using namespace std;
-#endif
-#else
-#ifndef W32
-using namespace std;
-#endif
-#endif
-
-// build a hash table from a munched word list
-#ifdef HUNSPELL_CHROME_CLIENT
-HashMgr::HashMgr(hunspell::BDictReader* reader)
-{
- bdict_reader = reader;
-#else
-HashMgr::HashMgr(FILE* dic_handle, FILE* aff_handle)
-{
-#endif
- tablesize = 0;
- tableptr = NULL;
- flag_mode = FLAG_CHAR;
- complexprefixes = 0;
- utf8 = 0;
- ignorechars = NULL;
- ignorechars_utf16 = NULL;
- ignorechars_utf16_len = 0;
- numaliasf = 0;
- aliasf = NULL;
- numaliasm = 0;
- aliasm = NULL;
-#ifdef HUNSPELL_CHROME_CLIENT
- // No tables to load, just the AF config.
- int ec = load_config();
-#else
- load_config(aff_handle);
- int ec = load_tables(dic_handle);
-#endif
- if (ec) {
- /* error condition - what should we do here */
- HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n",ec);
- if (tableptr) {
- free(tableptr);
- tableptr = NULL;
- }
- 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++) {
- struct hentry * pt = &tableptr[i];
- struct hentry * nt = NULL;
- if (pt) {
- if (pt->astr && !aliasf) free(pt->astr);
- if (pt->word) free(pt->word);
-#ifdef HUNSPELL_EXPERIMENTAL
- if (pt->description && !aliasm) free(pt->description);
-#endif
- pt = pt->next;
- }
- while(pt) {
- nt = pt->next;
- if (pt->astr && !aliasf) free(pt->astr);
- if (pt->word) free(pt->word);
-#ifdef HUNSPELL_EXPERIMENTAL
- if (pt->description && !aliasm) free(pt->description);
-#endif
- free(pt);
- pt = nt;
- }
- }
- free(tableptr);
- tableptr = NULL;
- }
- tablesize = 0;
-
- if (aliasf) {
- for (int j = 0; j < (numaliasf); j++) free(aliasf[j]);
- free(aliasf);
- aliasf = NULL;
- if (aliasflen) {
- free(aliasflen);
- aliasflen = NULL;
- }
- }
- if (aliasm) {
- for (int j = 0; j < (numaliasm); j++) free(aliasm[j]);
- free(aliasm);
- aliasm = NULL;
- }
-
- if (ignorechars) free(ignorechars);
- if (ignorechars_utf16) free(ignorechars_utf16);
-
-#ifdef HUNSPELL_CHROME_CLIENT
- EmptyHentryCache();
- for (std::vector<std::string*>::iterator it = pointer_to_strings_.begin();
- it != pointer_to_strings_.end(); ++it) {
- delete *it;
- }
-#endif
-}
-
-#ifdef HUNSPELL_CHROME_CLIENT
-void HashMgr::EmptyHentryCache() {
- // We need to delete each cache entry, and each additional one in the linked
- // list of homonyms.
- for (HEntryCache::iterator i = hentry_cache.begin();
- i != hentry_cache.end(); ++i) {
- hentry* cur = i->second;
- while (cur) {
- hentry* next = cur->next_homonym;
- delete cur;
- cur = next;
- }
- }
- hentry_cache.clear();
-}
-#endif
-
-// lookup a root word in the hashtable
-
-struct hentry * HashMgr::lookup(const char *word) const
-{
-#ifdef HUNSPELL_CHROME_CLIENT
- int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD];
- int affix_count = bdict_reader->FindWord(word, affix_ids);
- if (affix_count == 0) { // look for custom added word
- std::map<StringPiece, int>::const_iterator iter =
- custom_word_to_affix_id_map_.find(word);
- if (iter != custom_word_to_affix_id_map_.end()) {
- affix_count = 1;
- affix_ids[0] = iter->second;
- }
- }
-
- static const int kMaxWordLen = 128;
- static char word_buf[kMaxWordLen];
- strncpy(word_buf, word, kMaxWordLen);
-
- return AffixIDsToHentry(word_buf, affix_ids, affix_count);
-#else
- struct hentry * dp;
- if (tableptr) {
- dp = &tableptr[hash(word)];
- if (dp->word == NULL) return NULL;
- for ( ; dp != NULL; dp = dp->next) {
- if (strcmp(word,dp->word) == 0) return dp;
- }
- }
- return NULL;
-#endif
-}
-
-// add a word to the hash table (private)
-
-int HashMgr::add_word(const char * word, int wl, unsigned short * aff, int al, const char * desc)
-{
-#ifndef HUNSPELL_CHROME_CLIENT
- char * st = mystrdup(word);
- if (wl && !st) return 1;
- if (ignorechars != NULL) {
- if (utf8) {
- remove_ignored_chars_utf(st, ignorechars_utf16, ignorechars_utf16_len);
- } else {
- remove_ignored_chars(st, ignorechars);
- }
- }
- if (complexprefixes) {
- if (utf8) reverseword_utf(st); else reverseword(st);
- }
- int i = hash(st);
- struct hentry * dp = &tableptr[i];
- if (dp->word == NULL) {
- dp->wlen = (short) wl;
- dp->alen = (short) al;
- dp->word = st;
- dp->astr = aff;
- dp->next = NULL;
- dp->next_homonym = NULL;
-#ifdef HUNSPELL_EXPERIMENTAL
- if (aliasm) {
- dp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
- } else {
- dp->description = mystrdup(desc);
- if (desc && !dp->description) return 1;
- if (dp->description && complexprefixes) {
- if (utf8) reverseword_utf(dp->description); else reverseword(dp->description);
- }
- }
-#endif
- } else {
- struct hentry* hp = (struct hentry *) malloc (sizeof(struct hentry));
- if (!hp) return 1;
- hp->wlen = (short) wl;
- hp->alen = (short) al;
- hp->word = st;
- hp->astr = aff;
- hp->next = NULL;
- hp->next_homonym = NULL;
-#ifdef HUNSPELL_EXPERIMENTAL
- if (aliasm) {
- hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
- } else {
- hp->description = mystrdup(desc);
- if (desc && !hp->description) return 1;
- if (dp->description && complexprefixes) {
- if (utf8) reverseword_utf(hp->description); else reverseword(hp->description);
- }
- }
-#endif
- while (dp->next != NULL) {
- if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) dp->next_homonym = hp;
- dp=dp->next;
- }
- if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) dp->next_homonym = hp;
- dp->next = hp;
- }
-#endif // HUNSPELL_CHROME_CLIENT
- std::map<StringPiece, int>::iterator iter =
- custom_word_to_affix_id_map_.find(word);
- if(iter == custom_word_to_affix_id_map_.end()) { // word needs to be added
- std::string* new_string_word = new std::string(word);
- pointer_to_strings_.push_back(new_string_word);
- StringPiece sp(*(new_string_word));
- custom_word_to_affix_id_map_[sp] = 0; // no affixes for custom words
- return 1;
- }
-
- return 0;
-}
-
-// add a custom dic. word to the hash table (public)
-int HashMgr::put_word(const char * word, int wl, char * aff)
-{
- unsigned short * flags;
- int al = 0;
- if (aff) {
- al = decode_flags(&flags, aff);
- flag_qsort(flags, 0, al);
- } else {
- flags = NULL;
- }
- add_word(word, wl, flags, al, NULL);
- return 0;
-}
-
-int HashMgr::put_word_pattern(const char * word, int wl, const char * pattern)
-{
- unsigned short * flags;
- struct hentry * dp = lookup(pattern);
- if (!dp || !dp->astr) return 1;
- flags = (unsigned short *) malloc (dp->alen * sizeof(short));
- memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short));
- add_word(word, wl, flags, dp->alen, NULL);
- return 0;
-}
-
-// walk the hash table entry by entry - null at end
-struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const
-{
-#ifdef HUNSPELL_CHROME_CLIENT
- // This function creates a new hentry if NULL is passed as hp. It also takes
- // the responsibility of deleting the pointer hp when walk is over.
-
- // This function is only ever called by one place and not nested. We can
- // therefore keep static state between calls and use |col| as a "reset" flag
- // to avoid changing the API. It is set to -1 for the first call.
- static hunspell::WordIterator word_iterator =
- bdict_reader->GetAllWordIterator();
- if (col < 0) {
- col = 1;
- word_iterator = bdict_reader->GetAllWordIterator();
- }
-
- int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD];
- static const int kMaxWordLen = 128;
- static char word[kMaxWordLen];
- int affix_count = word_iterator.Advance(word, kMaxWordLen, affix_ids);
- if (affix_count == 0) {
- delete hp;
- return NULL;
- }
- short word_len = static_cast<short>(strlen(word));
-
- // For now, just re-compute the |hp| and return it. No need to create linked
- // lists for the extra affixes. If hp is NULL, create it here.
- if (!hp)
- hp = new hentry;
- hp->word = word;
- hp->wlen = word_len;
- hp->alen = (short)const_cast<HashMgr*>(this)->get_aliasf(affix_ids[0],
- &hp->astr);
- hp->next = NULL;
- hp->next_homonym = NULL;
-
- return hp;
-#else
- //reset to start
- if ((col < 0) || (hp == NULL)) {
- col = -1;
- hp = NULL;
- }
-
- if (hp && hp->next != NULL) {
- hp = hp->next;
- } else {
- col++;
- hp = (col < tablesize) ? &tableptr[col] : NULL;
- // search for next non-blank column entry
- while (hp && (hp->word == NULL)) {
- col ++;
- hp = (col < tablesize) ? &tableptr[col] : NULL;
- }
- if (col < tablesize) return hp;
- hp = NULL;
- col = -1;
- }
- return hp;
-#endif
-}
-
-// load a munched word list and build a hash table on the fly
-int HashMgr::load_tables(FILE* t_handle)
-{
-#ifndef HUNSPELL_CHROME_CLIENT
- int wl, al;
- char * ap;
- char * dp;
- unsigned short * flags;
-
- // raw dictionary - munched file
- FILE * rawdict = _fdopen(_dup(_fileno(t_handle)), "r");
- if (rawdict == NULL) return 1;
- fseek(rawdict, 0, SEEK_SET);
-
- // first read the first line of file to get hash table size */
- char ts[MAXDELEN];
- if (! fgets(ts, MAXDELEN-1,rawdict)) return 2;
- mychomp(ts);
-
- /* remove byte order mark */
- if (strncmp(ts,"\xef\xbb\xbf",3) == 0) {
- memmove(ts, ts+3, strlen(ts+3)+1);
- HUNSPELL_WARNING(stderr, "warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions\n");
- }
-
- if ((*ts < '1') || (*ts > '9')) HUNSPELL_WARNING(stderr, "error - missing word count in dictionary file\n");
- tablesize = atoi(ts);
- if (!tablesize) return 4;
- tablesize = tablesize + 5 + USERWORD;
- if ((tablesize %2) == 0) tablesize++;
-
- // allocate the hash table
- tableptr = (struct hentry *) calloc(tablesize, sizeof(struct hentry));
- if (! tableptr) return 3;
- for (int i=0; i<tablesize; i++) tableptr[i].word = NULL;
-
- // loop through all words on much list and add to hash
- // table and create word and affix strings
-
- while (fgets(ts,MAXDELEN-1,rawdict)) {
- mychomp(ts);
- // split each line into word and morphological description
- dp = strchr(ts,'\t');
-
- if (dp) {
- *dp = '\0';
- dp++;
- } else {
- dp = NULL;
- }
-
- // 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++;
- continue;
- } else if (*(ap - 1) != '\\') break;
- // replace "\/" with "/"
- for (char * sp = ap - 1; *sp; *sp = *(sp + 1), sp++);
- ap = strchr(ap,'/');
- }
-
- if (ap) {
- *ap = '\0';
- if (aliasf) {
- int index = atoi(ap + 1);
- al = get_aliasf(index, &flags);
- if (!al) {
- HUNSPELL_WARNING(stderr, "error - bad flag vector alias: %s\n", ts);
- *ap = '\0';
- }
- } else {
- al = decode_flags(&flags, ap + 1);
- flag_qsort(flags, 0, al);
- }
- } else {
- al = 0;
- ap = NULL;
- flags = NULL;
- }
-
- wl = strlen(ts);
-
- // add the word and its index
- if (add_word(ts,wl,flags,al,dp)) return 5;
-
- }
-
- fclose(rawdict);
-#endif
- return 0;
-}
-
-
-// the hash function is a simple load and rotate
-// algorithm borrowed
-
-int HashMgr::hash(const char * word) const
-{
-#ifdef HUNSPELL_CHROME_CLIENT
- return 0;
-#else
- long hv = 0;
- for (int i=0; i < 4 && *word != 0; i++)
- hv = (hv << 8) | (*word++);
- while (*word != 0) {
- ROTATE(hv,ROTATE_LEN);
- hv ^= (*word++);
- }
- return (unsigned long) hv % tablesize;
-#endif
-}
-
-int HashMgr::decode_flags(unsigned short ** result, char * flags) {
- int len;
- switch (flag_mode) {
- case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
- len = strlen(flags);
- if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: length of FLAG_LONG flagvector is odd: %s\n", flags);
- len = len/2;
- *result = (unsigned short *) malloc(len * sizeof(short));
- for (int i = 0; i < len; i++) {
- (*result)[i] = (((unsigned short) flags[i * 2]) << 8) + (unsigned short) flags[i * 2 + 1];
- }
- break;
- }
- case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521 23 233)
- len = 1;
- char * src = flags;
- unsigned short * dest;
- char * p;
- for (p = flags; *p; p++) {
- if (*p == ',') len++;
- }
- *result = (unsigned short *) malloc(len * sizeof(short));
- dest = *result;
- for (p = flags; *p; p++) {
- if (*p == ',') {
- *dest = (unsigned short) atoi(src);
- if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
- src = p + 1;
- dest++;
- }
- }
- *dest = (unsigned short) atoi(src);
- if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
- break;
- }
- case FLAG_UNI: { // UTF-8 characters
- w_char w[MAXDELEN/2];
- len = u8_u16(w, MAXDELEN/2, flags);
- *result = (unsigned short *) malloc(len * sizeof(short));
- memcpy(*result, w, len * sizeof(short));
- break;
- }
- default: { // Ispell's one-character flags (erfg -> e r f g)
- unsigned short * dest;
- len = strlen(flags);
- *result = (unsigned short *) malloc(len * sizeof(short));
- dest = *result;
- for (unsigned char * p = (unsigned char *) flags; *p; p++) {
- *dest = (unsigned short) *p;
- dest++;
- }
- }
- }
- return len;
-}
-
-unsigned short HashMgr::decode_flag(const char * f) {
- unsigned short s = 0;
- switch (flag_mode) {
- case FLAG_LONG:
- s = ((unsigned short) f[0] << 8) + (unsigned short) f[1];
- break;
- case FLAG_NUM:
- s = (unsigned short) atoi(f);
- break;
- case FLAG_UNI:
- u8_u16((w_char *) &s, 1, f);
- break;
- default:
- s = (unsigned short) *((unsigned char *)f);
- }
- if (!s) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
- return s;
-}
-
-char * HashMgr::encode_flag(unsigned short f) {
- unsigned char ch[10];
- if (f==0) return mystrdup("(NULL)");
- if (flag_mode == FLAG_LONG) {
- ch[0] = (unsigned char) (f >> 8);
- ch[1] = (unsigned char) (f - ((f >> 8) << 8));
- ch[2] = '\0';
- } else if (flag_mode == FLAG_NUM) {
- sprintf((char *) ch, "%d", f);
- } else if (flag_mode == FLAG_UNI) {
- u16_u8((char *) &ch, 10, (w_char *) &f, 1);
- } else {
- ch[0] = (unsigned char) (f);
- ch[1] = '\0';
- }
- return mystrdup((char *) ch);
-}
-
-#ifdef HUNSPELL_CHROME_CLIENT
-int HashMgr::load_config()
-{
- utf8 = 1; // We always use UTF-8.
-
- // Read in all the AF lines which tell us the rules for each affix group ID.
- char line[MAXDELEN+1];
- hunspell::LineIterator iterator = bdict_reader->GetAfLineIterator();
- while (iterator.AdvanceAndCopy(line, MAXDELEN)) {
- int rv = parse_aliasf(line, &iterator);
- if (rv)
- return rv;
- }
-
- // Read in the regular commands from the affix file. We only care about the
- // IGNORE line here. The rest of the commands will be read by the affix
- // manager.
- iterator = bdict_reader->GetOtherLineIterator();
- while (iterator.AdvanceAndCopy(line, MAXDELEN)) {
- // Parse in the ignored characters (for example, Arabic optional
- // diacritics characters.
- if (strncmp(line,"IGNORE",6) == 0) {
- parse_array(line, &ignorechars, &ignorechars_utf16,
- &ignorechars_utf16_len, "IGNORE", utf8);
- break; // All done.
- }
- }
-
- return 0;
-}
-#else
-// read in aff file and set flag mode
-int HashMgr::load_config(FILE* aff_handle)
-{
- int firstline = 1;
-
- // io buffers
- char line[MAXDELEN+1];
-
- // open the affix file
- FILE * afflst;
- afflst = _fdopen(_dup(_fileno(aff_handle)), "r");
- if (!afflst) {
- HUNSPELL_WARNING(stderr, "Error - could not open affix description file\n");
- return 1;
- }
- fseek(afflst, 0, SEEK_SET);
-
- // read in each line ignoring any that do not
- // start with a known line type indicator
-
- while (fgets(line,MAXDELEN,afflst)) {
- 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);
- }
-
- /* parse in the try string */
- if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) {
- if (flag_mode != FLAG_CHAR) {
- HUNSPELL_WARNING(stderr, "error: duplicate FLAG parameter\n");
- }
- if (strstr(line, "long")) flag_mode = FLAG_LONG;
- if (strstr(line, "num")) flag_mode = FLAG_NUM;
- if (strstr(line, "UTF-8")) flag_mode = FLAG_UNI;
- if (flag_mode == FLAG_CHAR) {
- HUNSPELL_WARNING(stderr, "error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line);
- }
- }
- if ((strncmp(line,"SET",3) == 0) && isspace(line[3]) && strstr(line, "UTF-8")) utf8 = 1;
-
- /* parse in the ignored characters (for example, Arabic optional diacritics characters */
- if (strncmp(line,"IGNORE",6) == 0) {
- if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) {
- fclose(afflst);
- return 1;
- }
- }
-
- if ((strncmp(line,"AF",2) == 0) && isspace(line[2])) {
- if (parse_aliasf(line, afflst)) {
- fclose(afflst);
- return 1;
- }
- }
-
-#ifdef HUNSPELL_EXPERIMENTAL
- if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) {
- if (parse_aliasm(line, afflst)) {
- fclose(afflst);
- return 1;
- }
- }
-#endif
- if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1;
- if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break;
- }
- fclose(afflst);
- return 0;
-}
-#endif // HUNSPELL_CHROME_CLIENT
-
-/* parse in the ALIAS table */
-#ifdef HUNSPELL_CHROME_CLIENT
-int HashMgr::parse_aliasf(char* line, hunspell::LineIterator* iterator)
-{
-#else
-int HashMgr::parse_aliasf(char * line, FILE * af)
-{
-#endif
- if (numaliasf != 0) {
- HUNSPELL_WARNING(stderr, "error: duplicate AF (alias for flag vector) tables used\n");
- 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: {
- numaliasf = atoi(piece);
- if (numaliasf < 1) {
- numaliasf = 0;
- aliasf = NULL;
- aliasflen = NULL;
- HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n");
- free(piece);
- return 1;
- }
- aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *));
- aliasflen = (unsigned short *) malloc(numaliasf * sizeof(short));
- if (!aliasf || !aliasflen) {
- numaliasf = 0;
- if (aliasf) free(aliasf);
- if (aliasflen) free(aliasflen);
- aliasf = NULL;
- aliasflen = NULL;
- return 1;
- }
- np++;
- break;
- }
- default: break;
- }
- i++;
- }
- free(piece);
- piece = mystrsep(&tp, 0);
- }
- if (np != 2) {
- numaliasf = 0;
- free(aliasf);
- free(aliasflen);
- aliasf = NULL;
- aliasflen = NULL;
- HUNSPELL_WARNING(stderr, "error: missing AF table information\n");
- return 1;
- }
-
- /* now parse the numaliasf lines to read in the remainder of the table */
- char * nl = line;
- for (int j=0; j < numaliasf; j++) {
-#ifdef HUNSPELL_CHROME_CLIENT
- if (!iterator->AdvanceAndCopy(nl, MAXDELEN))
- return 1;
-#else
- if (!fgets(nl,MAXDELEN,af)) return 1;
-#endif
- 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: AF table is corrupt\n");
- free(piece);
- return 1;
- }
- break;
- }
- case 1: {
- aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece);
- flag_qsort(aliasf[j], 0, aliasflen[j]);
- break;
- }
- default: break;
- }
- i++;
- }
- free(piece);
- piece = mystrsep(&tp, 0);
- }
- if (!aliasf[j]) {
- free(aliasf);
- free(aliasflen);
- aliasf = NULL;
- aliasflen = NULL;
- numaliasf = 0;
- HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
- return 1;
- }
- }
- return 0;
-}
-
-#ifdef HUNSPELL_CHROME_CLIENT
-hentry* HashMgr::AffixIDsToHentry(char* word,
- int* affix_ids,
- int affix_count) const
-{
- if (affix_count == 0)
- return NULL;
-
- HEntryCache& cache = const_cast<HashMgr*>(this)->hentry_cache;
- std::string std_word(word);
- HEntryCache::iterator found = cache.find(std_word);
- if (found != cache.end()) {
- // We must return an existing hentry for the same word if we've previously
- // handed one out. Hunspell will compare pointers in some cases to see if
- // two words it has found are the same.
- return found->second;
- }
-
- short word_len = static_cast<short>(strlen(word));
-
- // We can get a number of prefixes per word. There will normally be only one,
- // but if not, there will be a linked list of "hentry"s for the "homonym"s
- // for the word.
- struct hentry* first_he = NULL;
- struct hentry* prev_he = NULL; // For making linked list.
- for (int i = 0; i < affix_count; i++) {
- struct hentry* he = new hentry;
- if (i == 0)
- first_he = he;
- he->word = word;
- he->wlen = word_len;
- he->alen = (short)const_cast<HashMgr*>(this)->get_aliasf(affix_ids[i],
- &he->astr);
- he->next = NULL;
- he->next_homonym = NULL;
- if (prev_he)
- prev_he->next_homonym = he;
- prev_he = he;
- }
-
- cache[std_word] = first_he; // Save this word in the cache for later.
- return first_he;
-}
-
-#endif
-
-#ifdef HUNSPELL_CHROME_CLIENT
-hentry* HashMgr::GetHentryFromHEntryCache(char* word) {
- HEntryCache& cache = const_cast<HashMgr*>(this)->hentry_cache;
- std::string std_word(word);
- HEntryCache::iterator found = cache.find(std_word);
- if (found != cache.end())
- return found->second;
- else
- return NULL;
-}
-
-#endif
-
-int HashMgr::is_aliasf() {
- return (aliasf != NULL);
-}
-
-int HashMgr::get_aliasf(int index, unsigned short ** fvec) {
- if ((index > 0) && (index <= numaliasf)) {
- *fvec = aliasf[index - 1];
- return aliasflen[index - 1];
- }
- HUNSPELL_WARNING(stderr, "error: bad flag alias index: %d\n", index);
- *fvec = NULL;
- return 0;
-}
-
-#ifdef HUNSPELL_EXPERIMENTAL
-/* parse morph alias definitions */
-int HashMgr::parse_aliasm(char * line, FILE * af)
-{
- if (numaliasm != 0) {
- HUNSPELL_WARNING(stderr, "error: duplicate AM (aliases for morphological descriptions) tables used\n");
- 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: {
- numaliasm = atoi(piece);
- if (numaliasm < 1) {
- HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n");
- free(piece);
- return 1;
- }
- aliasm = (char **) malloc(numaliasm * sizeof(char *));
- if (!aliasm) {
- numaliasm = 0;
- return 1;
- }
- np++;
- break;
- }
- default: break;
- }
- i++;
- }
- free(piece);
- piece = mystrsep(&tp, 0);
- }
- if (np != 2) {
- numaliasm = 0;
- free(aliasm);
- aliasm = NULL;
- HUNSPELL_WARNING(stderr, "error: missing AM alias information\n");
- return 1;
- }
-
- /* now parse the numaliasm lines to read in the remainder of the table */
- char * nl = line;
- for (int j=0; j < numaliasm; j++) {
- if (!fgets(nl,MAXDELEN,af)) return 1;
- mychomp(nl);
- tp = nl;
- i = 0;
- aliasm[j] = NULL;
- piece = mystrsep(&tp, 0);
- while (piece) {
- if (*piece != '\0') {
- switch(i) {
- case 0: {
- if (strncmp(piece,"AM",2) != 0) {
- HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n");
- free(piece);
- numaliasm = 0;
- free(aliasm);
- aliasm = NULL;
- return 1;
- }
- break;
- }
- case 1: {
- if (complexprefixes) {
- if (utf8) reverseword_utf(piece);
- else reverseword(piece);
- }
- aliasm[j] = mystrdup(piece);
- break; }
- default: break;
- }
- i++;
- }
- free(piece);
- piece = mystrsep(&tp, 0);
- }
- if (!aliasm[j]) {
- numaliasm = 0;
- free(aliasm);
- aliasm = NULL;
- HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
- return 1;
- }
- }
- return 0;
-}
-
-int HashMgr::is_aliasm() {
- return (aliasm != NULL);
-}
-
-char * HashMgr::get_aliasm(int index) {
- if ((index > 0) && (index <= numaliasm)) return aliasm[index - 1];
- HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index);
- return NULL;
-}
-#endif
+#include "license.hunspell"
+#include "license.myspell"
+
+#ifndef MOZILLA_CLIENT
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cctype>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#endif
+
+#include "hashmgr.hxx"
+#include "csutil.hxx"
+#include "atypes.hxx"
+
+#ifdef MOZILLA_CLIENT
+#ifdef __SUNPRO_CC // for SunONE Studio compiler
+using namespace std;
+#endif
+#else
+#ifndef W32
+using namespace std;
+#endif
+#endif
+
+// build a hash table from a munched word list
+#ifdef HUNSPELL_CHROME_CLIENT
+HashMgr::HashMgr(hunspell::BDictReader* reader)
+{
+ bdict_reader = reader;
+#else
+HashMgr::HashMgr(FILE* dic_handle, FILE* aff_handle)
+{
+#endif
+ tablesize = 0;
+ tableptr = NULL;
+ flag_mode = FLAG_CHAR;
+ complexprefixes = 0;
+ utf8 = 0;
+ ignorechars = NULL;
+ ignorechars_utf16 = NULL;
+ ignorechars_utf16_len = 0;
+ numaliasf = 0;
+ aliasf = NULL;
+ numaliasm = 0;
+ aliasm = NULL;
+#ifdef HUNSPELL_CHROME_CLIENT
+ // No tables to load, just the AF config.
+ int ec = load_config();
+#else
+ load_config(aff_handle);
+ int ec = load_tables(dic_handle);
+#endif
+ if (ec) {
+ /* error condition - what should we do here */
+ HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n",ec);
+ if (tableptr) {
+ free(tableptr);
+ tableptr = NULL;
+ }
+ 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++) {
+ struct hentry * pt = &tableptr[i];
+ struct hentry * nt = NULL;
+ if (pt) {
+ if (pt->astr && !aliasf) free(pt->astr);
+ if (pt->word) free(pt->word);
+#ifdef HUNSPELL_EXPERIMENTAL
+ if (pt->description && !aliasm) free(pt->description);
+#endif
+ pt = pt->next;
+ }
+ while(pt) {
+ nt = pt->next;
+ if (pt->astr && !aliasf) free(pt->astr);
+ if (pt->word) free(pt->word);
+#ifdef HUNSPELL_EXPERIMENTAL
+ if (pt->description && !aliasm) free(pt->description);
+#endif
+ free(pt);
+ pt = nt;
+ }
+ }
+ free(tableptr);
+ tableptr = NULL;
+ }
+ tablesize = 0;
+
+ if (aliasf) {
+ for (int j = 0; j < (numaliasf); j++) free(aliasf[j]);
+ free(aliasf);
+ aliasf = NULL;
+ if (aliasflen) {
+ free(aliasflen);
+ aliasflen = NULL;
+ }
+ }
+ if (aliasm) {
+ for (int j = 0; j < (numaliasm); j++) free(aliasm[j]);
+ free(aliasm);
+ aliasm = NULL;
+ }
+
+ if (ignorechars) free(ignorechars);
+ if (ignorechars_utf16) free(ignorechars_utf16);
+
+#ifdef HUNSPELL_CHROME_CLIENT
+ EmptyHentryCache();
+ for (std::vector<std::string*>::iterator it = pointer_to_strings_.begin();
+ it != pointer_to_strings_.end(); ++it) {
+ delete *it;
+ }
+#endif
+}
+
+#ifdef HUNSPELL_CHROME_CLIENT
+void HashMgr::EmptyHentryCache() {
+ // We need to delete each cache entry, and each additional one in the linked
+ // list of homonyms.
+ for (HEntryCache::iterator i = hentry_cache.begin();
+ i != hentry_cache.end(); ++i) {
+ hentry* cur = i->second;
+ while (cur) {
+ hentry* next = cur->next_homonym;
+ delete cur;
+ cur = next;
+ }
+ }
+ hentry_cache.clear();
+}
+#endif
+
+// lookup a root word in the hashtable
+
+struct hentry * HashMgr::lookup(const char *word) const
+{
+#ifdef HUNSPELL_CHROME_CLIENT
+ int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD];
+ int affix_count = bdict_reader->FindWord(word, affix_ids);
+ if (affix_count == 0) { // look for custom added word
+ std::map<StringPiece, int>::const_iterator iter =
+ custom_word_to_affix_id_map_.find(word);
+ if (iter != custom_word_to_affix_id_map_.end()) {
+ affix_count = 1;
+ affix_ids[0] = iter->second;
+ }
+ }
+
+ static const int kMaxWordLen = 128;
+ static char word_buf[kMaxWordLen];
+ strncpy(word_buf, word, kMaxWordLen);
+
+ return AffixIDsToHentry(word_buf, affix_ids, affix_count);
+#else
+ struct hentry * dp;
+ if (tableptr) {
+ dp = &tableptr[hash(word)];
+ if (dp->word == NULL) return NULL;
+ for ( ; dp != NULL; dp = dp->next) {
+ if (strcmp(word,dp->word) == 0) return dp;
+ }
+ }
+ return NULL;
+#endif
+}
+
+// add a word to the hash table (private)
+
+int HashMgr::add_word(const char * word, int wl, unsigned short * aff, int al, const char * desc)
+{
+#ifndef HUNSPELL_CHROME_CLIENT
+ char * st = mystrdup(word);
+ if (wl && !st) return 1;
+ if (ignorechars != NULL) {
+ if (utf8) {
+ remove_ignored_chars_utf(st, ignorechars_utf16, ignorechars_utf16_len);
+ } else {
+ remove_ignored_chars(st, ignorechars);
+ }
+ }
+ if (complexprefixes) {
+ if (utf8) reverseword_utf(st); else reverseword(st);
+ }
+ int i = hash(st);
+ struct hentry * dp = &tableptr[i];
+ if (dp->word == NULL) {
+ dp->wlen = (short) wl;
+ dp->alen = (short) al;
+ dp->word = st;
+ dp->astr = aff;
+ dp->next = NULL;
+ dp->next_homonym = NULL;
+#ifdef HUNSPELL_EXPERIMENTAL
+ if (aliasm) {
+ dp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
+ } else {
+ dp->description = mystrdup(desc);
+ if (desc && !dp->description) return 1;
+ if (dp->description && complexprefixes) {
+ if (utf8) reverseword_utf(dp->description); else reverseword(dp->description);
+ }
+ }
+#endif
+ } else {
+ struct hentry* hp = (struct hentry *) malloc (sizeof(struct hentry));
+ if (!hp) return 1;
+ hp->wlen = (short) wl;
+ hp->alen = (short) al;
+ hp->word = st;
+ hp->astr = aff;
+ hp->next = NULL;
+ hp->next_homonym = NULL;
+#ifdef HUNSPELL_EXPERIMENTAL
+ if (aliasm) {
+ hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
+ } else {
+ hp->description = mystrdup(desc);
+ if (desc && !hp->description) return 1;
+ if (dp->description && complexprefixes) {
+ if (utf8) reverseword_utf(hp->description); else reverseword(hp->description);
+ }
+ }
+#endif
+ while (dp->next != NULL) {
+ if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) dp->next_homonym = hp;
+ dp=dp->next;
+ }
+ if ((!dp->next_homonym) && (strcmp(hp->word, dp->word) == 0)) dp->next_homonym = hp;
+ dp->next = hp;
+ }
+#endif // HUNSPELL_CHROME_CLIENT
+ std::map<StringPiece, int>::iterator iter =
+ custom_word_to_affix_id_map_.find(word);
+ if(iter == custom_word_to_affix_id_map_.end()) { // word needs to be added
+ std::string* new_string_word = new std::string(word);
+ pointer_to_strings_.push_back(new_string_word);
+ StringPiece sp(*(new_string_word));
+ custom_word_to_affix_id_map_[sp] = 0; // no affixes for custom words
+ return 1;
+ }
+
+ return 0;
+}
+
+// add a custom dic. word to the hash table (public)
+int HashMgr::put_word(const char * word, int wl, char * aff)
+{
+ unsigned short * flags;
+ int al = 0;
+ if (aff) {
+ al = decode_flags(&flags, aff);
+ flag_qsort(flags, 0, al);
+ } else {
+ flags = NULL;
+ }
+ add_word(word, wl, flags, al, NULL);
+ return 0;
+}
+
+int HashMgr::put_word_pattern(const char * word, int wl, const char * pattern)
+{
+ unsigned short * flags;
+ struct hentry * dp = lookup(pattern);
+ if (!dp || !dp->astr) return 1;
+ flags = (unsigned short *) malloc (dp->alen * sizeof(short));
+ memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short));
+ add_word(word, wl, flags, dp->alen, NULL);
+ return 0;
+}
+
+// walk the hash table entry by entry - null at end
+struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const
+{
+#ifdef HUNSPELL_CHROME_CLIENT
+ // This function creates a new hentry if NULL is passed as hp. It also takes
+ // the responsibility of deleting the pointer hp when walk is over.
+
+ // This function is only ever called by one place and not nested. We can
+ // therefore keep static state between calls and use |col| as a "reset" flag
+ // to avoid changing the API. It is set to -1 for the first call.
+ static hunspell::WordIterator word_iterator =
+ bdict_reader->GetAllWordIterator();
+ if (col < 0) {
+ col = 1;
+ word_iterator = bdict_reader->GetAllWordIterator();
+ }
+
+ int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD];
+ static const int kMaxWordLen = 128;
+ static char word[kMaxWordLen];
+ int affix_count = word_iterator.Advance(word, kMaxWordLen, affix_ids);
+ if (affix_count == 0) {
+ delete hp;
+ return NULL;
+ }
+ short word_len = static_cast<short>(strlen(word));
+
+ // For now, just re-compute the |hp| and return it. No need to create linked
+ // lists for the extra affixes. If hp is NULL, create it here.
+ if (!hp)
+ hp = new hentry;
+ hp->word = word;
+ hp->wlen = word_len;
+ hp->alen = (short)const_cast<HashMgr*>(this)->get_aliasf(affix_ids[0],
+ &hp->astr);
+ hp->next = NULL;
+ hp->next_homonym = NULL;
+
+ return hp;
+#else
+ //reset to start
+ if ((col < 0) || (hp == NULL)) {
+ col = -1;
+ hp = NULL;
+ }
+
+ if (hp && hp->next != NULL) {
+ hp = hp->next;
+ } else {
+ col++;
+ hp = (col < tablesize) ? &tableptr[col] : NULL;
+ // search for next non-blank column entry
+ while (hp && (hp->word == NULL)) {
+ col ++;
+ hp = (col < tablesize) ? &tableptr[col] : NULL;
+ }
+ if (col < tablesize) return hp;
+ hp = NULL;
+ col = -1;
+ }
+ return hp;
+#endif
+}
+
+// load a munched word list and build a hash table on the fly
+int HashMgr::load_tables(FILE* t_handle)
+{
+#ifndef HUNSPELL_CHROME_CLIENT
+ int wl, al;
+ char * ap;
+ char * dp;
+ unsigned short * flags;
+
+ // raw dictionary - munched file
+ FILE * rawdict = _fdopen(_dup(_fileno(t_handle)), "r");
+ if (rawdict == NULL) return 1;
+ fseek(rawdict, 0, SEEK_SET);
+
+ // first read the first line of file to get hash table size */
+ char ts[MAXDELEN];
+ if (! fgets(ts, MAXDELEN-1,rawdict)) return 2;
+ mychomp(ts);
+
+ /* remove byte order mark */
+ if (strncmp(ts,"\xef\xbb\xbf",3) == 0) {
+ memmove(ts, ts+3, strlen(ts+3)+1);
+ HUNSPELL_WARNING(stderr, "warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions\n");
+ }
+
+ if ((*ts < '1') || (*ts > '9')) HUNSPELL_WARNING(stderr, "error - missing word count in dictionary file\n");
+ tablesize = atoi(ts);
+ if (!tablesize) return 4;
+ tablesize = tablesize + 5 + USERWORD;
+ if ((tablesize %2) == 0) tablesize++;
+
+ // allocate the hash table
+ tableptr = (struct hentry *) calloc(tablesize, sizeof(struct hentry));
+ if (! tableptr) return 3;
+ for (int i=0; i<tablesize; i++) tableptr[i].word = NULL;
+
+ // loop through all words on much list and add to hash
+ // table and create word and affix strings
+
+ while (fgets(ts,MAXDELEN-1,rawdict)) {
+ mychomp(ts);
+ // split each line into word and morphological description
+ dp = strchr(ts,'\t');
+
+ if (dp) {
+ *dp = '\0';
+ dp++;
+ } else {
+ dp = NULL;
+ }
+
+ // 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++;
+ continue;
+ } else if (*(ap - 1) != '\\') break;
+ // replace "\/" with "/"
+ for (char * sp = ap - 1; *sp; *sp = *(sp + 1), sp++);
+ ap = strchr(ap,'/');
+ }
+
+ if (ap) {
+ *ap = '\0';
+ if (aliasf) {
+ int index = atoi(ap + 1);
+ al = get_aliasf(index, &flags);
+ if (!al) {
+ HUNSPELL_WARNING(stderr, "error - bad flag vector alias: %s\n", ts);
+ *ap = '\0';
+ }
+ } else {
+ al = decode_flags(&flags, ap + 1);
+ flag_qsort(flags, 0, al);
+ }
+ } else {
+ al = 0;
+ ap = NULL;
+ flags = NULL;
+ }
+
+ wl = strlen(ts);
+
+ // add the word and its index
+ if (add_word(ts,wl,flags,al,dp)) return 5;
+
+ }
+
+ fclose(rawdict);
+#endif
+ return 0;
+}
+
+
+// the hash function is a simple load and rotate
+// algorithm borrowed
+
+int HashMgr::hash(const char * word) const
+{
+#ifdef HUNSPELL_CHROME_CLIENT
+ return 0;
+#else
+ long hv = 0;
+ for (int i=0; i < 4 && *word != 0; i++)
+ hv = (hv << 8) | (*word++);
+ while (*word != 0) {
+ ROTATE(hv,ROTATE_LEN);
+ hv ^= (*word++);
+ }
+ return (unsigned long) hv % tablesize;
+#endif
+}
+
+int HashMgr::decode_flags(unsigned short ** result, char * flags) {
+ int len;
+ switch (flag_mode) {
+ case FLAG_LONG: { // two-character flags (1x2yZz -> 1x 2y Zz)
+ len = strlen(flags);
+ if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: length of FLAG_LONG flagvector is odd: %s\n", flags);
+ len = len/2;
+ *result = (unsigned short *) malloc(len * sizeof(short));
+ for (int i = 0; i < len; i++) {
+ (*result)[i] = (((unsigned short) flags[i * 2]) << 8) + (unsigned short) flags[i * 2 + 1];
+ }
+ break;
+ }
+ case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521 23 233)
+ len = 1;
+ char * src = flags;
+ unsigned short * dest;
+ char * p;
+ for (p = flags; *p; p++) {
+ if (*p == ',') len++;
+ }
+ *result = (unsigned short *) malloc(len * sizeof(short));
+ dest = *result;
+ for (p = flags; *p; p++) {
+ if (*p == ',') {
+ *dest = (unsigned short) atoi(src);
+ if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
+ src = p + 1;
+ dest++;
+ }
+ }
+ *dest = (unsigned short) atoi(src);
+ if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
+ break;
+ }
+ case FLAG_UNI: { // UTF-8 characters
+ w_char w[MAXDELEN/2];
+ len = u8_u16(w, MAXDELEN/2, flags);
+ *result = (unsigned short *) malloc(len * sizeof(short));
+ memcpy(*result, w, len * sizeof(short));
+ break;
+ }
+ default: { // Ispell's one-character flags (erfg -> e r f g)
+ unsigned short * dest;
+ len = strlen(flags);
+ *result = (unsigned short *) malloc(len * sizeof(short));
+ dest = *result;
+ for (unsigned char * p = (unsigned char *) flags; *p; p++) {
+ *dest = (unsigned short) *p;
+ dest++;
+ }
+ }
+ }
+ return len;
+}
+
+unsigned short HashMgr::decode_flag(const char * f) {
+ unsigned short s = 0;
+ switch (flag_mode) {
+ case FLAG_LONG:
+ s = ((unsigned short) f[0] << 8) + (unsigned short) f[1];
+ break;
+ case FLAG_NUM:
+ s = (unsigned short) atoi(f);
+ break;
+ case FLAG_UNI:
+ u8_u16((w_char *) &s, 1, f);
+ break;
+ default:
+ s = (unsigned short) *((unsigned char *)f);
+ }
+ if (!s) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n");
+ return s;
+}
+
+char * HashMgr::encode_flag(unsigned short f) {
+ unsigned char ch[10];
+ if (f==0) return mystrdup("(NULL)");
+ if (flag_mode == FLAG_LONG) {
+ ch[0] = (unsigned char) (f >> 8);
+ ch[1] = (unsigned char) (f - ((f >> 8) << 8));
+ ch[2] = '\0';
+ } else if (flag_mode == FLAG_NUM) {
+ sprintf((char *) ch, "%d", f);
+ } else if (flag_mode == FLAG_UNI) {
+ u16_u8((char *) &ch, 10, (w_char *) &f, 1);
+ } else {
+ ch[0] = (unsigned char) (f);
+ ch[1] = '\0';
+ }
+ return mystrdup((char *) ch);
+}
+
+#ifdef HUNSPELL_CHROME_CLIENT
+int HashMgr::load_config()
+{
+ utf8 = 1; // We always use UTF-8.
+
+ // Read in all the AF lines which tell us the rules for each affix group ID.
+ char line[MAXDELEN+1];
+ hunspell::LineIterator iterator = bdict_reader->GetAfLineIterator();
+ while (iterator.AdvanceAndCopy(line, MAXDELEN)) {
+ int rv = parse_aliasf(line, &iterator);
+ if (rv)
+ return rv;
+ }
+
+ // Read in the regular commands from the affix file. We only care about the
+ // IGNORE line here. The rest of the commands will be read by the affix
+ // manager.
+ iterator = bdict_reader->GetOtherLineIterator();
+ while (iterator.AdvanceAndCopy(line, MAXDELEN)) {
+ // Parse in the ignored characters (for example, Arabic optional
+ // diacritics characters.
+ if (strncmp(line,"IGNORE",6) == 0) {
+ parse_array(line, &ignorechars, &ignorechars_utf16,
+ &ignorechars_utf16_len, "IGNORE", utf8);
+ break; // All done.
+ }
+ }
+
+ return 0;
+}
+#else
+// read in aff file and set flag mode
+int HashMgr::load_config(FILE* aff_handle)
+{
+ int firstline = 1;
+
+ // io buffers
+ char line[MAXDELEN+1];
+
+ // open the affix file
+ FILE * afflst;
+ afflst = _fdopen(_dup(_fileno(aff_handle)), "r");
+ if (!afflst) {
+ HUNSPELL_WARNING(stderr, "Error - could not open affix description file\n");
+ return 1;
+ }
+ fseek(afflst, 0, SEEK_SET);
+
+ // read in each line ignoring any that do not
+ // start with a known line type indicator
+
+ while (fgets(line,MAXDELEN,afflst)) {
+ 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);
+ }
+
+ /* parse in the try string */
+ if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) {
+ if (flag_mode != FLAG_CHAR) {
+ HUNSPELL_WARNING(stderr, "error: duplicate FLAG parameter\n");
+ }
+ if (strstr(line, "long")) flag_mode = FLAG_LONG;
+ if (strstr(line, "num")) flag_mode = FLAG_NUM;
+ if (strstr(line, "UTF-8")) flag_mode = FLAG_UNI;
+ if (flag_mode == FLAG_CHAR) {
+ HUNSPELL_WARNING(stderr, "error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line);
+ }
+ }
+ if ((strncmp(line,"SET",3) == 0) && isspace(line[3]) && strstr(line, "UTF-8")) utf8 = 1;
+
+ /* parse in the ignored characters (for example, Arabic optional diacritics characters */
+ if (strncmp(line,"IGNORE",6) == 0) {
+ if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) {
+ fclose(afflst);
+ return 1;
+ }
+ }
+
+ if ((strncmp(line,"AF",2) == 0) && isspace(line[2])) {
+ if (parse_aliasf(line, afflst)) {
+ fclose(afflst);
+ return 1;
+ }
+ }
+
+#ifdef HUNSPELL_EXPERIMENTAL
+ if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) {
+ if (parse_aliasm(line, afflst)) {
+ fclose(afflst);
+ return 1;
+ }
+ }
+#endif
+ if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1;
+ if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break;
+ }
+ fclose(afflst);
+ return 0;
+}
+#endif // HUNSPELL_CHROME_CLIENT
+
+/* parse in the ALIAS table */
+#ifdef HUNSPELL_CHROME_CLIENT
+int HashMgr::parse_aliasf(char* line, hunspell::LineIterator* iterator)
+{
+#else
+int HashMgr::parse_aliasf(char * line, FILE * af)
+{
+#endif
+ if (numaliasf != 0) {
+ HUNSPELL_WARNING(stderr, "error: duplicate AF (alias for flag vector) tables used\n");
+ 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: {
+ numaliasf = atoi(piece);
+ if (numaliasf < 1) {
+ numaliasf = 0;
+ aliasf = NULL;
+ aliasflen = NULL;
+ HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n");
+ free(piece);
+ return 1;
+ }
+ aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *));
+ aliasflen = (unsigned short *) malloc(numaliasf * sizeof(short));
+ if (!aliasf || !aliasflen) {
+ numaliasf = 0;
+ if (aliasf) free(aliasf);
+ if (aliasflen) free(aliasflen);
+ aliasf = NULL;
+ aliasflen = NULL;
+ return 1;
+ }
+ np++;
+ break;
+ }
+ default: break;
+ }
+ i++;
+ }
+ free(piece);
+ piece = mystrsep(&tp, 0);
+ }
+ if (np != 2) {
+ numaliasf = 0;
+ free(aliasf);
+ free(aliasflen);
+ aliasf = NULL;
+ aliasflen = NULL;
+ HUNSPELL_WARNING(stderr, "error: missing AF table information\n");
+ return 1;
+ }
+
+ /* now parse the numaliasf lines to read in the remainder of the table */
+ char * nl = line;
+ for (int j=0; j < numaliasf; j++) {
+#ifdef HUNSPELL_CHROME_CLIENT
+ if (!iterator->AdvanceAndCopy(nl, MAXDELEN))
+ return 1;
+#else
+ if (!fgets(nl,MAXDELEN,af)) return 1;
+#endif
+ 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: AF table is corrupt\n");
+ free(piece);
+ return 1;
+ }
+ break;
+ }
+ case 1: {
+ aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece);
+ flag_qsort(aliasf[j], 0, aliasflen[j]);
+ break;
+ }
+ default: break;
+ }
+ i++;
+ }
+ free(piece);
+ piece = mystrsep(&tp, 0);
+ }
+ if (!aliasf[j]) {
+ free(aliasf);
+ free(aliasflen);
+ aliasf = NULL;
+ aliasflen = NULL;
+ numaliasf = 0;
+ HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifdef HUNSPELL_CHROME_CLIENT
+hentry* HashMgr::AffixIDsToHentry(char* word,
+ int* affix_ids,
+ int affix_count) const
+{
+ if (affix_count == 0)
+ return NULL;
+
+ HEntryCache& cache = const_cast<HashMgr*>(this)->hentry_cache;
+ std::string std_word(word);
+ HEntryCache::iterator found = cache.find(std_word);
+ if (found != cache.end()) {
+ // We must return an existing hentry for the same word if we've previously
+ // handed one out. Hunspell will compare pointers in some cases to see if
+ // two words it has found are the same.
+ return found->second;
+ }
+
+ short word_len = static_cast<short>(strlen(word));
+
+ // We can get a number of prefixes per word. There will normally be only one,
+ // but if not, there will be a linked list of "hentry"s for the "homonym"s
+ // for the word.
+ struct hentry* first_he = NULL;
+ struct hentry* prev_he = NULL; // For making linked list.
+ for (int i = 0; i < affix_count; i++) {
+ struct hentry* he = new hentry;
+ if (i == 0)
+ first_he = he;
+ he->word = word;
+ he->wlen = word_len;
+ he->alen = (short)const_cast<HashMgr*>(this)->get_aliasf(affix_ids[i],
+ &he->astr);
+ he->next = NULL;
+ he->next_homonym = NULL;
+ if (prev_he)
+ prev_he->next_homonym = he;
+ prev_he = he;
+ }
+
+ cache[std_word] = first_he; // Save this word in the cache for later.
+ return first_he;
+}
+
+#endif
+
+#ifdef HUNSPELL_CHROME_CLIENT
+hentry* HashMgr::GetHentryFromHEntryCache(char* word) {
+ HEntryCache& cache = const_cast<HashMgr*>(this)->hentry_cache;
+ std::string std_word(word);
+ HEntryCache::iterator found = cache.find(std_word);
+ if (found != cache.end())
+ return found->second;
+ else
+ return NULL;
+}
+
+#endif
+
+int HashMgr::is_aliasf() {
+ return (aliasf != NULL);
+}
+
+int HashMgr::get_aliasf(int index, unsigned short ** fvec) {
+ if ((index > 0) && (index <= numaliasf)) {
+ *fvec = aliasf[index - 1];
+ return aliasflen[index - 1];
+ }
+ HUNSPELL_WARNING(stderr, "error: bad flag alias index: %d\n", index);
+ *fvec = NULL;
+ return 0;
+}
+
+#ifdef HUNSPELL_EXPERIMENTAL
+/* parse morph alias definitions */
+int HashMgr::parse_aliasm(char * line, FILE * af)
+{
+ if (numaliasm != 0) {
+ HUNSPELL_WARNING(stderr, "error: duplicate AM (aliases for morphological descriptions) tables used\n");
+ 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: {
+ numaliasm = atoi(piece);
+ if (numaliasm < 1) {
+ HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n");
+ free(piece);
+ return 1;
+ }
+ aliasm = (char **) malloc(numaliasm * sizeof(char *));
+ if (!aliasm) {
+ numaliasm = 0;
+ return 1;
+ }
+ np++;
+ break;
+ }
+ default: break;
+ }
+ i++;
+ }
+ free(piece);
+ piece = mystrsep(&tp, 0);
+ }
+ if (np != 2) {
+ numaliasm = 0;
+ free(aliasm);
+ aliasm = NULL;
+ HUNSPELL_WARNING(stderr, "error: missing AM alias information\n");
+ return 1;
+ }
+
+ /* now parse the numaliasm lines to read in the remainder of the table */
+ char * nl = line;
+ for (int j=0; j < numaliasm; j++) {
+ if (!fgets(nl,MAXDELEN,af)) return 1;
+ mychomp(nl);
+ tp = nl;
+ i = 0;
+ aliasm[j] = NULL;
+ piece = mystrsep(&tp, 0);
+ while (piece) {
+ if (*piece != '\0') {
+ switch(i) {
+ case 0: {
+ if (strncmp(piece,"AM",2) != 0) {
+ HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n");
+ free(piece);
+ numaliasm = 0;
+ free(aliasm);
+ aliasm = NULL;
+ return 1;
+ }
+ break;
+ }
+ case 1: {
+ if (complexprefixes) {
+ if (utf8) reverseword_utf(piece);
+ else reverseword(piece);
+ }
+ aliasm[j] = mystrdup(piece);
+ break; }
+ default: break;
+ }
+ i++;
+ }
+ free(piece);
+ piece = mystrsep(&tp, 0);
+ }
+ if (!aliasm[j]) {
+ numaliasm = 0;
+ free(aliasm);
+ aliasm = NULL;
+ HUNSPELL_WARNING(stderr, "error: map table is corrupt\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int HashMgr::is_aliasm() {
+ return (aliasm != NULL);
+}
+
+char * HashMgr::get_aliasm(int index) {
+ if ((index > 0) && (index <= numaliasm)) return aliasm[index - 1];
+ HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index);
+ return NULL;
+}
+#endif