Open Chinese Convert 0.4.3 A project for conversion between Traditional and Simplified Chinese

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

All Data Structures Files Functions Variables Groups Pages
dict_group.c
1 /*
2 * Open Chinese Convert
3 *
4 * Copyright 2010-2013 BYVoid <byvoid@byvoid.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "config_reader.h"
20 #include "dict_group.h"
21 #include "dict_chain.h"
22
23 static dictionary_error errnum = DICTIONARY_ERROR_VOID;
24
25 DictGroup* dict_group_new(DictChain* dict_chain) {
26 DictGroup* dict_group =
27 (DictGroup*)malloc(sizeof(DictGroup));
28 dict_group->count = 0;
29 dict_group->dict_chain = dict_chain;
30 return dict_group;
31 }
32
33 void dict_group_delete(DictGroup* dict_group) {
34 size_t i;
35 for (i = 0; i < dict_group->count; i++) {
36 dict_delete(dict_group->dicts[i]);
37 }
38 free(dict_group);
39 }
40
41 static char* try_find_dictionary_with_config(
42 DictGroup* dict_group,
43 const char* filename) {
44 if (is_absolute_path(filename)) {
45 return NULL;
46 }
47 /* Get config path */
48 if (dict_group->dict_chain == NULL) {
49 return NULL;
50 }
51 Config* config = dict_group->dict_chain->config;
52 if (config == NULL) {
53 return NULL;
54 }
55 const char* config_path = config->file_path;
56 if (config_path == NULL) {
57 return NULL;
58 }
59 char* config_path_filename = (char*)malloc(strlen(config_path) + strlen(
60 filename) + 2);
61 sprintf(config_path_filename, "%s/%s", config_path, filename);
62 FILE* fp = fopen(config_path_filename, "r");
63 if (fp) {
64 fclose(fp);
65 return config_path_filename;
66 }
67 return NULL;
68 }
69
70 int dict_group_load(DictGroup* dict_group,
71 const char* filename,
72 opencc_dictionary_type type) {
73 Dict* dictionary;
74 char* path = try_open_file(filename);
75 if (path == NULL) {
76 path = try_find_dictionary_with_config(dict_group, filename);
77 if (path == NULL) {
78 errnum = DICTIONARY_ERROR_CANNOT_ACCESS_DICTFILE;
79 return -1;
80 }
81 }
82 dictionary = dict_new(path, type);
83 free(path);
84 if (dictionary == (Dict*)-1) {
85 errnum = DICTIONARY_ERROR_INVALID_DICT;
86 return -1;
87 }
88 dict_group->dicts[dict_group->count++] = dictionary;
89 return 0;
90 }
91
92 Dict* dict_group_get_dict(DictGroup* dict_group, size_t index) {
93 if (index >= dict_group->count) {
94 errnum = DICTIONARY_ERROR_INVALID_INDEX;
95 return (Dict*)-1;
96 }
97 return dict_group->dicts[index];
98 }
99
100 const ucs4_t* const* dict_group_match_longest(
101 DictGroup* dict_group,
102 const ucs4_t* word,
103 size_t maxlen,
104 size_t* match_length) {
105 if (dict_group->count == 0) {
106 errnum = DICTIONARY_ERROR_NODICT;
107 return (const ucs4_t* const*)-1;
108 }
109 const ucs4_t* const* retval = NULL;
110 size_t t_match_length, max_length = 0;
111 size_t i;
112 for (i = 0; i < dict_group->count; i++) {
113 /* 依次查找每個辭典，取得最長匹配長度 */
114 const ucs4_t* const* t_retval = dict_match_longest(
115 dict_group->dicts[i],
116 word,
117 maxlen,
118 &t_match_length);
119 if (t_retval != NULL) {
120 if (t_match_length > max_length) {
121 max_length = t_match_length;
122 retval = t_retval;
123 }
124 }
125 }
126 if (match_length != NULL) {
127 *match_length = max_length;
128 }
129 return retval;
130 }
131
132 size_t dict_group_get_all_match_lengths(DictGroup* dict_group,
133 const ucs4_t* word,
134 size_t* match_length) {
135 if (dict_group->count == 0) {
136 errnum = DICTIONARY_ERROR_NODICT;
137 return (size_t)-1;
138 }
139 size_t rscnt = 0;
140 size_t i;
141 for (i = 0; i < dict_group->count; i++) {
142 size_t retval;
143 retval = dict_get_all_match_lengths(
144 dict_group->dicts[i],
145 word,
146 match_length + rscnt
147 );
148 rscnt += retval;
149 /* 去除重複長度 */
150 if ((i > 0) && (rscnt > 1)) {
151 qsort(match_length, rscnt, sizeof(match_length[0]), qsort_int_cmp);
152 size_t j, k;
153 for (j = 0, k = 1; k < rscnt; k++) {
154 if (match_length[k] != match_length[j]) {
155 match_length[++j] = match_length[k];
156 }
157 }
158 rscnt = j + 1;
159 }
160 }
161 return rscnt;
162 }
163
164 dictionary_error dictionary_errno(void) {
165 return errnum;
166 }
167
168 void dictionary_perror(const char* spec) {
169 perr(spec);
170 perr("\n");
171 switch (errnum) {
172 case DICTIONARY_ERROR_VOID:
173 break;
174 case DICTIONARY_ERROR_NODICT:
175 perr(_("No dictionary loaded"));
176 break;
177 case DICTIONARY_ERROR_CANNOT_ACCESS_DICTFILE:
178 perror(_("Can not open dictionary file"));
179 break;
180 case DICTIONARY_ERROR_INVALID_DICT:
181 perror(_("Invalid dictionary file"));
182 break;
183 case DICTIONARY_ERROR_INVALID_INDEX:
184 perror(_("Invalid dictionary index"));
185 break;
186 default:
187 perr(_("Unknown"));
188 }
189 }
SDictChain
Definition: common.h:71
SDict
Definition: common.h:58
SConfig
Definition: common.h:84
SDictGroup
Definition: common.h:64