Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / src / pinyin / hunpin_seg.cpp
1 /*
2  *  hunpin_seg.cpp
3  *  FIT
4  *
5  *  Created by cererd.long on 10-10-8.
6  *  Copyright 2010 __MyCompanyName__. All rights reserved.
7  *
8  */
9
10 #include "hunpin_seg.h"
11 #include <cassert>
12 #include <functional>
13 #include <algorithm>
14 #include "pinyin_seg.h"
15 #include "quanpin_trie.h"
16
17
18 CShuangpinData CHunpinSegmentor::s_shpData;
19
20 CHunpinSegmentor::CHunpinSegmentor (EShuangpinType shpType)
21     : m_pGetFuzzySyllablesOp(NULL),
22       m_pytrie(base, check, value, sizeof(base) / sizeof(*base)),
23       m_updatedFrom(0)
24 {
25     m_segs.reserve(32);
26     s_shpData.setShuangpinType(shpType);
27 }
28
29
30 int
31 CHunpinSegmentor::_encode(const char* buf, int ret)
32 {
33     CMappedYin syls;
34     syls.reserve(8);
35     s_shpData.getMapString(buf, syls);
36     if (syls.empty())
37         return -1;
38
39
40     CMappedYin::const_iterator iter = syls.begin();
41     CMappedYin::const_iterator iter_end = syls.end();
42
43     m_segs.push_back(TSegment(0, 0, 1, IPySegmentor::SYLLABLE));
44     TSegment &s = m_segs.back();
45
46     s.m_len = 2;
47     s.m_start = ret;
48     s.m_syllables.clear();
49     s.m_type = IPySegmentor::SYLLABLE;
50     for (; iter != iter_end; iter++) {
51         s.m_syllables.push_back(s_shpData.encodeSyllable(iter->c_str()));
52     }
53
54     return s.m_start;
55 }
56
57 int
58 CHunpinSegmentor::_encode(const char* buf)
59 {
60     CMappedYin syls;
61     syls.reserve(8);
62     s_shpData.getMapString(buf, syls);
63     if (syls.empty())
64         return -1;
65
66     CMappedYin::const_iterator iter = syls.begin();
67     CMappedYin::const_iterator iter_end = syls.end();
68
69     TSegment &s = m_segs.back();
70     s.m_len = 2;
71     s.m_start = m_pystr.size() - s.m_len;
72     s.m_syllables.clear();
73     s.m_type = IPySegmentor::SYLLABLE;
74     for (; iter != iter_end; iter++) {
75         s.m_syllables.push_back(s_shpData.encodeSyllable(iter->c_str()));
76     }
77
78     return s.m_start;
79 }
80
81 bool
82 CHunpinSegmentor::load(const char * pyTrieFileName)
83 {
84     return m_pytrie.load(pyTrieFileName);
85 }
86
87 #if 0
88 void
89 print_pystr(const std::string pystr)
90 {
91     for (const char* c = pystr.c_str();
92          c != pystr.c_str() + pystr.length();
93          ++c) {
94         printf("%c", *c & 0x7f);
95     }
96     printf("<\n");
97 }
98 #endif
99
100 unsigned
101 CHunpinSegmentor::push(unsigned ch)
102 {
103     m_inputBuf.push_back(ch);
104
105     m_updatedFrom = _push(ch);
106
107
108     return m_updatedFrom;
109 }
110
111 unsigned
112 CHunpinSegmentor::pop()
113 {
114     if (m_pystr.empty())
115         return m_updatedFrom = 0;
116
117     unsigned size = m_inputBuf.size();
118     m_inputBuf.resize(size - 1);
119     m_pystr.resize(size - 1);
120
121     unsigned l = m_segs.back().m_len;
122     m_segs.pop_back();
123
124     if (l == 1)
125         return m_updatedFrom = size - 1;
126
127     std::string new_pystr = m_pystr.substr(size - l);
128     m_pystr.resize(size - l);
129
130     m_updatedFrom = _updateWith(new_pystr);
131
132     return m_updatedFrom;
133 }
134
135 unsigned
136 CHunpinSegmentor::insertAt(unsigned idx, unsigned ch)
137 {
138     unsigned i, j;
139     _locateSegment(idx, i, j);
140
141     m_inputBuf.insert(idx, 1, ch);
142     m_pystr.insert(idx, 1, ch);
143
144     std::string new_pystr = m_pystr.substr(i);
145     m_pystr.resize(i);
146     m_segs.erase(m_segs.begin() + j, m_segs.end());
147
148     m_updatedFrom = _updateWith(new_pystr);
149
150     return m_updatedFrom;
151 }
152
153 unsigned
154 CHunpinSegmentor::deleteAt(unsigned idx, bool backward)
155 {
156     unsigned i, j;
157     if (!backward) idx += 1;
158     _locateSegment(idx, i, j);
159
160     m_inputBuf.erase(idx, 1);
161     m_pystr.erase(idx, 1);
162
163     std::string new_pystr = m_pystr.substr(i);
164     m_pystr.resize(i);
165     m_segs.erase(m_segs.begin() + j, m_segs.end());
166
167     m_updatedFrom = _updateWith(new_pystr);
168
169     return m_updatedFrom;
170 }
171
172 unsigned
173 CHunpinSegmentor::clear(unsigned from)
174 {
175     m_inputBuf.resize(from);
176     return _clear(from);
177 }
178
179 unsigned
180 CHunpinSegmentor::_clear(unsigned from)
181 {
182     unsigned i, j;
183     _locateSegment(from, i, j);
184
185
186     std::string new_pystr = m_pystr.substr(i, from - i);
187     m_pystr.resize(i);
188     m_segs.erase(m_segs.begin() + j, m_segs.end());
189
190     m_updatedFrom = _updateWith(new_pystr, from);
191
192     return m_updatedFrom;
193 }
194
195 void
196 CHunpinSegmentor::_locateSegment(unsigned idx,
197                                  unsigned &strIdx,
198                                  unsigned &segIdx)
199 {
200     strIdx = segIdx = 0;
201
202     TSegmentVec::iterator it = m_segs.begin();
203     TSegmentVec::iterator ite = m_segs.end();
204
205     for (; it != ite; ++it) {
206         if (strIdx + (*it).m_len > idx)
207             break;
208
209         strIdx += (*it).m_len;
210         segIdx += 1;
211     }
212 }
213
214 // TOTEST
215 unsigned
216 CHunpinSegmentor::_push(unsigned ch)
217 {
218     m_pystr.push_back(ch);
219
220     TSegmentVec::iterator ite = m_segs.size() > 0 ? m_segs.end() -
221                                 1 : m_segs.begin() - 1;
222     const unsigned maxStringCount = 6;
223     unsigned syllableCount = 0;
224     unsigned stringCount = 0;
225     for (; ite != m_segs.begin() - 1; ite--) {
226         stringCount += (*ite).m_len;
227         syllableCount++;
228         if (stringCount > maxStringCount) {
229             syllableCount--;
230             break;
231         }
232     }
233
234     unsigned strlen = m_pystr.size();
235     unsigned ret;
236
237     for (int index = syllableCount; index >= 0; index--) {
238         TSegmentVec::iterator it = m_segs.end() - index;
239         unsigned tmpl;
240         unsigned v;
241         if (index != 0) {
242             if ((strlen - (*it).m_start) == 2) {
243                 char buf[4];
244                 sprintf(buf, "%c%c", m_pystr[(*it).m_start],
245                         m_pystr[(*it).m_start + 1]);
246                 int startFrom = _encode(buf);
247                 if (startFrom >= 0) break;
248             }
249
250             v = m_pytrie.match_longest(m_pystr.rbegin(),
251                                        m_pystr.rbegin() + strlen -
252                                        (*it).m_start, tmpl);
253
254             if (tmpl == (strlen - (*it).m_start)) {
255                 TSegmentVec new_segs(1, TSegment(v, (*it).m_start, tmpl));
256                 m_segs.erase(m_segs.end() - index, m_segs.end());
257                 std::copy(new_segs.rbegin(), new_segs.rend(),
258                           back_inserter(m_segs));
259
260                 break;
261             }
262         } else {
263             v = m_pytrie.match_longest(m_pystr.rbegin(),
264                                        m_pystr.rbegin() + 1, tmpl);
265             if (tmpl == 0) {
266                 IPySegmentor::ESegmentType seg_type;
267                 if (ch == '\'' && m_inputBuf.size() > 1) {
268                     seg_type = IPySegmentor::SYLLABLE_SEP;
269                 } else if (islower(ch)) {
270                     seg_type = IPySegmentor::INVALID;
271                 } else {
272                     seg_type = IPySegmentor::STRING;
273                 }
274                 ret = m_pystr.size() - 1;
275                 m_segs.push_back(TSegment(ch, ret, 1, seg_type));
276             } else {
277                 ret = m_pystr.size() - 1;
278                 m_segs.push_back(TSegment(v, ret, 1));
279             }
280         }
281     }
282
283     TSegment &last_seg = m_segs.back();
284     if (m_pGetFuzzySyllablesOp && m_pGetFuzzySyllablesOp->isEnabled())
285         if (m_segs.back().m_type == SYLLABLE)
286             _addFuzzySyllables(last_seg);
287
288     return last_seg.m_start;
289 }
290
291 /*
292    //慢算法
293    unsigned CHunpinSegmentor::_push (unsigned ch)
294    {
295         printf("using hunpin_seg");
296         //translation for positive match arithmetic
297         //m_segs.erase (m_segs.begin(), m_segs.end());
298         m_segs.clear();
299         m_pystr.push_back (ch);
300         unsigned strlen = m_pystr.size();
301         unsigned maxlen = 6;
302         unsigned _start = 0;
303
304         while (_start < strlen) {
305                 for (unsigned _tn = (maxlen+_start) <= strlen ? maxlen : (strlen - _start) ; _tn > 0 ; _tn--) {
306
307
308                         if (_tn == 2) {
309                                 char buf[4];
310                                 //printf("\nout,shuang pin output,char1:%c,char2:%c\n",m_pystr[_start],m_pystr[_start+1]);
311
312                                 sprintf(buf, "%c%c", m_pystr[_start], m_pystr[_start+1]);
313                                 int startFrom = _encode(buf,_start);
314                                 if(startFrom >= 0)  {
315                                         //printf("\nin,shuang pin output,char1:%c,char2:%c\n",m_pystr[_start],m_pystr[_start+1]);
316                                         _start += 2;
317                                         break;
318                                 }
319                         }
320
321
322                         unsigned tmpl;
323                         int v  = m_pytrie.match_longest ((m_pystr.rbegin() + strlen - _start - _tn), (m_pystr.rbegin() + strlen - _start), tmpl);
324
325                         //printf("\n input match len is %d,size is %d,_start is %d ,end is %d ,start char is %c,end char is %c\n",tmpl,strlen,_start,_start + _tn,m_pystr[_start],m_pystr[_start+_tn-1]);
326
327                         if(tmpl == _tn) {
328                                 m_segs.push_back (TSegment (v, _start, _tn));
329                                 _start += _tn;
330                                 break;
331                         }
332                         else if(_tn == 1 && tmpl == 0) {
333                                 IPySegmentor::ESegmentType seg_type;
334                                 if (m_pystr[_start] == '\'' && m_inputBuf.size() > 1)
335                                         seg_type = IPySegmentor::SYLLABLE_SEP;
336                                 else if (islower (m_pystr[_start]))
337                                         seg_type = IPySegmentor::INVALID;
338                                 else
339                                         seg_type = IPySegmentor::STRING;
340
341                                 m_segs.push_back (TSegment (m_pystr[_start], _start, 1, seg_type));
342                                 _start += 1;
343                                 break;
344                         }
345                 }
346         }
347
348         TSegment &last_seg = m_segs.back();
349         if (m_pGetFuzzySyllablesOp && m_pGetFuzzySyllablesOp->isEnabled())
350         if ( m_segs.back().m_type == SYLLABLE)
351             _addFuzzySyllables (last_seg);
352
353         return last_seg.m_start;
354    }
355  */
356
357 void
358 CHunpinSegmentor::_addFuzzySyllables(TSegment& seg)
359 {
360     assert(seg.m_type == SYLLABLE);
361
362     seg.m_fuzzy_syllables.clear();
363
364     CSyllables fuzzy_set = (*m_pGetFuzzySyllablesOp)(seg.m_syllables.front());
365     CSyllables::const_iterator it = fuzzy_set.begin();
366     CSyllables::const_iterator ite = fuzzy_set.end();
367
368     for (; it != ite; ++it)
369         seg.m_fuzzy_syllables.push_back(*it);
370 }
371
372 unsigned
373 CHunpinSegmentor::_updateWith(const std::string& new_pystr, unsigned from)
374 {
375     unsigned minUpdatedFrom = from;
376     std::string::const_iterator it = new_pystr.begin();
377     for (; it != new_pystr.end(); ++it) {
378         unsigned updatedFrom = _push(*it & 0x7f);
379
380         if (updatedFrom < minUpdatedFrom) minUpdatedFrom = updatedFrom;
381     }
382     return minUpdatedFrom;
383 }