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 <assert.h> 39 #include "userdict.h" 40 41 42 bool CUserDict::load(const char *fname) 43 { 44 int rc = sqlite3_open(fname, &m_db); 45 46 if (rc != SQLITE_OK) { 47 sqlite3_close(m_db); 48 return false; 49 } 50 51 return _createTable() && _createIndexes(); 52 } 53 54 55 void CUserDict::free() 56 { 57 if (m_db) { 58 sqlite3_close(m_db); 59 m_db = NULL; 60 } 61 } 62 63 64 unsigned CUserDict::addWord (CSyllables &syllables, const wstring& word) 65 { 66 assert(m_db != NULL); 67 assert (syllables.size() >= 2 && syllables.size() <= MAX_USRDEF_WORD_LEN); 68 69 sqlite3_stmt *stmt; 70 const char *sql_str = 71 "INSERT INTO dict (len, i0, f0, t0, i1, f1, t1, i2, f2, t2, i3, f3, t3, i4, f4, t4, i5, f5, t5, utf8str) \ 72 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"; 73 const char *tail; 74 75 sqlite3_prepare (m_db, sql_str, strlen(sql_str), &stmt, &tail); 76 77 int i = 1; 78 sqlite3_bind_int (stmt, i++, syllables.size()); 79 80 CSyllables::iterator it = syllables.begin(); 81 CSyllables::iterator ite = syllables.end(); 82 for (; it != ite; ++it) { 83 sqlite3_bind_int (stmt, i++, it->initial); 84 sqlite3_bind_int (stmt, i++, it->final); 85 sqlite3_bind_int (stmt, i++, it->tone); 86 } 87 88 while (i <= MAX_USRDEF_WORD_LEN*3 + 1) 89 sqlite3_bind_int (stmt, i++, 0); 90 91 char buf[MAX_USRDEF_WORD_LEN*6+1]; 92 WCSTOMBS(buf, word.c_str(), sizeof(buf) - 1); 93 sqlite3_bind_text (stmt, i, (const char *)buf, strlen(buf), NULL); 94 95 unsigned ret = (SQLITE_DONE == sqlite3_step (stmt))? 96 INI_USRDEF_WID + sqlite3_last_insert_rowid (m_db): 97 0; 98 99 sqlite3_finalize (stmt); 100 return ret; 101 } 102 103 104 void CUserDict::removeWord (unsigned wid) 105 { 106 assert (m_db != NULL); 107 char *zErr = NULL; 108 char sql[256] = "DELETE FROM dict WHERE id="; 109 110 if (wid > INI_USRDEF_WID) { 111 sprintf(sql, "%s%d;", sql, (wid - INI_USRDEF_WID)); 112 sqlite3_exec(m_db, sql, NULL, NULL, &zErr); 113 } 114 } 115 116 117 void CUserDict::getWords (CSyllables &syllables, 118 std::vector<CPinyinTrie::TWordIdInfo> &result) 119 { 120 assert (m_db != NULL); 121 122 char *sql_str; 123 const char *tail; 124 std::string i_conditions, f_conditions, t_conditions; 125 int length = syllables.size(); 126 sqlite3_stmt *stmt; 127 int rc; 128 char buf[256]; 129 130 if (length > MAX_USRDEF_WORD_LEN) 131 return; 132 133 for (int i=0; i<length; i++) { 134 sprintf (buf, " and i%d=%d", i, syllables[i].initial); 135 i_conditions += buf; 136 137 if (!syllables[i].final) 138 continue; 139 140 sprintf (buf, " and f%i=%i", i, syllables[i].final); 141 f_conditions += buf; 142 143 if (!syllables[i].tone) 144 continue; 145 146 sprintf (buf, " and t%i=%i", i, syllables[i].tone); 147 t_conditions += buf; 148 } 149 150 sql_str = sqlite3_mprintf("SELECT id, utf8str FROM dict WHERE len=%i%q%q%q;", 151 length, i_conditions.c_str(), f_conditions.c_str(), t_conditions.c_str()); 152 153 rc = sqlite3_prepare(m_db, sql_str, strlen (sql_str), &stmt, &tail); 154 if(rc != SQLITE_OK) { 155 sqlite3_free(sql_str); 156 fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(m_db)); 157 return; 158 } 159 160 unsigned id = 0; 161 TWCHAR cwstr[MAX_USRDEF_WORD_LEN + 1]; 162 const unsigned char *utf8str = NULL; 163 CPinyinTrie::TWordIdInfo word; 164 165 while(SQLITE_ROW == sqlite3_step(stmt)) { 166 id = sqlite3_column_int (stmt, 0); 167 utf8str = sqlite3_column_text (stmt, 1); 168 169 if (id >= MAX_USRDEF_WID - INI_USRDEF_WID) 170 continue; 171 172 memset(&cwstr[0], 0, sizeof(cwstr)); 173 MBSTOWCS(cwstr, (const char*)utf8str, MAX_USRDEF_WORD_LEN); 174 175 word.m_id = id + INI_USRDEF_WID; 176 word.m_len = length; 177 word.m_bSeen = 1; 178 result.push_back (word); 179 180 m_dict.insert (std::make_pair (id, wstring(cwstr))); 181 } 182 183 sqlite3_free(sql_str); 184 sqlite3_finalize(stmt); 185 } 186 187 188 const TWCHAR* CUserDict::operator [] (unsigned wid) 189 { 190 assert (m_db != NULL); 191 192 sqlite3_stmt *stmt=NULL; 193 int rc = SQLITE_OK; 194 const char *tail; 195 char sql_str[256]; 196 197 if (wid <= INI_USRDEF_WID || wid > MAX_USRDEF_WID) 198 return NULL; 199 200 wid -= INI_USRDEF_WID; 201 202 std::map<unsigned, wstring>::const_iterator it = m_dict.find(wid); 203 if (it != m_dict.end ()) 204 return it->second.c_str (); 205 206 sprintf (sql_str, "SELECT utf8str FROM dict WHERE id=%d;", wid); 207 208 rc = sqlite3_prepare(m_db, sql_str, strlen(sql_str), &stmt, &tail); 209 if(rc != SQLITE_OK) { 210 fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(m_db)); 211 return NULL; 212 } 213 214 const TWCHAR *ret = NULL; 215 const unsigned char *utf8str = NULL; 216 TWCHAR cwstr[MAX_USRDEF_WORD_LEN + 1]; 217 if (SQLITE_ROW == sqlite3_step(stmt)) { 218 utf8str = sqlite3_column_text(stmt, 0); 219 MBSTOWCS(cwstr, (const char*)utf8str, MAX_USRDEF_WORD_LEN); 220 wstring wstr(cwstr); 221 m_dict.insert (std::make_pair (wid, wstr)); 222 ret = wstr.c_str(); 223 } 224 225 sqlite3_finalize (stmt); 226 return ret; 227 } 228 229 230 bool CUserDict::_createTable() 231 { 232 assert(m_db != NULL); 233 234 char *zErr = NULL; 235 int rc = SQLITE_OK; 236 const char *sql_str = 237 "CREATE TABLE IF NOT EXISTS dict( \ 238 id INTEGER PRIMARY KEY, len INTEGER, \ 239 i0 INTEGER, i1 INTEGER, i2 INTEGER, i3 INTEGER, i4 INTEGER, i5 INTEGER, \ 240 f0 INTEGER, f1 INTEGER, f2 INTEGER, f3 INTEGER, f4 INTEGER, f5 INTEGER, \ 241 t0 INTEGER, t1 INTEGER, t2 INTEGER, t3 INTEGER, t4 INTEGER, t5 INTEGER, \ 242 utf8str TEXT, UNIQUE (i0, i1, i2, i3, i4, i5, utf8str));"; 243 244 rc = sqlite3_exec(m_db, sql_str, NULL, NULL, &zErr); 245 if(rc != SQLITE_OK) { 246 if (zErr != NULL) { 247 fprintf(stderr, "SQL error: %s\n", zErr); 248 sqlite3_free(zErr); 249 } 250 return false; 251 } 252 253 return true; 254 } 255 256 bool CUserDict::_createIndexes() 257 { 258 assert(m_db!=NULL); 259 260 char *zErr = NULL; 261 int rc = SQLITE_OK; 262 const char * sql_str = 263 "CREATE INDEX IF NOT EXISTS index_0 ON dict (len, i0, i1, i2, i3, i4, i5);"; 264 265 rc = sqlite3_exec(m_db, sql_str, NULL, NULL, &zErr); 266 if(rc != SQLITE_OK) { 267 if (zErr != NULL) { 268 fprintf(stderr, "SQL error: %s\n", zErr); 269 sqlite3_free(zErr); 270 } 271 return false; 272 } 273 274 return true; 275 } 276
