Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / src / slm / sim_dict.cpp
1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * The contents of this file are subject to the terms of either the GNU Lesser
7  * General Public License Version 2.1 only ("LGPL") or the Common Development and
8  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
9  * file except in compliance with the License. You can obtain a copy of the CDDL at
10  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
11  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
12  * specific language governing permissions and limitations under the License. When
13  * distributing the software, include this License Header Notice in each file and
14  * include the full text of the License in the License file as well as the
15  * following notice:
16  *
17  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
18  * (CDDL)
19  * For Covered Software in this distribution, this License shall be governed by the
20  * laws of the State of California (excluding conflict-of-law provisions).
21  * Any litigation relating to this License shall be subject to the jurisdiction of
22  * the Federal Courts of the Northern District of California and the state courts
23  * of the State of California, with venue lying in Santa Clara County, California.
24  *
25  * Contributor(s):
26  *
27  * If you wish your version of this file to be governed by only the CDDL or only
28  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
29  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
30  * license." If you don't indicate a single choice of license, a recipient has the
31  * option to distribute your version of this file under either the CDDL or the LGPL
32  * Version 2.1, or to extend the choice of license to its licensees as provided
33  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
34  * Version 2 license, then the option applies only if the new code is made subject
35  * to such option by the copyright holder.
36  */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #include "sim_dict.h"
42
43
44 void
45 CSIMDict::freeSubTree(CSIMDict::TState& root)
46 {
47     if (root.follow != NULL) {
48         Map_Type &map = *(root.follow);
49         for (Map_Type::iterator it = map.begin(), last = map.end();
50              it != last;
51              ++it)
52             freeSubTree(it->second);
53         delete root.follow;
54         root.follow = NULL;
55     }
56 }
57
58 const CSIMDict::TState*
59 CSIMDict::step(const CSIMDict::TState* root, TWCHAR wch)
60 {
61     if ((root != NULL) && (root->follow != NULL) && wch != WCH_NULL) {
62         Map_Type::iterator it = root->follow->find(TWCHAR(wch));
63         if (it != root->follow->end())
64             return &(it->second);
65     }
66     return NULL;
67 }
68
69 int
70 CSIMDict::matchLongest(const CSIMDict::TState* root,
71                        CSIMDict::PState &  result,
72                        const TWCHAR* str)
73 {
74     int lastWordLen = 0, len = 0;
75     result = root;
76     while (root != NULL) {
77         if (root->word_id != SIM_ID_NOT_WORD) {
78             result = root;
79             lastWordLen = len;
80         }
81         ++len;
82         root = step(root, *str++);
83     }
84     return lastWordLen;
85 }
86
87 bool
88 CSIMDict::parseText(const char* filename)
89 {
90     FILE * fp = NULL;
91     static char buf[1024];
92     static TWCHAR wword[sizeof(buf)];
93     unsigned int id;
94
95     try {
96         if ((fp = fopen(filename, "r")) == NULL)
97             return false;
98         while (fgets(buf, 1024, fp) != NULL) {
99             if (*buf == '\n' || *buf == '#')
100                 continue;
101
102             char* p = buf;
103             while (*p == ' ' || *p == '\t')
104                 ++p;
105             char* pstart = p;
106             while (*p != 0 && *p != ' ' && *p != '\t')
107                 ++p;
108             if (*p == 0)
109                 continue;
110             *p++ = 0;
111             while (*p == ' ' || *p == '\t')
112                 ++p;
113             if (!(*p >= '0' && *p <= '9')) continue;
114             for (id = 0; *p >= '0' && *p <= '9'; ++p)
115                 id = 10 * id + (*p - '0');
116
117             if (id < SIM_ID_REALWORD_START)
118                 continue;
119             if (MBSTOWCS(wword, pstart, sizeof(buf)) != (size_t)-1) {
120                 insertWord(wword, TSIMWordId(id));
121             } else {
122                 fprintf(stderr,
123                         "mbs to wcs conversion error for : %s %d\n",
124                         buf,
125                         id);
126                 exit(100);
127             }
128         }
129         fclose(fp);
130     } catch (...) {
131         if (fp != NULL)
132             fclose(fp);
133         buf[sizeof(buf) - 1] = 0;
134         fprintf(stderr,
135                 "Catch exception when loading dictionary at %s, exiting...",
136                 buf);
137         exit(200);
138     }
139     return true;
140 }
141
142 void
143 CSIMDict::insertWord(const TWCHAR* wstr, TSIMWordId id)
144 {
145     TState* ps = &m_root;
146     while (*wstr) {
147         TWCHAR ch(*wstr++);
148         TSIMWordId nodeId = (*wstr) ? SIM_ID_NOT_WORD : id;
149         if (ps->follow == NULL) {
150             ps->follow = new Map_Type();
151         }
152         Map_Type & map = *(ps->follow);
153         Map_Type::iterator it = map.find(ch);
154         if (it != map.end() && nodeId != SIM_ID_NOT_WORD &&
155             it->second.word_id != SIM_ID_NOT_WORD && it->second.word_id !=
156             nodeId) {
157             throw new int(100);
158         }
159         if (it != map.end()) {
160             if (nodeId != SIM_ID_NOT_WORD)
161                 it->second.word_id = nodeId;
162             ps = &(it->second);
163         } else {
164             ps = &(map[ch] = TState(nodeId));
165         }
166     }
167 }
168
169 void
170 CSIMDict::InnerPrint(FILE* fp, wstring & wstr, const TState* pnode)
171 {
172     if (pnode != NULL && pnode->word_id != SIM_ID_NOT_WORD) {
173         char* buf = new char[wstr.size() * 2 + 2];
174         WCSTOMBS(buf, wstr.c_str(), wstr.size() * 2 + 2);
175         fprintf(fp, "%s %d\n", buf, unsigned(pnode->word_id));
176         delete[] buf;
177     }
178     if (pnode != NULL && pnode->follow != NULL) {
179         Map_Type::iterator it, ite = pnode->follow->end();
180         for (it = pnode->follow->begin(); it != ite; ++it) {
181             TWCHAR wch = TWCHAR(it->first);
182             wstr.push_back(wch);
183             InnerPrint(fp, wstr, &(it->second));
184             wstr.erase(wstr.size() - 1, 1);
185         }
186     }
187 }