Open Chinese Convert  0.4.3
A project for conversion between Traditional and Simplified Chinese
 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 }