| /* |
| * Copyright (C) 2008,2009 OMRON SOFTWARE Co., Ltd. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "nj_lib.h" |
| #include "nj_err.h" |
| #include "nj_ext.h" |
| #include "nj_dic.h" |
| #include "njd.h" |
| |
| #define DATA_SIZE (10) |
| #define DATA_OFFSET_FHINSI (0) |
| #define DATA_OFFSET_BHINSI (1) |
| #define DATA_OFFSET_HINDO (2) |
| #define DATA_OFFSET_CANDIDATE (3) |
| #define DATA_OFFSET_CANDIDATE_LEN (5) |
| #define DATA_OFFSET_YOMI (6) |
| #define DATA_OFFSET_YOMI_LEN (9) |
| |
| #define YOMINASI_DIC_FREQ_DIV 63 |
| |
| #define DATA_FHINSI(x) \ |
| ( (NJ_UINT16)(0x01FF & \ |
| (((NJ_UINT16)*((x)+DATA_OFFSET_FHINSI ) << 1) | \ |
| ( *((x)+DATA_OFFSET_FHINSI+1) >> 7))) ) |
| #define DATA_BHINSI(x) \ |
| ( (NJ_UINT16)(0x01FF & \ |
| (((NJ_UINT16)*((x)+DATA_OFFSET_BHINSI ) << 2) | \ |
| ( *((x)+DATA_OFFSET_BHINSI+1) >> 6))) ) |
| #define DATA_HINDO(x) \ |
| ((NJ_HINDO)(0x003F & ((NJ_UINT16)*((x)+DATA_OFFSET_HINDO)))) |
| #define DATA_CANDIDATE(x) \ |
| ((NJ_UINT32)(0x000FFFFF & \ |
| (((NJ_UINT32)*((x)+DATA_OFFSET_CANDIDATE) << 12) | \ |
| ((NJ_UINT32)*((x)+DATA_OFFSET_CANDIDATE+1) << 4) | \ |
| ( *((x)+DATA_OFFSET_CANDIDATE+2) >> 4)))) |
| #define DATA_CANDIDATE_SIZE(x) \ |
| ((NJ_UINT8)((*((x)+DATA_OFFSET_CANDIDATE_LEN) << 4) | \ |
| (*((x)+DATA_OFFSET_CANDIDATE_LEN+1) >> 4))) |
| #define DATA_YOMI(x) \ |
| ((NJ_UINT32)(0x000FFFFF & \ |
| (((NJ_UINT32)*((x)+DATA_OFFSET_YOMI) << 16) | \ |
| ((NJ_UINT32)*((x)+DATA_OFFSET_YOMI+1) << 8) | \ |
| ( *((x)+DATA_OFFSET_YOMI+2) )))) |
| #define DATA_YOMI_SIZE(x) \ |
| ((NJ_UINT8)((*((x)+DATA_OFFSET_YOMI_LEN)))) |
| |
| #define YOMI_INDX_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x1C))) |
| #define YOMI_INDX_CNT(h) ((NJ_UINT16)(NJ_INT16_READ((h)+0x20))) |
| #define YOMI_INDX_BYTE(h) ((NJ_UINT16)(NJ_INT16_READ((h)+0x22))) |
| #define STEM_AREA_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x24))) |
| #define STRS_AREA_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x28))) |
| #define YOMI_AREA_TOP_ADDR(h) ((NJ_UINT8*)((h)+NJ_INT32_READ((h)+0x2C))) |
| |
| #define NO_CONV_FLG ((NJ_UINT32) 0x00080000L) |
| |
| #define HINSI_OFFSET (7) |
| |
| #define CURRENT_INFO_SET (NJ_UINT8)(0x10) |
| |
| static NJ_UINT16 search_data(NJ_SEARCH_CONDITION *condition, NJ_SEARCH_LOCATION_SET *loctset); |
| static NJ_UINT16 convert_to_yomi(NJ_DIC_HANDLE hdl, NJ_UINT8 *index, NJ_UINT16 len, NJ_CHAR *yomi, NJ_UINT16 size); |
| static NJ_UINT16 yomi_strcmp_forward(NJ_DIC_HANDLE hdl, NJ_UINT8 *data, NJ_CHAR *yomi); |
| |
| static NJ_UINT16 search_data(NJ_SEARCH_CONDITION *condition, NJ_SEARCH_LOCATION_SET *loctset) |
| { |
| NJ_UINT32 offset; |
| NJ_UINT8 *data; |
| NJ_UINT16 i, j; |
| NJ_UINT16 hindo; |
| NJ_UINT8 hit_flg; |
| NJ_UINT8 *tmp_hinsi = NULL; |
| |
| |
| offset = loctset->loct.current; |
| data = STEM_AREA_TOP_ADDR(loctset->loct.handle) + offset; |
| |
| if (GET_LOCATION_STATUS(loctset->loct.status) != NJ_ST_SEARCH_NO_INIT) { |
| data += DATA_SIZE; |
| offset += DATA_SIZE; |
| |
| |
| if (data >= STRS_AREA_TOP_ADDR(loctset->loct.handle)) { |
| |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| } |
| |
| |
| tmp_hinsi = condition->hinsi.fore; |
| condition->hinsi.fore = condition->hinsi.yominasi_fore; |
| |
| i = (STRS_AREA_TOP_ADDR(loctset->loct.handle) - data) / DATA_SIZE; |
| for (j = 0; j < i; j++) { |
| |
| if (njd_connect_test(condition, DATA_FHINSI(data), DATA_BHINSI(data))) { |
| |
| hit_flg = 0; |
| |
| if (condition->operation == NJ_CUR_OP_LINK) { |
| |
| hit_flg = 1; |
| } else { |
| |
| |
| |
| if (yomi_strcmp_forward(loctset->loct.handle, data, condition->yomi)) { |
| |
| hit_flg = 1; |
| } |
| } |
| |
| if (hit_flg) { |
| |
| loctset->loct.current_info = CURRENT_INFO_SET; |
| loctset->loct.current = offset; |
| loctset->loct.status = NJ_ST_SEARCH_READY; |
| hindo = DATA_HINDO(STEM_AREA_TOP_ADDR(loctset->loct.handle) + loctset->loct.current); |
| loctset->cache_freq = CALCULATE_HINDO(hindo, loctset->dic_freq.base, |
| loctset->dic_freq.high, YOMINASI_DIC_FREQ_DIV); |
| |
| |
| condition->hinsi.fore = tmp_hinsi; |
| return 1; |
| } |
| } |
| |
| data += DATA_SIZE; |
| offset += DATA_SIZE; |
| } |
| |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| |
| condition->hinsi.fore = tmp_hinsi; |
| return 0; |
| } |
| |
| static NJ_UINT16 convert_to_yomi(NJ_DIC_HANDLE hdl, NJ_UINT8 *index, NJ_UINT16 len, NJ_CHAR *yomi, NJ_UINT16 size) |
| { |
| NJ_UINT8 *wkc; |
| NJ_CHAR *wky; |
| NJ_UINT16 i, idx, yib, ret; |
| NJ_UINT16 j, char_len; |
| |
| |
| |
| wkc = YOMI_INDX_TOP_ADDR(hdl); |
| |
| |
| yib = YOMI_INDX_BYTE(hdl); |
| |
| |
| if (NJ_CHAR_ILLEGAL_DIC_YINDEX(yib)) { |
| |
| return 0; |
| } |
| |
| |
| ret = 0; |
| wky = yomi; |
| for (i = 0; i < len; i++) { |
| idx = (NJ_UINT16)((*index - 1) * yib); |
| if (yib == 2) { |
| char_len = UTL_CHAR(wkc + idx); |
| |
| if (((ret + char_len + NJ_TERM_LEN) * sizeof(NJ_CHAR)) > size) { |
| return (size / sizeof(NJ_CHAR)); |
| } |
| for (j = 0; j < char_len; j++) { |
| NJ_CHAR_COPY(wky, wkc + idx + j); |
| wky++; |
| ret++; |
| } |
| } else { |
| |
| if (((ret + 1 + NJ_TERM_LEN) * sizeof(NJ_CHAR)) > size) { |
| return (size / sizeof(NJ_CHAR)); |
| } |
| *wky++ = (NJ_CHAR)(*(wkc + idx)); |
| ret++; |
| } |
| index++; |
| } |
| *wky = NJ_CHAR_NUL; |
| return ret; |
| } |
| |
| static NJ_UINT16 yomi_strcmp_forward(NJ_DIC_HANDLE hdl, NJ_UINT8 *data, NJ_CHAR *yomi) |
| { |
| NJ_UINT8 *area; |
| NJ_CHAR *stroke; |
| NJ_CHAR buf[NJ_MAX_LEN + NJ_TERM_LEN]; |
| NJ_UINT16 ylen, dic_ylen, j, size; |
| |
| |
| |
| size = sizeof(buf); |
| stroke = buf; |
| |
| |
| area = YOMI_AREA_TOP_ADDR(hdl) + DATA_YOMI(data); |
| |
| if (YOMI_INDX_CNT(hdl) == 0) { |
| |
| dic_ylen = DATA_YOMI_SIZE(data) / sizeof(NJ_CHAR); |
| |
| |
| if (size < ((dic_ylen + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return 0; |
| } |
| for (j = 0; j < dic_ylen; j++) { |
| NJ_CHAR_COPY(stroke, area); |
| stroke++; |
| area += sizeof(NJ_CHAR); |
| } |
| *stroke = NJ_CHAR_NUL; |
| } else { |
| |
| dic_ylen = convert_to_yomi(hdl, area, DATA_YOMI_SIZE(data), stroke, size); |
| |
| |
| if (size < ((dic_ylen + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return 0; |
| } |
| } |
| |
| |
| ylen = nj_strlen(yomi); |
| |
| |
| if (dic_ylen < ylen) { |
| |
| return 0; |
| } |
| |
| |
| if (nj_strncmp(yomi, buf, ylen) == 0) { |
| |
| return 1; |
| } |
| return 0; |
| } |
| |
| NJ_INT16 njd_f_search_word(NJ_SEARCH_CONDITION *con, NJ_SEARCH_LOCATION_SET *loctset) |
| { |
| NJ_UINT16 ret; |
| |
| switch (con->operation) { |
| case NJ_CUR_OP_LINK: |
| |
| |
| if ((con->hinsi.yominasi_fore == NULL) || |
| (con->hinsi.foreSize == 0)) { |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| break; |
| case NJ_CUR_OP_FORE: |
| |
| |
| if (NJ_CHAR_STRLEN_IS_0(con->yomi)) { |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| |
| |
| if ((con->hinsi.yominasi_fore == NULL) || |
| (con->hinsi.foreSize == 0)) { |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| break; |
| default: |
| |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| |
| |
| if (con->mode != NJ_CUR_MODE_FREQ) { |
| |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| |
| |
| if ((GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_NO_INIT) |
| || (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_READY)) { |
| |
| ret = search_data(con, loctset); |
| if (ret < 1) { |
| |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| } |
| return ret; |
| } else { |
| |
| loctset->loct.status = NJ_ST_SEARCH_END; |
| return 0; |
| } |
| } |
| |
| NJ_INT16 njd_f_get_word(NJ_SEARCH_LOCATION_SET *loctset, NJ_WORD *word) |
| { |
| NJ_UINT8 *data; |
| NJ_CHAR stroke[NJ_MAX_LEN + NJ_TERM_LEN]; |
| NJ_INT16 yomilen, kouholen; |
| |
| |
| |
| if (GET_LOCATION_STATUS(loctset->loct.status) == NJ_ST_SEARCH_END) { |
| return 0; |
| } |
| |
| |
| data = STEM_AREA_TOP_ADDR(loctset->loct.handle) + loctset->loct.current; |
| |
| NJ_SET_YLEN_TO_STEM(word, 1); |
| |
| |
| word->stem.loc = loctset->loct; |
| yomilen = njd_f_get_stroke(word, stroke, sizeof(stroke)); |
| if (yomilen <= 0) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_WORD, NJ_ERR_INVALID_RESULT); |
| } |
| word->stem.info1 = yomilen; |
| word->stem.info1 |= (NJ_UINT16)(DATA_FHINSI(data) << HINSI_OFFSET); |
| word->stem.info2 = (NJ_UINT16)(DATA_BHINSI(data) << HINSI_OFFSET); |
| kouholen = (NJ_UINT16)DATA_CANDIDATE_SIZE(data)/sizeof(NJ_CHAR); |
| if (kouholen == 0) { |
| |
| kouholen = yomilen; |
| } |
| word->stem.info2 |= kouholen; |
| word->stem.hindo = CALCULATE_HINDO(DATA_HINDO(data), loctset->dic_freq.base, |
| loctset->dic_freq.high, YOMINASI_DIC_FREQ_DIV); |
| |
| |
| word->stem.type = 0; |
| |
| return 1; |
| } |
| |
| NJ_INT16 njd_f_get_stroke(NJ_WORD *word, NJ_CHAR *stroke, NJ_UINT16 size) { |
| NJ_SEARCH_LOCATION *loc; |
| NJ_UINT8 *area, *data; |
| NJ_UINT16 len; |
| NJ_UINT32 j; |
| |
| if (NJ_GET_YLEN_FROM_STEM(word) == 0) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_INVALID_RESULT); |
| } |
| |
| |
| |
| loc = &word->stem.loc; |
| data = STEM_AREA_TOP_ADDR(loc->handle) + loc->current; |
| |
| |
| area = YOMI_AREA_TOP_ADDR(loc->handle) + DATA_YOMI(data); |
| |
| if (YOMI_INDX_CNT(loc->handle) == 0) { |
| |
| len = DATA_YOMI_SIZE(data)/sizeof(NJ_CHAR); |
| |
| |
| if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH); |
| } |
| |
| for (j = 0; j < len; j++) { |
| NJ_CHAR_COPY(stroke, area); |
| stroke++; |
| area += sizeof(NJ_CHAR); |
| } |
| *stroke = NJ_CHAR_NUL; |
| } else { |
| |
| len = convert_to_yomi(loc->handle, area, DATA_YOMI_SIZE(data), stroke, size); |
| |
| |
| if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH); |
| } |
| } |
| return len; |
| } |
| |
| NJ_INT16 njd_f_get_candidate(NJ_WORD *word, NJ_CHAR *candidate, NJ_UINT16 size) |
| { |
| NJ_SEARCH_LOCATION *loc; |
| NJ_UINT8 *data, *area; |
| NJ_CHAR work[NJ_MAX_LEN + NJ_TERM_LEN]; |
| NJ_UINT16 len, j; |
| |
| |
| |
| |
| loc = &word->stem.loc; |
| data = STEM_AREA_TOP_ADDR(loc->handle) + loc->current; |
| |
| |
| len = DATA_CANDIDATE_SIZE(data)/sizeof(NJ_CHAR); |
| if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_CANDIDATE, NJ_ERR_BUFFER_NOT_ENOUGH); |
| } |
| |
| |
| if (len == 0) { |
| |
| area = YOMI_AREA_TOP_ADDR(loc->handle) + DATA_YOMI(data); |
| if (YOMI_INDX_CNT(loc->handle) == 0) { |
| |
| len = DATA_YOMI_SIZE(data)/sizeof(NJ_CHAR); |
| |
| |
| if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_STROKE, NJ_ERR_BUFFER_NOT_ENOUGH); |
| } |
| for (j = 0; j < len; j++) { |
| NJ_CHAR_COPY(candidate + j, area); |
| area += sizeof(NJ_CHAR); |
| } |
| candidate[len] = NJ_CHAR_NUL; |
| return len; |
| } else { |
| |
| len = convert_to_yomi(loc->handle, area, DATA_YOMI_SIZE(data), work, size); |
| |
| |
| if (size < ((len + NJ_TERM_LEN) * sizeof(NJ_CHAR))) { |
| return NJ_SET_ERR_VAL(NJ_FUNC_NJD_F_GET_CANDIDATE, NJ_ERR_BUFFER_NOT_ENOUGH); |
| } |
| } |
| |
| if (DATA_CANDIDATE(data) & NO_CONV_FLG) { |
| nje_convert_hira_to_kata(work, candidate, len); |
| } else { |
| for (j = 0; j < len; j++) { |
| candidate[j] = work[j]; |
| } |
| } |
| } else { |
| |
| area = STRS_AREA_TOP_ADDR(loc->handle) + DATA_CANDIDATE(data); |
| for (j = 0; j < len; j++) { |
| NJ_CHAR_COPY(candidate + j, area); |
| area += sizeof(NJ_CHAR); |
| } |
| } |
| |
| candidate[len] = NJ_CHAR_NUL; |
| return len; |
| } |