clean up PYConfig.h/cc
[platform/upstream/ibus-libpinyin.git] / src / PYSimpTradConverter.cc
1 /* vim:set et ts=4 sts=4:
2  *
3  * ibus-pinyin - The Chinese PinYin engine for IBus
4  *
5  * Copyright (c) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
6  * Copyright (c) 2010 BYVoid <byvoid1@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25
26 #include "PYSimpTradConverter.h"
27
28 #ifdef HAVE_OPENCC
29 #  include <opencc.h>
30 #else
31 #  include <cstring>
32 #  include <cstdlib>
33 #endif
34
35 #include "PYTypes.h"
36 #include "PYString.h"
37
38 namespace PY {
39
40 #ifdef HAVE_OPENCC
41
42 class opencc {
43     static const int BUFFER_SIZE = 64;
44 public:
45     opencc (void)
46     {
47         m_od = opencc_open (OPENCC_DEFAULT_CONFIG_SIMP_TO_TRAD);
48         g_assert (m_od != NULL);
49     }
50
51     ~opencc (void)
52     {
53         opencc_close(m_od);
54     }
55
56     void convert (const gchar *in, String &out)
57     {
58         glong n_char;
59         gunichar *in_ucs4 = g_utf8_to_ucs4_fast (in, -1, &n_char);
60
61         ucs4_t *pinbuf = (ucs4_t *)in_ucs4;
62         size_t inbuf_left = n_char;
63         while (inbuf_left != 0) {
64             ucs4_t *poutbuf = (ucs4_t *)m_buffer;
65             size_t outbuf_left = BUFFER_SIZE;
66             size_t retval = opencc_convert(m_od, &pinbuf, &inbuf_left, &poutbuf, &outbuf_left);
67             if (retval == (size_t) -1) {
68                 /* append left chars in pinbuf */
69                 g_warning ("opencc_convert return failed");
70                 out << (gunichar *) pinbuf;
71                 break;
72             }
73             *poutbuf = L'\0';
74             out << m_buffer;
75         }
76         g_free (in_ucs4);
77     }
78 private:
79     opencc_t m_od;
80     gunichar m_buffer[BUFFER_SIZE + 1];
81 };
82
83 void
84 SimpTradConverter::simpToTrad (const gchar *in, String &out)
85 {
86     static opencc opencc;
87     opencc.convert (in, out);
88 }
89
90 #else
91
92 static gint _xcmp (const gchar *p1, const gchar *p2, const gchar *str)
93 {
94     for (;;) {
95         // both reach end
96         if (p1 == p2 && *str == '\0')
97             return 0;
98         // p1 reaches end
99         if (p1 == p2)
100             return -1;
101         // str reaches end
102         if (*str == '\0')
103             return 1;
104
105         if (*p1 < *str)
106             return -1;
107         if (*p1 > *str)
108             return 1;
109
110         p1 ++; str ++;
111     };
112 }
113
114 static gint _cmp (gconstpointer p1, gconstpointer p2)
115 {
116     const gchar **pp = (const gchar **) p1;
117     const gchar **s2 = (const gchar **) p2;
118
119     return _xcmp (pp[0], pp[1], s2[0]);
120 }
121
122 #include "PYSimpTradConverterTable.h"
123
124 void
125 SimpTradConverter::simpToTrad (const gchar *in, String &out)
126 {
127     const gchar *pend;
128     const gchar *pp[2];
129     glong len;
130     glong begin;
131
132     if (!g_utf8_validate (in, -1 , NULL)) {
133         g_warning ("\%s\" is not an utf8 string!", in);
134         g_assert_not_reached ();
135     }
136
137     begin = 0;
138     pend = in + std::strlen (in);
139     len = g_utf8_strlen (in, -1);   // length in charactoers
140     pp[0] = in;
141
142     while (pp[0] != pend) {
143         glong slen  = std::min (len - begin, (glong) SIMP_TO_TRAD_MAX_LEN); // the length of sub string in character
144         pp[1] = g_utf8_offset_to_pointer (pp[0], slen);    // the end of sub string
145
146         for (;;) {
147             const gchar **result;
148             result = (const gchar **) std::bsearch (pp, simp_to_trad,
149                                             G_N_ELEMENTS (simp_to_trad), sizeof (simp_to_trad[0]),
150                                             _cmp);
151
152             if (result != NULL) {
153                 // found item in table,
154                 // append the trad to out and adjust pointers
155                 out << result[1];
156                 pp[0] = pp[1];
157                 begin += slen;
158                 break;
159             }
160
161             if (slen == 1) {
162                 // if only one character left,
163                 // append origin character to out and adjust pointers
164                 out.append (pp[0], pp[1] - pp[0]);
165                 pp[0] = pp[1];
166                 begin += 1;
167                 break;
168             }
169
170             // if more than on characters left,
171             // adjust pp[1] to previous character
172             pp[1] = g_utf8_prev_char (pp[1]);
173             slen--;
174         }
175     }
176 }
177 #endif
178
179 }