17898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project/*
27898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
37898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project *
47898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
57898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * you may not use this file except in compliance with the License.
67898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * You may obtain a copy of the License at
77898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project *
87898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
97898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project *
107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * See the License for the specific language governing permissions and
147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project * limitations under the License.
157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project */
167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#include <stdio.h>
187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#include <string.h>
197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#include <assert.h>
207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#include "../include/dictdef.h"
217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#ifdef ___BUILD_MODEL___
237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#include "../include/spellingtable.h"
247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#endif
257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#include "../include/spellingtrie.h"
277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectnamespace ime_pinyin {
297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source ProjectSpellingTrie* SpellingTrie::instance_ = NULL;
317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project// z/c/s is for Zh/Ch/Sh
337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectconst char SpellingTrie::kHalfId2Sc_[kFullSplIdStart + 1] =
347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    "0ABCcDEFGHIJKLMNOPQRSsTUVWXYZz";
357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project// Bit 0 : is it a Shengmu char?
377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project// Bit 1 : is it a Yunmu char? (one char is a Yunmu)
387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project// Bit 2 : is it enabled in ShouZiMu(first char) mode?
397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectunsigned char SpellingTrie::char_flags_[] = {
407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // a    b      c     d     e     f     g
417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // h    i     j      k     l     m    n
437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // o    p     q      r     s     t
457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // u    v     w      x     y     z
477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  0x00, 0x00, 0x01, 0x01, 0x01, 0x01
487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project};
497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectint compare_spl(const void* p1, const void* p2) {
517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return strcmp((const char*)(p1), (const char*)(p2));
527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source ProjectSpellingTrie::SpellingTrie() {
557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_buf_ = NULL;
567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_size_ = 0;
577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_num_ = 0;
587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spl_ym_ids_ = NULL;
597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splstr_queried_ = NULL;
607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splstr16_queried_ = NULL;
617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  root_ = NULL;
627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  dumb_node_ = NULL;
637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splitter_node_ = NULL;
647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  instance_ = NULL;
657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  ym_buf_ = NULL;
667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  f2h_ = NULL;
677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  szm_enable_shm(true);
697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  szm_enable_ym(true);
707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#ifdef ___BUILD_MODEL___
727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  node_num_ = 0;
737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#endif
747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source ProjectSpellingTrie::~SpellingTrie() {
777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != spelling_buf_)
787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] spelling_buf_;
797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != splstr_queried_)
817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] splstr_queried_;
827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != splstr16_queried_)
847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] splstr16_queried_;
857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != spl_ym_ids_)
877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] spl_ym_ids_;
887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != root_) {
907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    free_son_trie(root_);
917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete root_;
927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != dumb_node_) {
957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] dumb_node_;
967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != splitter_node_) {
997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] splitter_node_;
1007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
1017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != instance_) {
1037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete instance_;
1047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    instance_ = NULL;
1057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
1067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != ym_buf_)
1087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] ym_buf_;
1097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != f2h_)
1117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] f2h_;
1127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::if_valid_id_update(uint16 *splid) const {
1157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == splid || 0 == *splid)
1167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
1177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (*splid >= kFullSplIdStart)
1197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return true;
1207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (*splid < kFullSplIdStart) {
1217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    char ch = kHalfId2Sc_[*splid];
1227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (ch > 'Z') {
1237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return true;
1247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else {
1257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (szm_is_enabled(ch)) {
1267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        return true;
1277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      } else if (is_yunmu_char(ch)) {
1287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        assert(h2f_num_[*splid] > 0);
1297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        *splid = h2f_start_[*splid];
1307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        return true;
1317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      }
1327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
1337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
1347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return false;
1357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_half_id(uint16 splid) const {
1387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (0 == splid || splid >= kFullSplIdStart)
1397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
1407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return true;
1427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_full_id(uint16 splid) const {
1457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (splid < kFullSplIdStart || splid >= kFullSplIdStart + spelling_num_)
1467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
1477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return true;
1487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::half_full_compatible(uint16 half_id, uint16 full_id) const {
1517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  uint16 half_fr_full = full_to_half(full_id);
1527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (half_fr_full == half_id)
1547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return true;
1557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // &~0x20 is used to conver the char to upper case.
1577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // So that Zh/Ch/Sh(whose char is z/c/s) can be matched with Z/C/S.
1587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  char ch_f = (kHalfId2Sc_[half_fr_full] & (~0x20));
1597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  char ch_h = kHalfId2Sc_[half_id];
1607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (ch_f == ch_h)
1617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return true;
1627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return false;
1647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_half_id_yunmu(uint16 splid) const {
1677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (0 == splid || splid >= kFullSplIdStart)
1687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
1697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  char ch = kHalfId2Sc_[splid];
1717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // If ch >= 'a', that means the half id is one of Zh/Ch/Sh
1727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (ch >= 'a') {
1737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
1747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
1757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return char_flags_[ch - 'A'] & kHalfIdYunmuMask;
1777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_shengmu_char(char ch) const {
1807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return char_flags_[ch - 'A'] & kHalfIdShengmuMask;
1817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_yunmu_char(char ch) const {
1847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return char_flags_[ch - 'A'] & kHalfIdYunmuMask;
1857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_szm_char(char ch) const {
1887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return is_shengmu_char(ch) || is_yunmu_char(ch);
1897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::szm_is_enabled(char ch) const {
1927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return char_flags_[ch - 'A'] & kHalfIdSzmMask;
1937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
1947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
1957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectvoid SpellingTrie::szm_enable_shm(bool enable) {
1967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (enable) {
1977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (char ch = 'A'; ch <= 'Z'; ch++) {
1987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (is_shengmu_char(ch))
1997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        char_flags_[ch - 'A'] = char_flags_[ch - 'A'] | kHalfIdSzmMask;
2007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
2017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else {
2027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (char ch = 'A'; ch <= 'Z'; ch++) {
2037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (is_shengmu_char(ch))
2047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        char_flags_[ch - 'A'] = char_flags_[ch - 'A'] & (kHalfIdSzmMask ^ 0xff);
2057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
2067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
2077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectvoid SpellingTrie::szm_enable_ym(bool enable) {
2107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (enable) {
2117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (char ch = 'A'; ch <= 'Z'; ch++) {
2127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (is_yunmu_char(ch))
2137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        char_flags_[ch - 'A'] = char_flags_[ch - 'A'] | kHalfIdSzmMask;
2147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
2157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else {
2167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (char ch = 'A'; ch <= 'Z'; ch++) {
2177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (is_yunmu_char(ch))
2187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        char_flags_[ch - 'A'] = char_flags_[ch - 'A'] & (kHalfIdSzmMask ^ 0xff);
2197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
2207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
2217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::is_szm_enabled(char ch) const {
2247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return char_flags_[ch - 'A'] & kHalfIdSzmMask;
2257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectconst SpellingTrie* SpellingTrie::get_cpinstance() {
2287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return &get_instance();
2297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source ProjectSpellingTrie& SpellingTrie::get_instance() {
2327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == instance_)
2337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    instance_ = new SpellingTrie();
2347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return *instance_;
2367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectuint16 SpellingTrie::half2full_num(uint16 half_id) const {
2397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == root_ || half_id >= kFullSplIdStart)
2407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return 0;
2417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return h2f_num_[half_id];
2427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectuint16 SpellingTrie::half_to_full(uint16 half_id, uint16 *spl_id_start) const {
2457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == spl_id_start || NULL == root_ || half_id >= kFullSplIdStart)
2467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return 0;
2477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  *spl_id_start = h2f_start_[half_id];
2497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return h2f_num_[half_id];
2507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectuint16 SpellingTrie::full_to_half(uint16 full_id) const {
2537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == root_ || full_id < kFullSplIdStart ||
2547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      full_id > spelling_num_ + kFullSplIdStart)
2557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return 0;
2567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return f2h_[full_id - kFullSplIdStart];
2587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectvoid SpellingTrie::free_son_trie(SpellingNode* node) {
2617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == node)
2627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return;
2637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (size_t pos = 0; pos < node->num_of_son; pos++) {
2657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    free_son_trie(node->first_son + pos);
2667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
2677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != node->first_son)
2697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] node->first_son;
2707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
2717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::construct(const char* spelling_arr, size_t item_size,
2737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project                             size_t item_num, float score_amplifier,
2747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project                             unsigned char average_score) {
2757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (spelling_arr == NULL)
2767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
2777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(h2f_start_, 0, sizeof(uint16) * kFullSplIdStart);
2797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(h2f_num_, 0, sizeof(uint16) * kFullSplIdStart);
2807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // If the arr is the same as the buf, means this function is called by
2827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // load_table(), the table data are ready; otherwise the array should be
2837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // saved.
2847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (spelling_arr != spelling_buf_) {
2857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (NULL != spelling_buf_)
2867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      delete [] spelling_buf_;
2877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    spelling_buf_ = new char[item_size * item_num];
2887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (NULL == spelling_buf_)
2897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return false;
2907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    memcpy(spelling_buf_, spelling_arr, sizeof(char) * item_size * item_num);
2917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
2927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_size_ = item_size;
2947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_num_ = item_num;
2957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  score_amplifier_ = score_amplifier;
2977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  average_score_ = average_score;
2987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
2997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != splstr_queried_)
3007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] splstr_queried_;
3017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splstr_queried_ = new char[spelling_size_];
3027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == splstr_queried_)
3037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
3047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != splstr16_queried_)
3067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] splstr16_queried_;
3077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splstr16_queried_ = new char16[spelling_size_];
3087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == splstr16_queried_)
3097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
3107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // First, sort the buf to ensure they are in ascendant order
3127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  qsort(spelling_buf_, spelling_num_, spelling_size_, compare_spl);
3137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#ifdef ___BUILD_MODEL___
3157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  node_num_ = 1;
3167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#endif
3177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  root_ = new SpellingNode();
3197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(root_, 0, sizeof(SpellingNode));
3207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  dumb_node_ = new SpellingNode();
3227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(dumb_node_, 0, sizeof(SpellingNode));
3237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  dumb_node_->score = average_score_;
3247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splitter_node_ = new SpellingNode();
3267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(splitter_node_, 0, sizeof(SpellingNode));
3277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splitter_node_->score = average_score_;
3287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(level1_sons_, 0, sizeof(SpellingNode*) * kValidSplCharNum);
3307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  root_->first_son = construct_spellings_subset(0, spelling_num_, 0, root_);
3327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // Root's score should be cleared.
3347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  root_->score = 0;
3357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == root_->first_son)
3377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
3387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  h2f_start_[0] = h2f_num_[0] = 0;
3407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (!build_f2h())
3427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
3437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#ifdef ___BUILD_MODEL___
3457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (kPrintDebug0) {
3467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    printf("---SpellingTrie Nodes: %d\n", node_num_);
3477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
3487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return build_ym_info();
3497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#else
3507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return true;
3517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#endif
3527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
3537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#ifdef ___BUILD_MODEL___
3557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectconst char* SpellingTrie::get_ym_str(const char *spl_str) {
3567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  bool start_ZCS = false;
3577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (is_shengmu_char(*spl_str)) {
3587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if ('Z' == *spl_str || 'C' == *spl_str || 'S' == *spl_str)
3597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      start_ZCS = true;
3607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    spl_str += 1;
3617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (start_ZCS && 'h' == *spl_str)
3627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      spl_str += 1;
3637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
3647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return spl_str;
3657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
3667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::build_ym_info() {
3687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  bool sucess;
3697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  SpellingTable *spl_table = new SpellingTable();
3707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  sucess = spl_table->init_table(kMaxPinyinSize - 1, 2 * kMaxYmNum, false);
3727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  assert(sucess);
3737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (uint16 pos = 0; pos < spelling_num_; pos++) {
3757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    const char *spl_str = spelling_buf_ + spelling_size_ * pos;
3767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    spl_str = get_ym_str(spl_str);
3777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if ('\0' != spl_str[0]) {
3787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      sucess = spl_table->put_spelling(spl_str, 0);
3797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      assert(sucess);
3807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
3817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
3827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  size_t ym_item_size;  // '\0' is included
3847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  size_t ym_num;
3857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  const char* ym_buf;
3867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  ym_buf = spl_table->arrange(&ym_item_size, &ym_num);
3877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != ym_buf_)
3897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] ym_buf_;
3907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  ym_buf_ = new char[ym_item_size * ym_num];
3917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == ym_buf_) {
3927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete spl_table;
3937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
3947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
3957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
3967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memcpy(ym_buf_, ym_buf, sizeof(char) * ym_item_size * ym_num);
3977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  ym_size_ = ym_item_size;
3987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  ym_num_ = ym_num;
3997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  delete spl_table;
4017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // Generate the maping from the spelling ids to the Yunmu ids.
4037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (spl_ym_ids_)
4047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete spl_ym_ids_;
4057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spl_ym_ids_ = new uint8[spelling_num_ + kFullSplIdStart];
4067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == spl_ym_ids_)
4077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
4087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(spl_ym_ids_, 0, sizeof(uint8) * (spelling_num_ + kFullSplIdStart));
4107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (uint16 id = 1; id < spelling_num_ + kFullSplIdStart; id++) {
4127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    const char *str = get_spelling_str(id);
4137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    str = get_ym_str(str);
4157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if ('\0' != str[0]) {
4167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      uint8 ym_id = get_ym_id(str);
4177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      spl_ym_ids_[id] = ym_id;
4187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      assert(ym_id > 0);
4197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else {
4207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      spl_ym_ids_[id] = 0;
4217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
4227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
4237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return true;
4247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
4257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#endif
4267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source ProjectSpellingNode* SpellingTrie::construct_spellings_subset(
4287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    size_t item_start, size_t item_end, size_t level, SpellingNode* parent) {
4297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (level >= spelling_size_ || item_end <= item_start || NULL == parent)
4307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return NULL;
4317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  SpellingNode *first_son = NULL;
4337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  uint16 num_of_son = 0;
4347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  unsigned char min_son_score = 255;
4357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  const char *spelling_last_start = spelling_buf_ + spelling_size_ * item_start;
4377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  char char_for_node = spelling_last_start[level];
4387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  assert(char_for_node >= 'A' && char_for_node <= 'Z' ||
4397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project         'h' == char_for_node);
4407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // Scan the array to find how many sons
4427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (size_t i = item_start + 1; i < item_end; i++) {
4437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    const char *spelling_current = spelling_buf_ + spelling_size_ * i;
4447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    char char_current = spelling_current[level];
4457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (char_current != char_for_node) {
4467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      num_of_son++;
4477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      char_for_node = char_current;
4487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
4497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
4507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  num_of_son++;
4517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // Allocate memory
4537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#ifdef ___BUILD_MODEL___
4547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  node_num_ += num_of_son;
4557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project#endif
4567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  first_son = new SpellingNode[num_of_son];
4577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  memset(first_son, 0, sizeof(SpellingNode)*num_of_son);
4587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // Now begin construct tree
4607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  size_t son_pos = 0;
4617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_last_start = spelling_buf_ + spelling_size_ * item_start;
4637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  char_for_node = spelling_last_start[level];
4647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  bool spelling_endable = true;
4667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (spelling_last_start[level + 1] != '\0')
4677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    spelling_endable = false;
4687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  size_t item_start_next = item_start;
4707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (size_t i = item_start + 1; i < item_end; i++) {
4727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    const char *spelling_current = spelling_buf_ + spelling_size_ * i;
4737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    char char_current = spelling_current[level];
4747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    assert(is_valid_spl_char(char_current));
4757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (char_current != char_for_node) {
4777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      // Construct a node
4787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      SpellingNode *node_current = first_son + son_pos;
4797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      node_current->char_this_node = char_for_node;
4807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      // For quick search in the first level
4827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (0 == level)
4837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        level1_sons_[char_for_node - 'A'] = node_current;
4847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (spelling_endable) {
4867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        node_current->spelling_idx = kFullSplIdStart + item_start_next;
4877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      }
4887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (spelling_last_start[level + 1] != '\0' || i - item_start_next > 1) {
4907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        size_t real_start = item_start_next;
4917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (spelling_last_start[level + 1] == '\0')
4927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          real_start++;
4937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        node_current->first_son =
4957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project            construct_spellings_subset(real_start, i, level + 1,
4967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project                                       node_current);
4977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
4987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (real_start == item_start_next + 1) {
4997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          uint16 score_this = static_cast<unsigned char>(
5007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project              spelling_last_start[spelling_size_ - 1]);
5017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          if (score_this < node_current->score)
5027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project            node_current->score = score_this;
5037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        }
5047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      } else {
5057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        node_current->first_son = NULL;
5067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        node_current->score = static_cast<unsigned char>(
5077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project            spelling_last_start[spelling_size_ - 1]);
5087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      }
5097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (node_current->score < min_son_score)
5117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        min_son_score = node_current->score;
5127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      bool is_half = false;
5147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (level == 0 && is_szm_char(char_for_node)) {
5157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        node_current->spelling_idx =
5167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          static_cast<uint16>(char_for_node - 'A' + 1);
5177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (char_for_node > 'C')
5197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          node_current->spelling_idx++;
5207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (char_for_node > 'S')
5217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          node_current->spelling_idx++;
5227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        h2f_num_[node_current->spelling_idx] = i - item_start_next;
5247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        is_half = true;
5257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      } else if (level == 1 && char_for_node == 'h') {
5267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        char ch_level0 = spelling_last_start[0];
5277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        uint16 part_id = 0;
5287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (ch_level0 == 'C')
5297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          part_id = 'C' - 'A' + 1 + 1;
5307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        else if (ch_level0 == 'S')
5317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          part_id = 'S' - 'A' + 1 + 2;
5327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        else if (ch_level0 == 'Z')
5337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          part_id = 'Z' - 'A' + 1 + 3;
5347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (0 != part_id) {
5357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          node_current->spelling_idx = part_id;
5367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          h2f_num_[node_current->spelling_idx] = i - item_start_next;
5377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          is_half = true;
5387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        }
5397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      }
5407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (is_half) {
5427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        if (h2f_num_[node_current->spelling_idx] > 0)
5437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          h2f_start_[node_current->spelling_idx] =
5447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project            item_start_next + kFullSplIdStart;
5457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        else
5467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          h2f_start_[node_current->spelling_idx] = 0;
5477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      }
5487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      // for next sibling
5507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      spelling_last_start = spelling_current;
5517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      char_for_node = char_current;
5527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      item_start_next = i;
5537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      spelling_endable = true;
5547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (spelling_current[level + 1] != '\0')
5557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        spelling_endable = false;
5567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      son_pos++;
5587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
5597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
5607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // the last one
5627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  SpellingNode *node_current = first_son + son_pos;
5637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  node_current->char_this_node = char_for_node;
5647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // For quick search in the first level
5667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (0 == level)
5677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    level1_sons_[char_for_node - 'A'] = node_current;
5687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (spelling_endable) {
5707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    node_current->spelling_idx = kFullSplIdStart + item_start_next;
5717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
5727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (spelling_last_start[level + 1] != '\0' ||
5747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      item_end - item_start_next > 1) {
5757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    size_t real_start = item_start_next;
5767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (spelling_last_start[level + 1] == '\0')
5777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      real_start++;
5787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    node_current->first_son =
5807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        construct_spellings_subset(real_start, item_end, level + 1,
5817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project                                   node_current);
5827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (real_start == item_start_next + 1) {
5847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      uint16 score_this = static_cast<unsigned char>(
5857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          spelling_last_start[spelling_size_ - 1]);
5867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (score_this < node_current->score)
5877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        node_current->score = score_this;
5887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
5897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else {
5907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    node_current->first_son = NULL;
5917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    node_current->score = static_cast<unsigned char>(
5927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        spelling_last_start[spelling_size_ - 1]);
5937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
5947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (node_current->score < min_son_score)
5967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    min_son_score = node_current->score;
5977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
5987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  assert(son_pos + 1 == num_of_son);
5997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  bool is_half = false;
6017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (level == 0 && szm_is_enabled(char_for_node)) {
6027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    node_current->spelling_idx = static_cast<uint16>(char_for_node - 'A' + 1);
6037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (char_for_node > 'C')
6057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      node_current->spelling_idx++;
6067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (char_for_node > 'S')
6077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      node_current->spelling_idx++;
6087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    h2f_num_[node_current->spelling_idx] = item_end - item_start_next;
6107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    is_half = true;
6117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else if (level == 1 && char_for_node == 'h') {
6127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    char ch_level0 = spelling_last_start[0];
6137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    uint16 part_id = 0;
6147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (ch_level0 == 'C')
6157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      part_id = 'C' - 'A' + 1 + 1;
6167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    else if (ch_level0 == 'S')
6177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      part_id = 'S' - 'A' + 1 + 2;
6187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    else if (ch_level0 == 'Z')
6197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      part_id = 'Z' - 'A' + 1 + 3;
6207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (0 != part_id) {
6217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      node_current->spelling_idx = part_id;
6227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      h2f_num_[node_current->spelling_idx] = item_end - item_start_next;
6237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      is_half = true;
6247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
6257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
6267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (is_half) {
6277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (h2f_num_[node_current->spelling_idx] > 0)
6287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      h2f_start_[node_current->spelling_idx] =
6297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        item_start_next + kFullSplIdStart;
6307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    else
6317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      h2f_start_[node_current->spelling_idx] = 0;
6327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
6337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  parent->num_of_son = num_of_son;
6357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  parent->score = min_son_score;
6367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return first_son;
6377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
6387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::save_spl_trie(FILE *fp) {
6407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == fp || NULL == spelling_buf_)
6417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fwrite(&spelling_size_, sizeof(size_t), 1, fp) != 1)
6447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fwrite(&spelling_num_, sizeof(size_t), 1, fp) != 1)
6477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fwrite(&score_amplifier_, sizeof(float), 1, fp) != 1)
6507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fwrite(&average_score_, sizeof(unsigned char), 1, fp) != 1)
6537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fwrite(spelling_buf_, sizeof(char) * spelling_size_,
6567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project             spelling_num_, fp) != spelling_num_)
6577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return true;
6607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
6617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::load_spl_trie(FILE *fp) {
6637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == fp)
6647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fread(&spelling_size_, sizeof(size_t), 1, fp) != 1)
6677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fread(&spelling_num_, sizeof(size_t), 1, fp) != 1)
6707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fread(&score_amplifier_, sizeof(float), 1, fp) != 1)
6737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fread(&average_score_, sizeof(unsigned char), 1, fp) != 1)
6767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != spelling_buf_)
6797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] spelling_buf_;
6807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  spelling_buf_ = new char[spelling_size_ * spelling_num_];
6827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == spelling_buf_)
6837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (fread(spelling_buf_, sizeof(char) * spelling_size_,
6867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project            spelling_num_, fp) != spelling_num_)
6877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return construct(spelling_buf_, spelling_size_, spelling_num_,
6907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project                   score_amplifier_, average_score_);
6917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
6927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
6937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectbool SpellingTrie::build_f2h() {
6947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL != f2h_)
6957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    delete [] f2h_;
6967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  f2h_ = new uint16[spelling_num_];
6977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == f2h_)
6987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return false;
6997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (uint16 hid = 0; hid < kFullSplIdStart; hid++) {
7017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (uint16 fid = h2f_start_[hid];
7027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project         fid < h2f_start_[hid] + h2f_num_[hid]; fid++)
7037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      f2h_[fid - kFullSplIdStart] = hid;
7047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
7057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return true;
7077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
7087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectsize_t SpellingTrie::get_spelling_num() {
7107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return spelling_num_;
7117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
7127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectuint8 SpellingTrie::get_ym_id(const char *ym_str) {
7147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == ym_str || NULL == ym_buf_)
7157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    return 0;
7167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  for (uint8 pos = 0; pos < ym_num_; pos++)
7187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (strcmp(ym_buf_ + ym_size_ * pos, ym_str) == 0)
7197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return pos + 1;
7207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return 0;
7227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
7237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectconst char* SpellingTrie::get_spelling_str(uint16 splid) {
7257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splstr_queried_[0] = '\0';
7267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (splid >= kFullSplIdStart) {
7287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    splid -= kFullSplIdStart;
7297898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    snprintf(splstr_queried_, spelling_size_, "%s",
7307898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project             spelling_buf_ + splid * spelling_size_);
7317898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else {
7327898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (splid == 'C' - 'A' + 1 + 1) {
7337898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      snprintf(splstr_queried_, spelling_size_, "%s", "Ch");
7347898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else if (splid == 'S' - 'A' + 1 + 2) {
7357898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      snprintf(splstr_queried_, spelling_size_, "%s", "Sh");
7367898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else if (splid == 'Z' - 'A' + 1 + 3) {
7377898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      snprintf(splstr_queried_, spelling_size_, "%s", "Zh");
7387898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else {
7397898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (splid > 'C' - 'A' + 1)
7407898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        splid--;
7417898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (splid > 'S' - 'A' + 1)
7427898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        splid--;
7437898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr_queried_[0] = 'A' + splid - 1;
7447898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr_queried_[1] = '\0';
7457898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
7467898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
7477898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return splstr_queried_;
7487898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
7497898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7507898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectconst char16* SpellingTrie::get_spelling_str16(uint16 splid) {
7517898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  splstr16_queried_[0] = '\0';
7527898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7537898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (splid >= kFullSplIdStart) {
7547898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    splid -= kFullSplIdStart;
7557898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (size_t pos = 0; pos < spelling_size_; pos++) {
7567898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[pos] = static_cast<char16>
7577898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          (spelling_buf_[splid * spelling_size_ + pos]);
7587898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
7597898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else {
7607898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (splid == 'C' - 'A' + 1 + 1) {
7617898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[0] = static_cast<char16>('C');
7627898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[1] = static_cast<char16>('h');
7637898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[2] = static_cast<char16>('\0');
7647898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else if (splid == 'S' - 'A' + 1 + 2) {
7657898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[0] = static_cast<char16>('S');
7667898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[1] = static_cast<char16>('h');
7677898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[2] = static_cast<char16>('\0');
7687898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else if (splid == 'Z' - 'A' + 1 + 3) {
7697898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[0] = static_cast<char16>('Z');
7707898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[1] = static_cast<char16>('h');
7717898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[2] = static_cast<char16>('\0');
7727898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else {
7737898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (splid > 'C' - 'A' + 1)
7747898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        splid--;
7757898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (splid > 'S' - 'A' + 1)
7767898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        splid--;
7777898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[0] = 'A' + splid - 1;
7787898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16_queried_[1] = '\0';
7797898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
7807898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
7817898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return splstr16_queried_;
7827898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
7837898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7847898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Projectsize_t SpellingTrie::get_spelling_str16(uint16 splid, char16 *splstr16,
7857898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project                                        size_t splstr16_len) {
7867898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (NULL == splstr16 || splstr16_len < kMaxPinyinSize + 1) return 0;
7877898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
7887898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  if (splid >= kFullSplIdStart) {
7897898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    splid -= kFullSplIdStart;
7907898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    for (size_t pos = 0; pos <= kMaxPinyinSize; pos++) {
7917898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[pos] = static_cast<char16>
7927898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project          (spelling_buf_[splid * spelling_size_ + pos]);
7937898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (static_cast<char16>('\0') == splstr16[pos]) {
7947898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        return pos;
7957898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      }
7967898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
7977898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  } else {
7987898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    if (splid == 'C' - 'A' + 1 + 1) {
7997898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[0] = static_cast<char16>('C');
8007898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[1] = static_cast<char16>('h');
8017898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[2] = static_cast<char16>('\0');
8027898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return 2;
8037898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else if (splid == 'S' - 'A' + 1 + 2) {
8047898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[0] = static_cast<char16>('S');
8057898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[1] = static_cast<char16>('h');
8067898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[2] = static_cast<char16>('\0');
8077898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return 2;
8087898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else if (splid == 'Z' - 'A' + 1 + 3) {
8097898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[0] = static_cast<char16>('Z');
8107898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[1] = static_cast<char16>('h');
8117898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[2] = static_cast<char16>('\0');
8127898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return 2;
8137898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    } else {
8147898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (splid > 'C' - 'A' + 1)
8157898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        splid--;
8167898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      if (splid > 'S' - 'A' + 1)
8177898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project        splid--;
8187898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[0] = 'A' + splid - 1;
8197898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      splstr16[1] = '\0';
8207898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project      return 1;
8217898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project    }
8227898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  }
8237898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
8247898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  // Not reachable.
8257898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project  return 0;
8267898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}
8277898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project
8287898d76cc005bbe1c5893a9f57439561e0771ccThe Android Open Source Project}  // namespace ime_pinyin
829