2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
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
17 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
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.
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.
44 CUserDict::load(const char *fname)
46 int rc = sqlite3_open(":memory:", &m_db);
48 if (rc != SQLITE_OK) {
53 m_fname = strdup(fname);
56 return _createTable() && _createIndexes();
77 CUserDict::addWord(CSyllables &syllables, const wstring& word)
80 assert(syllables.size() >= 2 && syllables.size() <= MAX_USRDEF_WORD_LEN);
84 "INSERT INTO dict (len, i0, f0, t0, i1, f1, t1, i2, f2, t2, i3, f3, t3, i4, f4, t4, i5, f5, t5, utf8str) \
85 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
88 sqlite3_prepare(m_db, sql_str, strlen(sql_str), &stmt, &tail);
91 sqlite3_bind_int(stmt, i++, syllables.size());
93 CSyllables::iterator it = syllables.begin();
94 CSyllables::iterator ite = syllables.end();
95 for (; it != ite; ++it) {
96 sqlite3_bind_int(stmt, i++, it->initial);
97 sqlite3_bind_int(stmt, i++, it->final);
98 sqlite3_bind_int(stmt, i++, it->tone);
101 while (i <= MAX_USRDEF_WORD_LEN * 3 + 1)
102 sqlite3_bind_int(stmt, i++, 0);
104 char buf[MAX_USRDEF_WORD_LEN * 6 + 1];
105 WCSTOMBS(buf, word.c_str(), sizeof(buf) - 1);
106 sqlite3_bind_text(stmt, i, (const char*)buf, strlen(buf), NULL);
108 unsigned ret = (SQLITE_DONE == sqlite3_step(stmt)) ?
109 INI_USRDEF_WID + sqlite3_last_insert_rowid(m_db) :
112 sqlite3_finalize(stmt);
119 CUserDict::removeWord(unsigned wid)
121 assert(m_db != NULL);
123 char sql[256] = "DELETE FROM dict WHERE id=";
125 if (wid > INI_USRDEF_WID) {
126 sprintf(sql, "%s%d;", sql, (wid - INI_USRDEF_WID));
127 sqlite3_exec(m_db, sql, NULL, NULL, &zErr);
129 m_dict.erase(m_dict.find(wid - INI_USRDEF_WID));
135 CUserDict::getWords(CSyllables &syllables,
136 std::vector<CPinyinTrie::TWordIdInfo> &result)
138 assert(m_db != NULL);
142 std::string i_conditions, f_conditions, t_conditions;
143 int length = syllables.size();
148 if (length > MAX_USRDEF_WORD_LEN)
151 for (int i = 0; i < length; i++) {
152 sprintf(buf, " and i%d=%d", i, syllables[i].initial);
155 if (!syllables[i].final)
158 sprintf(buf, " and f%i=%i", i, syllables[i].final);
161 if (!syllables[i].tone)
164 sprintf(buf, " and t%i=%i", i, syllables[i].tone);
168 sql_str = sqlite3_mprintf(
169 "SELECT id, utf8str FROM dict WHERE len=%i%q%q%q;",
171 i_conditions.c_str(),
172 f_conditions.c_str(),
173 t_conditions.c_str());
175 rc = sqlite3_prepare(m_db, sql_str, strlen(sql_str), &stmt, &tail);
176 if (rc != SQLITE_OK) {
177 sqlite3_free(sql_str);
178 fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(m_db));
183 TWCHAR cwstr[MAX_USRDEF_WORD_LEN + 1];
184 const unsigned char *utf8str = NULL;
185 CPinyinTrie::TWordIdInfo word;
187 while (SQLITE_ROW == sqlite3_step(stmt)) {
188 id = sqlite3_column_int(stmt, 0);
189 utf8str = sqlite3_column_text(stmt, 1);
191 if (id >= MAX_USRDEF_WID - INI_USRDEF_WID)
194 memset(&cwstr[0], 0, sizeof(cwstr));
195 MBSTOWCS(cwstr, (const char*)utf8str, MAX_USRDEF_WORD_LEN);
197 word.m_id = id + INI_USRDEF_WID;
199 result.push_back(word);
201 m_dict.insert(std::make_pair(id, wstring(cwstr)));
204 sqlite3_free(sql_str);
205 sqlite3_finalize(stmt);
210 CUserDict::operator [](unsigned wid)
212 assert(m_db != NULL);
214 sqlite3_stmt *stmt = NULL;
219 if (wid <= INI_USRDEF_WID || wid > MAX_USRDEF_WID)
222 wid -= INI_USRDEF_WID;
224 std::map<unsigned, wstring>::const_iterator it = m_dict.find(wid);
225 if (it != m_dict.end())
226 return it->second.c_str();
228 sprintf(sql_str, "SELECT utf8str FROM dict WHERE id=%d;", wid);
230 rc = sqlite3_prepare(m_db, sql_str, strlen(sql_str), &stmt, &tail);
231 if (rc != SQLITE_OK) {
232 fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(m_db));
236 const TWCHAR *ret = NULL;
237 const unsigned char *utf8str = NULL;
238 TWCHAR cwstr[MAX_USRDEF_WORD_LEN + 1];
239 if (SQLITE_ROW == sqlite3_step(stmt)) {
240 utf8str = sqlite3_column_text(stmt, 0);
241 MBSTOWCS(cwstr, (const char*)utf8str, MAX_USRDEF_WORD_LEN);
243 m_dict.insert(std::make_pair(wid, wstr));
247 sqlite3_finalize(stmt);
252 CUserDict::_copyDb(DBCopyDirection direction)
255 int rc = sqlite3_open(m_fname, &disk_db);
257 if (rc == SQLITE_OK) {
258 sqlite3 *dst = direction == Load ? m_db : disk_db;
259 sqlite3 *src = direction == Save ? m_db : disk_db;
260 sqlite3_backup *backup = sqlite3_backup_init(dst, "main", src, "main");
262 sqlite3_backup_step(backup, -1);
263 sqlite3_backup_finish(backup);
265 rc = sqlite3_errcode(dst);
268 sqlite3_close(disk_db);
273 CUserDict::_createTable()
275 assert(m_db != NULL);
279 const char *sql_str =
280 "CREATE TABLE IF NOT EXISTS dict( \
281 id INTEGER PRIMARY KEY, len INTEGER, \
282 i0 INTEGER, i1 INTEGER, i2 INTEGER, i3 INTEGER, i4 INTEGER, i5 INTEGER, \
283 f0 INTEGER, f1 INTEGER, f2 INTEGER, f3 INTEGER, f4 INTEGER, f5 INTEGER, \
284 t0 INTEGER, t1 INTEGER, t2 INTEGER, t3 INTEGER, t4 INTEGER, t5 INTEGER, \
285 utf8str TEXT, UNIQUE (i0, i1, i2, i3, i4, i5, utf8str));";
287 rc = sqlite3_exec(m_db, sql_str, NULL, NULL, &zErr);
288 if (rc != SQLITE_OK) {
290 fprintf(stderr, "SQL error: %s\n", zErr);
300 CUserDict::_createIndexes()
302 assert(m_db != NULL);
306 const char * sql_str =
307 "CREATE INDEX IF NOT EXISTS index_0 ON dict (len, i0, i1, i2, i3, i4, i5);";
309 rc = sqlite3_exec(m_db, sql_str, NULL, NULL, &zErr);
310 if (rc != SQLITE_OK) {
312 fprintf(stderr, "SQL error: %s\n", zErr);