Fix for ISF manifest DB change.
[platform/core/uifw/ise-engine-sunpinyin.git] / src / pinyin / shuangpin_seg.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 <cassert>
39 #include <climits>
40 #include "shuangpin_seg.h"
41
42 CShuangpinData CShuangpinSegmentor::s_shpData;
43
44 CShuangpinSegmentor::CShuangpinSegmentor (EShuangpinType shpType)
45     : m_updatedFrom(0), m_nAlpha(0), m_hasInvalid(false), m_nLastValidPos(0)
46 {
47     m_segs.reserve(32);
48     m_pystr.reserve(32);
49     s_shpData.setShuangpinType(shpType);
50 }
51
52 unsigned
53 CShuangpinSegmentor::push(unsigned ch)
54 {
55     m_inputBuf.push_back(ch);
56
57     return m_updatedFrom = _push(ch);
58 }
59
60 unsigned
61 CShuangpinSegmentor::pop()
62 {
63     if (m_pystr.empty())
64         return m_updatedFrom = 0;
65
66     unsigned size = m_inputBuf.size();
67
68     EShuangpinType shpType = s_shpData.getShuangpinType();
69     bool isInputPy = (islower(m_pystr[size - 1]) ||
70                       (m_pystr[size - 1] == ';' &&
71                        (shpType == MS2003 || shpType == ZIGUANG)));
72     if (!isInputPy) {
73         m_nAlpha -= 1;
74     }
75
76     m_inputBuf.resize(size - 1);
77     m_pystr.resize(size - 1);
78
79     unsigned l = m_segs.back().m_len;
80     m_segs.pop_back();
81
82     if (size == 1 || m_segs.back().m_type != IPySegmentor::INVALID) {
83         m_hasInvalid = false;
84     }
85     if (l == 1)
86         return m_updatedFrom = size - 1;
87
88     std::string new_pystr = m_pystr.substr(size - l);
89     m_pystr.resize(size - l);
90
91     m_updatedFrom = UINT_MAX;
92     std::string::const_iterator it = new_pystr.begin();
93     for (; it != new_pystr.end(); ++it) {
94         unsigned tmp = _push((*it) & 0x7f);
95         if (tmp < m_updatedFrom) m_updatedFrom = tmp;
96     }
97
98     return m_updatedFrom;
99 }
100
101 unsigned
102 CShuangpinSegmentor::insertAt(unsigned idx, unsigned ch)
103 {
104     unsigned pyIdx, segIdx;
105     _locateSegment(idx, pyIdx, segIdx);
106
107     m_inputBuf.insert(idx, 1, ch);
108     m_pystr.insert(idx, 1, ch);
109
110     std::string new_pystr = m_pystr.substr(pyIdx);
111     m_pystr.resize(pyIdx);
112     m_segs.erase(m_segs.begin() + segIdx, m_segs.end());
113
114     if (m_nLastValidPos == idx) {
115         m_hasInvalid = false;
116     } else if (m_nLastValidPos + 1 == idx) {
117         m_hasInvalid = false;
118         int nSize = m_pystr.size();
119         if (islower(m_pystr[nSize - 1])) {
120             m_nLastValidPos = idx - 1;
121             new_pystr.insert((size_t)0, 1, m_pystr[nSize - 1]);
122             m_pystr.erase(nSize - 1, 1);
123             m_segs.erase(m_segs.begin() + segIdx - 1);
124         }
125     } else if (m_nLastValidPos + 1 > idx) {
126         m_hasInvalid = false;
127         m_nLastValidPos = idx;
128     }
129     m_nAlpha = _getNumberOfNonAlpha();
130
131     m_updatedFrom = UINT_MAX;
132     std::string::const_iterator it = new_pystr.begin();
133     for (; it != new_pystr.end(); ++it) {
134         unsigned tmp = _push((*it) & 0x7f);
135         if (tmp < m_updatedFrom) m_updatedFrom = tmp;
136     }
137
138     return m_updatedFrom;
139 }
140
141 unsigned
142 CShuangpinSegmentor::deleteAt(unsigned idx, bool backward)
143 {
144     unsigned pyIdx, segIdx;
145     if (!backward) idx += 1;
146     _locateSegment(idx, pyIdx, segIdx);
147
148     m_inputBuf.erase(idx, 1);
149     m_pystr.erase(idx, 1);
150
151     std::string new_pystr = m_pystr.substr(pyIdx);
152     m_pystr.resize(pyIdx);
153     TSegmentVec tmp_segs(m_segs.begin() + segIdx + 1, m_segs.end());
154     m_segs.erase(m_segs.begin() + segIdx, m_segs.end());
155
156     if (m_nLastValidPos + 1 < idx) {
157         //del invalid ch, and do not effect current status.
158         m_pystr.insert(idx, new_pystr);
159         m_segs.insert(m_segs.end(), tmp_segs.begin(), tmp_segs.end());
160         return m_inputBuf.size() - 1;
161     } else {
162         m_hasInvalid = false;
163         m_nAlpha = _getNumberOfNonAlpha();
164     }
165
166     m_updatedFrom = UINT_MAX;
167     std::string::const_iterator it = new_pystr.begin();
168     for (; it != new_pystr.end(); ++it) {
169         unsigned tmp = _push((*it) & 0x7f);
170         if (tmp < m_updatedFrom) m_updatedFrom = tmp;
171     }
172
173     return m_updatedFrom;
174 }
175
176 unsigned
177 CShuangpinSegmentor::clear(unsigned from)
178 {
179     m_inputBuf.resize(from);
180     return _clear(from);
181 }
182
183 unsigned
184 CShuangpinSegmentor::_clear(unsigned from)
185 {
186     unsigned i, j;
187     _locateSegment(from, i, j);
188
189     std::string new_pystr = m_pystr.substr(i, from - i);
190     m_pystr.resize(i);
191     m_nAlpha = _getNumberOfNonAlpha();
192
193     m_segs.erase(m_segs.begin() + j, m_segs.end());
194
195     if (m_nLastValidPos + 1 >= from) {
196         m_hasInvalid = false;
197     }
198
199     m_updatedFrom = from;
200
201     for (std::string::const_iterator it = new_pystr.begin();
202          it != new_pystr.end(); ++it) {
203         unsigned tmp = _push((*it) & 0x7f);
204         if (tmp < m_updatedFrom) m_updatedFrom = tmp;
205     }
206
207     return m_updatedFrom;
208 }
209
210 int
211 CShuangpinSegmentor::_getNumberOfNonAlpha() const
212 {
213     int nNonAlpha = 0;
214     for (const char* c = m_pystr.c_str(); *c != 0; ++c) {
215         if (!islower(*c))
216             ++nNonAlpha;
217     }
218     return nNonAlpha;
219 }
220
221 void
222 CShuangpinSegmentor::_locateSegment(unsigned idx,
223                                     unsigned &strIdx,
224                                     unsigned &segIdx)
225 {
226     strIdx = segIdx = 0;
227
228     TSegmentVec::const_iterator it = m_segs.begin();
229     TSegmentVec::const_iterator ite = m_segs.end();
230
231     for (; it != ite; ++it) {
232         if (strIdx + it->m_len > idx)
233             break;
234
235         strIdx += it->m_len;
236         segIdx += 1;
237     }
238 }
239
240 int
241 CShuangpinSegmentor::_encode(const char* buf, char ch, bool isComplete)
242 {
243     CMappedYin syls;
244     syls.reserve(8);
245     s_shpData.getMapString(buf, syls);
246     if (syls.empty())
247         return -1;
248
249     const int len = m_pystr.size();
250     CMappedYin::const_iterator iter = syls.begin();
251     CMappedYin::const_iterator iter_end = syls.end();
252
253     if (isComplete) {
254         TSegment &s = m_segs.back();
255         s.m_len = 2;
256         s.m_start = len - s.m_len;
257         s.m_syllables.clear();
258         s.m_type = IPySegmentor::SYLLABLE;
259         for (; iter != iter_end; iter++) {
260             s.m_syllables.push_back(s_shpData.encodeSyllable(iter->c_str()));
261         }
262         m_nLastValidPos += 1;
263         return s.m_start;
264     } else {
265         TSegment s;
266         s.m_len = 1;
267         s.m_start = len - s.m_len;
268         m_nLastValidPos += 1;
269
270         for (; iter != iter_end; ++iter) {
271             TSyllable syl = s_shpData.encodeSyllable(iter->c_str());
272             if ((int)syl != 0) {
273                 s.m_syllables.push_back(syl);
274                 m_segs.push_back(s);
275             } else {
276                 m_segs.push_back(TSegment(ch, s.m_start, 1,
277                                           IPySegmentor::STRING));
278             }
279         }
280         return s.m_start;
281     }
282 }
283
284 unsigned
285 CShuangpinSegmentor::_push(unsigned ch)
286 {
287     int startFrom = 0;
288     bool isInputPy;
289     EShuangpinType shpType;
290
291     m_pystr.push_back(ch);
292     const int len = m_pystr.size();
293     if (m_hasInvalid) {
294         startFrom = len - 1;
295         m_segs.push_back(TSegment(ch, startFrom, 1, IPySegmentor::INVALID));
296         goto RETURN;
297     }
298
299     shpType = s_shpData.getShuangpinType();
300     isInputPy = (islower(ch) ||
301                  (ch == ';' && (shpType == MS2003 || shpType == ZIGUANG)));
302
303     if (!isInputPy) {
304         startFrom = len - 1;
305
306         IPySegmentor::ESegmentType seg_type;
307         if (ch == '\'' && m_inputBuf.size() > 1)
308             seg_type = IPySegmentor::SYLLABLE_SEP;
309         else
310             seg_type = IPySegmentor::STRING;
311         m_segs.push_back(TSegment(ch, startFrom, 1, seg_type));
312         m_nAlpha += 1;
313         m_nLastValidPos += 1;
314     } else {
315         bool bCompleted = !((len - m_nAlpha) % 2) && isInputPy;
316         char buf[4];
317         if (bCompleted) {
318             sprintf(buf, "%c%c", m_pystr[len - 2], ch);
319         } else {
320             sprintf(buf, "%c", ch);
321         }
322         startFrom = _encode(buf, ch, bCompleted);
323         if (startFrom < 0) {
324             m_hasInvalid = true;
325             startFrom = m_pystr.size() - 1;
326             m_segs.push_back(TSegment(ch, startFrom, 1, IPySegmentor::INVALID));
327         }
328     }
329
330 RETURN:;
331
332     if (m_pGetFuzzySyllablesOp && m_pGetFuzzySyllablesOp->isEnabled())
333         if (m_segs.back().m_type == SYLLABLE)
334             _addFuzzySyllables(m_segs.back());
335
336     return startFrom;
337 }
338
339 void
340 CShuangpinSegmentor::_addFuzzySyllables(TSegment& seg)
341 {
342     assert(seg.m_type == SYLLABLE);
343
344     seg.m_fuzzy_syllables.clear();
345
346     std::vector<unsigned>::iterator it = seg.m_syllables.begin();
347     std::vector<unsigned>::iterator ite = seg.m_syllables.end();
348     for (; it != ite; ++it) {
349         CSyllables fuzzy_set = (*m_pGetFuzzySyllablesOp)(*it);
350
351         CSyllables::const_iterator _it = fuzzy_set.begin();
352         CSyllables::const_iterator _ite = fuzzy_set.end();
353         for (; _it != _ite; ++_it)
354             seg.m_fuzzy_syllables.push_back(*_it);
355     }
356 }
357