1 /* 2 * Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "nj_lib.h" 18 #include "nj_err.h" 19 #include "nj_ext.h" 20 #include "nj_dic.h" 21 #include "njd.h" 22 23 #define DATA_SIZE (10) 24 #define DATA_OFFSET_FHINSI (0) 25 #define DATA_OFFSET_BHINSI (1) 26 #define DATA_OFFSET_HINDO (2) 27 #define DATA_OFFSET_CANDIDATE (3) 28 #define DATA_OFFSET_CANDIDATE_LEN (5) 29 #define DATA_OFFSET_YOMI (6) 30 #define DATA_OFFSET_YOMI_LEN (9) 31 32 #define YOMINASI_DIC_FREQ_DIV 63 33 34 #define DATA_FHINSI(x) \ 35 ( (NJ_UINT16)(0x01FF & \ 36 (((NJ_UINT16)*((x)+DATA_OFFSET_FHINSI ) << 1) | \ 37 ( *((x)+DATA_OFFSET_FHINSI+1) >> 7))) ) 38 #define DATA_BHINSI(x) \ 39 ( (NJ_UINT16)(0x01FF & \ 40 (((NJ_UINT16)*((x)+DATA_OFFSET_BHINSI ) << 2) | \ 41 ( *((x)+DATA_OFFSET_BHINSI+1) >> 6))) ) 42 #define DATA_HINDO(x) \ 43 ((NJ_HINDO)(0x003F & ((NJ_UINT16)*((x)+DATA_OFFSET_HINDO)))) 44 #define DATA_CANDIDATE(x) \ 45 ((NJ_UINT32)(0x000FFFFF & \ 46 (((NJ_UINT32)*((x)+DATA_OFFSET_CANDIDATE) << 12) | \ 47 ((NJ_UINT32)*((x)+DATA_OFFSET_CANDIDATE+1) << 4) | \ 48 ( *((x)+DATA_OFFSET_CANDIDATE+2) >> 4)))) 49 #define DATA_CANDIDATE_SIZE(x) \ 50 ((NJ_UINT8)((*((x)+DATA_OFFSET_CANDIDATE_LEN) << 4) | \ 51 (*((x)+DATA_OFFSET_CANDIDATE_LEN+1) >> 4))) 52 #define DATA_YOMI(x) \ 53 ((NJ_UINT32)(0x000FFFFF & \ 54 (((NJ_UINT32)*((x)+DATA_OFFSET_YOMI) << 16) | \ 55 ((NJ_UINT32)*((x)+DATA_OFFSET_YOMI+1) << 8) | \ 56 ( *((x)+DATA_OFFSET_YOMI+2) )))) 57 #define DATA_YOMI_SIZE(x) \ 58 ((NJ_UINT8)((*((x)+DATA_OFFSET_YOMI_LEN)))) 59 60 #define YOMI_INDX_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x1C))) 61 #define YOMI_INDX_CNT(h) ((NJ_UINT16)(NJ_INT16_READ((h)+0x20))) 62 #define YOMI_INDX_BYTE(h) ((NJ_UINT16)(NJ_INT16_READ((h)+0x22))) 63 #define STEM_AREA_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x24))) 64 #define STRS_AREA_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x28))) 65 #define YOMI_AREA_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x2C))) 66 67 #define NO_CONV_FLG ((NJ_UINT32) 0x00080000L) 68 69 #define HINSI_OFFSET (7) 70 71 #define CURRENT_INFO_SET (NJ_UINT8)(0x10) 72 73 static NJ_UINT16 search_data(NJ_SEARCH_CONDITION *condition, NJ_SEARCH_LOCATION_SET *loctset); 74 static NJ_UINT16 convert_to_yomi(NJ_DIC_HANDLE hdl, NJ_UINT8 *index, NJ_UINT16 len, NJ_CHAR *yomi, NJ_UINT16 size); 75 static NJ_UINT16 yomi_strcmp_forward(NJ_DIC_HANDLE hdl, NJ_UINT8 *data, NJ_CHAR *yomi); 76 77 static NJ_UINT16 search_data(NJ_SEARCH_CONDITION *condition, NJ_SEARCH_LOCATION_SET *loctset) 78 { 79 NJ_UINT32 offset; 80 NJ_UINT8 *data; 81 NJ_UINT16 i, j; 82 NJ_UINT16 hindo; 83 NJ_UINT8 hit_flg; 84 NJ_UINT8 *tmp_hinsi = NULL; 85 86 87 offset = loctset->loct.current; 88 data = STEM_AREA_TOP_ADDR(loctset->loct.handle) + offset; 89 90 if (GET_LOCATION_STATUS(loctset->loct.status) != NJ_ST_SEARCH_NO_INIT) { 91 data += DATA_SIZE; 92 offset += DATA_SIZE; 93 94 95 if (data >= STRS_AREA_TOP_ADDR(loctset->loct.handle)) { 96 97 loctset->loct.status = NJ_ST_SEARCH_END; 98 return 0; 99 } 100 } 101 102 103 tmp_hinsi = condition->hinsi.fore; 104 condition->hinsi.fore = condition->hinsi.yominasi_fore; 105 106 i = (STRS_AREA_TOP_ADDR(loctset->loct.handle) - data) / DATA_SIZE; 107 for (j = 0; j < i; j++) { 108 109 if (njd_connect_test(condition, DATA_FHINSI(data), DATA_BHINSI(data))) { 110 111 hit_flg = 0; 112 113 if (condition->operation == NJ_CUR_OP_LINK) { 114 115 hit_flg = 1; 116 } else { 117 118 119 120 if (yomi_strcmp_forward(loctset->loct.handle, data, condition->yomi)) { 121 122 hit_flg = 1; 123 } 124 } 125 126 if (hit_flg) { 127 128 loctset->loct.current_info = CURRENT_INFO_SET; 129 loctset->loct.current = offset; 130 loctset->loct.status = NJ_ST_SEARCH_READY; 131 hindo = DATA_HINDO(STEM_AREA_TOP_ADDR(loctset->loct.handle) + loctset->loct.current); 132 loctset->cache_freq = CALCULATE_HINDO(hindo, loctset->dic_freq.base, 133 loctset->dic_freq.high, YOMINASI_DIC_FREQ_DIV); 134 135 136 condition->hinsi.fore = tmp_hinsi; 137 return 1; 138 } 139 } 140 141 data += DATA_SIZE; 142 offset += DATA_SIZE; 143 } 144 145 loctset->loct.status = NJ_ST_SEARCH_END; 146 147 condition->hinsi.fore = tmp_hinsi; 148 return 0; 149 } 150 151 static NJ_UINT16 convert_to_yomi(NJ_DIC_HANDLE hdl, NJ_UINT8 *index, NJ_UINT16 len, NJ_CHAR *yomi, NJ_UINT16 size) 152 { 153 NJ_UINT8 *wkc; 154 NJ_CHAR *wky; 155 NJ_UINT16 i, idx, yib, ret; 156 NJ_UINT16 j, char_len; 157 158 159 160 wkc = YOMI_INDX_TOP_ADDR(hdl); 161 162 163 yib = YOMI_INDX_BYTE(hdl); 164 165 166 if (NJ_CHAR_ILLEGAL_DIC_YINDEX(yib)) { 167 168 return 0; 169 } 170 171 172 ret = 0; 173 wky = yomi; 174 for (i = 0; i < len; i++) { 175 idx = (NJ_UINT16)((*index - 1) * yib); 176 if (yib == 2) { 177 char_len = UTL_CHAR(wkc + idx); 178 179 if (((ret + char_len + NJ_TERM_LEN) * sizeof(NJ_CHAR)) > size) { 180 return (size / sizeof(NJ_CHAR)); 181 } 182 for (j = 0; j < char_len; j++) { 183 NJ_CHAR_COPY(wky, wkc + idx + j); 184 wky++; 185 ret++; 186 } 187 } else { 188 189 if (((ret + 1 + NJ_TERM_LEN) * sizeof(NJ_CHAR)) > size) { 190 return (size / sizeof(NJ_CHAR)); 191 } 192 *wky++ = (NJ_CHAR)(*(wkc + idx)); 193 ret++; 194 } 195 index++; 196 } 197 *wky = NJ_CHAR_NUL; 198 return ret; 199 } 200 201 static NJ_UINT16 yomi_strcmp_forward(NJ_DIC_HANDLE hdl, NJ_UINT8 *data, NJ_CHAR *yomi) 202 { 203 NJ_UINT8 *area; 204 NJ_CHAR *stroke; 205 NJ_CHAR buf[NJ_MAX_LEN + NJ_TERM_LEN]; 206 NJ_UINT16 ylen, dic_ylen, j, size; 207 208 209 210 size = sizeof(buf); 211 stroke = buf; 212 213 214 area = YOMI_AREA_TOP_ADDR(hdl) + DATA_YOMI(data); 215 216 if (YOMI_INDX_CNT(hdl) == 0) { 217 218 dic_ylen = DATA_YOMI_SIZE(data) / sizeof(NJ_CHAR); 219 220 221 if (size < ((dic_ylen + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 222 return 0; 223 } 224 for (j = 0; j < dic_ylen; j++) { 225 NJ_CHAR_COPY(stroke, area); 226 stroke++; 227 area += sizeof(NJ_CHAR); 228 } 229 *stroke = NJ_CHAR_NUL; 230 } else { 231 232 dic_ylen = convert_to_yomi(hdl, area, DATA_YOMI_SIZE(data), stroke, size); 233 234 235 if (size < ((dic_ylen + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 236 return 0; 237 } 238 } 239 240 241 ylen = nj_strlen(yomi); 242 243 244 if (dic_ylen < ylen) { 245 246 return 0; 247 } 248 249 250 if (nj_strncmp(yomi, buf, ylen) == 0) { 251 252 return 1; 253 } 254 return 0; 255 } 256 257 NJ_INT16 njd_f_search_word(NJ_SEARCH_CONDITION *con, NJ_SEARCH_LOCATION_SET *loctset) 258 { 259 NJ_UINT16 ret; 260 261 switch (con->operation) { 262 case NJ_CUR_OP_LINK: 263 264 265 if ((con->hinsi.yominasi_fore == NULL) || 266 (con->hinsi.foreSize == 0)) { 267 loctset->loct.status = NJ_ST_SEARCH_END; 268 return 0; 269 } 270 break; 271 case NJ_CUR_OP_FORE: 272 273 274 if (NJ_CHAR_STRLEN_IS_0(con->yomi)) { 275 loctset->loct.status = NJ_ST_SEARCH_END; 276 return 0; 277 } 278 279 280 if ((con->hinsi.yominasi_fore == NULL) || 281 (con->hinsi.foreSize == 0)) { 282 loctset->loct.status = NJ_ST_SEARCH_END; 283 return 0; 284 } 285 break; 286 default: 287 288 loctset->loct.status = NJ_ST_SEARCH_END; 289 return 0; 290 } 291 292 293 if (con->mode != NJ_CUR_MODE_FREQ) { 294 295 loctset->loct.status = NJ_ST_SEARCH_END; 296 return 0; 297 } 298 299 300 if ((GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT) 301 || (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_READY)) { 302 303 ret = search_data(con, loctset); 304 if (ret < 1) { 305 306 loctset->loct.status = NJ_ST_SEARCH_END; 307 } 308 return ret; 309 } else { 310 311 loctset->loct.status = NJ_ST_SEARCH_END; 312 return 0; 313 } 314 } 315 316 NJ_INT16 njd_f_get_word(NJ_SEARCH_LOCATION_SET *loctset, NJ_WORD *word) 317 { 318 NJ_UINT8 *data; 319 NJ_CHAR stroke[NJ_MAX_LEN + NJ_TERM_LEN]; 320 NJ_INT16 yomilen, kouholen; 321 322 323 324 if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_END) { 325 return 0; 326 } 327 328 329 data = STEM_AREA_TOP_ADDR(loctset->loct.handle) + loctset->loct.current; 330 331 NJ_SET_YLEN_TO_STEM(word, 1); 332 333 334 word->stem.loc = loctset->loct; 335 yomilen = njd_f_get_stroke(word, stroke, sizeof(stroke)); 336 if (yomilen <= 0) { 337 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_WORD, NJ_ERR_INVALID_RESULT); 338 } 339 word->stem.info1 = yomilen; 340 word->stem.info1 |= (NJ_UINT16)(DATA_FHINSI(data) << HINSI_OFFSET); 341 word->stem.info2 = (NJ_UINT16)(DATA_BHINSI(data) << HINSI_OFFSET); 342 kouholen = (NJ_UINT16)DATA_CANDIDATE_SIZE(data)/sizeof(NJ_CHAR); 343 if (kouholen == 0) { 344 345 kouholen = yomilen; 346 } 347 word->stem.info2 |= kouholen; 348 word->stem.hindo = CALCULATE_HINDO(DATA_HINDO(data), loctset->dic_freq.base, 349 loctset->dic_freq.high, YOMINASI_DIC_FREQ_DIV); 350 351 352 word->stem.type = 0; 353 354 return 1; 355 } 356 357 NJ_INT16 njd_f_get_stroke(NJ_WORD *word, NJ_CHAR *stroke, NJ_UINT16 size) { 358 NJ_SEARCH_LOCATION *loc; 359 NJ_UINT8 *area, *data; 360 NJ_UINT16 len; 361 NJ_UINT32 j; 362 363 if (NJ_GET_YLEN_FROM_STEM(word) == 0) { 364 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_INVALID_RESULT); 365 } 366 367 368 369 loc = &word->stem.loc; 370 data = STEM_AREA_TOP_ADDR(loc->handle) + loc->current; 371 372 373 area = YOMI_AREA_TOP_ADDR(loc->handle) + DATA_YOMI(data); 374 375 if (YOMI_INDX_CNT(loc->handle) == 0) { 376 377 len = DATA_YOMI_SIZE(data)/sizeof(NJ_CHAR); 378 379 380 if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 381 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH); 382 } 383 384 for (j = 0; j < len; j++) { 385 NJ_CHAR_COPY(stroke, area); 386 stroke++; 387 area += sizeof(NJ_CHAR); 388 } 389 *stroke = NJ_CHAR_NUL; 390 } else { 391 392 len = convert_to_yomi(loc->handle, area, DATA_YOMI_SIZE(data), stroke, size); 393 394 395 if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 396 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH); 397 } 398 } 399 return len; 400 } 401 402 NJ_INT16 njd_f_get_candidate(NJ_WORD *word, NJ_CHAR *candidate, NJ_UINT16 size) 403 { 404 NJ_SEARCH_LOCATION *loc; 405 NJ_UINT8 *data, *area; 406 NJ_CHAR work[NJ_MAX_LEN + NJ_TERM_LEN]; 407 NJ_UINT16 len, j; 408 409 410 411 412 loc = &word->stem.loc; 413 data = STEM_AREA_TOP_ADDR(loc->handle) + loc->current; 414 415 416 len = DATA_CANDIDATE_SIZE(data)/sizeof(NJ_CHAR); 417 if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 418 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_CANDIDATE, NJ_ERR_BUFFER_NOT_ENOUGH); 419 } 420 421 422 if (len == 0) { 423 424 area = YOMI_AREA_TOP_ADDR(loc->handle) + DATA_YOMI(data); 425 if (YOMI_INDX_CNT(loc->handle) == 0) { 426 427 len = DATA_YOMI_SIZE(data)/sizeof(NJ_CHAR); 428 429 430 if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 431 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH); 432 } 433 for (j = 0; j < len; j++) { 434 NJ_CHAR_COPY(candidate + j, area); 435 area += sizeof(NJ_CHAR); 436 } 437 candidate[len] = NJ_CHAR_NUL; 438 return len; 439 } else { 440 441 len = convert_to_yomi(loc->handle, area, DATA_YOMI_SIZE(data), work, size); 442 443 444 if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { 445 return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_CANDIDATE, NJ_ERR_BUFFER_NOT_ENOUGH); 446 } 447 } 448 449 if (DATA_CANDIDATE(data) & NO_CONV_FLG) { 450 nje_convert_hira_to_kata(work, candidate, len); 451 } else { 452 for (j = 0; j < len; j++) { 453 candidate[j] = work[j]; 454 } 455 } 456 } else { 457 458 area = STRS_AREA_TOP_ADDR(loc->handle) + DATA_CANDIDATE(data); 459 for (j = 0; j < len; j++) { 460 NJ_CHAR_COPY(candidate + j, area); 461 area += sizeof(NJ_CHAR); 462 } 463 } 464 465 candidate[len] = NJ_CHAR_NUL; 466 return len; 467 } 468