Home | History | Annotate | Download | only in engine
      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