27#if defined(_WIN32) && !defined(__GNUC__)
28# define strtok_r(str, delim, saveptr) strtok_s(str, delim, saveptr)
33static const char kAmbigDelimiters[] =
"\t ";
34static const char kIllegalMsg[] =
"Illegal ambiguity specification on line %d\n";
35static const char kIllegalUnicharMsg[] =
"Illegal unichar %s in ambiguity specification\n";
52 for (
unsigned i = 0;
i < unicharset.
size(); ++
i) {
53 replace_ambigs_.push_back(
nullptr);
54 dang_ambigs_.push_back(
nullptr);
55 one_to_one_definite_ambigs_.push_back(
nullptr);
56 if (use_ambigs_for_adaption) {
57 ambigs_for_adaption_.push_back(
nullptr);
58 reverse_ambigs_for_adaption_.push_back(
nullptr);
73 int debug_level,
bool use_ambigs_for_adaption,
77 tprintf(
"Reading ambiguities\n");
80 int test_ambig_part_size;
81 int replacement_ambig_part_size;
85 char *buffer =
new char[kBufferSize];
93 ASSERT_HOST(ambig_file->
FGets(buffer, kBufferSize) !=
nullptr && buffer[0] !=
'\0');
95 version =
static_cast<int>(strtol(buffer + 1,
nullptr, 10));
100 while (ambig_file->
FGets(buffer, kBufferSize) !=
nullptr) {
102 if (debug_level > 2) {
103 tprintf(
"read line %s\n", buffer);
106 if (!ParseAmbiguityLine(line_num, version, debug_level, encoder_set, buffer,
107 &test_ambig_part_size, test_unichar_ids, &replacement_ambig_part_size,
108 replacement_string, &
type)) {
114 test_ambig_part_size, test_unichar_ids, replacement_ambig_part_size,
115 replacement_string,
type, ambig_spec, unicharset)) {
120 if (test_ambig_part_size == 1 && replacement_ambig_part_size == 1 &&
type ==
DEFINITE_AMBIG) {
121 if (one_to_one_definite_ambigs_[test_unichar_ids[0]] ==
nullptr) {
122 one_to_one_definite_ambigs_[test_unichar_ids[0]] =
new UnicharIdVector();
124 one_to_one_definite_ambigs_[test_unichar_ids[0]]->push_back(ambig_spec->correct_ngram_id);
127 if (use_ambigs_for_adaption) {
128 std::vector<UNICHAR_ID> encoding;
131 if (unicharset->
encode_string(replacement_string,
true, &encoding,
nullptr,
nullptr)) {
132 for (
int i = 0;
i < test_ambig_part_size; ++
i) {
133 if (ambigs_for_adaption_[test_unichar_ids[
i]] ==
nullptr) {
136 adaption_ambigs_entry = ambigs_for_adaption_[test_unichar_ids[
i]];
137 for (
int id_to_insert : encoding) {
143 j < adaption_ambigs_entry->size() && (*adaption_ambigs_entry)[j] > id_to_insert;
146 if (j < adaption_ambigs_entry->size()) {
147 if ((*adaption_ambigs_entry)[j] != id_to_insert) {
148 adaption_ambigs_entry->insert(adaption_ambigs_entry->begin() + j, id_to_insert);
151 adaption_ambigs_entry->push_back(id_to_insert);
161 if (use_ambigs_for_adaption) {
162 for (
size_t i = 0;
i < ambigs_for_adaption_.size(); ++
i) {
163 adaption_ambigs_entry = ambigs_for_adaption_[
i];
164 if (adaption_ambigs_entry ==
nullptr) {
167 for (
size_t j = 0; j < adaption_ambigs_entry->size(); ++j) {
168 UNICHAR_ID ambig_id = (*adaption_ambigs_entry)[j];
169 if (reverse_ambigs_for_adaption_[ambig_id] ==
nullptr) {
172 reverse_ambigs_for_adaption_[ambig_id]->push_back(
i);
178 if (debug_level > 1) {
179 for (
int tbl = 0; tbl < 2; ++tbl) {
181 for (
size_t i = 0;
i < print_table.size(); ++
i) {
182 AmbigSpec_LIST *lst = print_table[
i];
183 if (lst ==
nullptr) {
187 tprintf(
"%s Ambiguities for %s:\n", (tbl == 0) ?
"Replaceable" :
"Dangerous",
190 AmbigSpec_IT lst_it(lst);
191 for (lst_it.mark_cycle_pt(); !lst_it.cycled_list(); lst_it.forward()) {
200 if (use_ambigs_for_adaption) {
201 for (
int vec_id = 0; vec_id < 2; ++vec_id) {
202 const std::vector<UnicharIdVector *> &vec =
203 (vec_id == 0) ? ambigs_for_adaption_ : reverse_ambigs_for_adaption_;
204 for (
size_t i = 0;
i < vec.size(); ++
i) {
205 adaption_ambigs_entry = vec[
i];
206 if (adaption_ambigs_entry !=
nullptr) {
207 tprintf(
"%sAmbigs for adaption for %s:\n", (vec_id == 0) ?
"" :
"Reverse ",
209 for (
size_t j = 0; j < adaption_ambigs_entry->size(); ++j) {
220bool UnicharAmbigs::ParseAmbiguityLine(
int line_num,
int version,
int debug_level,
222 int *test_ambig_part_size,
UNICHAR_ID *test_unichar_ids,
223 int *replacement_ambig_part_size,
char *replacement_string,
227 std::string input(buffer);
228 std::vector<std::string> fields =
split(input,
' ');
229 if (fields.size() != 3) {
231 tprintf(kIllegalMsg, line_num);
236 std::vector<UNICHAR_ID> unichars;
237 if (!unicharset.
encode_string(fields[0].c_str(),
true, &unichars,
nullptr,
nullptr)) {
240 *test_ambig_part_size = unichars.size();
243 tprintf(
"Too many unichars in ambiguity on line %d\n", line_num);
248 for (
size_t i = 0;
i < unichars.size(); ++
i) {
249 test_unichar_ids[
i] = unichars[
i];
251 test_unichar_ids[unichars.size()] = INVALID_UNICHAR_ID;
253 if (!unicharset.
encode_string(fields[1].c_str(),
true, &unichars,
nullptr,
nullptr)) {
256 *replacement_ambig_part_size = unichars.size();
259 tprintf(
"Too many unichars in ambiguity on line %d\n", line_num);
263 if (sscanf(fields[2].c_str(),
"%d",
type) != 1) {
265 tprintf(kIllegalMsg, line_num);
275 if (!(token = strtok_r(buffer, kAmbigDelimiters, &next_token)) ||
276 !sscanf(token,
"%d", test_ambig_part_size) || *test_ambig_part_size <= 0) {
278 tprintf(kIllegalMsg, line_num);
284 tprintf(
"Too many unichars in ambiguity on line %d\n", line_num);
288 for (
i = 0;
i < *test_ambig_part_size; ++
i) {
289 if (!(token = strtok_r(
nullptr, kAmbigDelimiters, &next_token))) {
294 tprintf(kIllegalUnicharMsg, token);
300 test_unichar_ids[
i] = INVALID_UNICHAR_ID;
302 if (
i != *test_ambig_part_size || !(token = strtok_r(
nullptr, kAmbigDelimiters, &next_token)) ||
303 !sscanf(token,
"%d", replacement_ambig_part_size) || *replacement_ambig_part_size <= 0) {
305 tprintf(kIllegalMsg, line_num);
311 tprintf(
"Too many unichars in ambiguity on line %d\n", line_num);
315 replacement_string[0] =
'\0';
316 for (
i = 0;
i < *replacement_ambig_part_size; ++
i) {
317 if (!(token = strtok_r(
nullptr, kAmbigDelimiters, &next_token))) {
320 strcat(replacement_string, token);
323 tprintf(kIllegalUnicharMsg, token);
328 if (
i != *replacement_ambig_part_size) {
330 tprintf(kIllegalMsg, line_num);
344 if (!(token = strtok_r(
nullptr, kAmbigDelimiters, &next_token)) || !sscanf(token,
"%d",
type)) {
346 tprintf(kIllegalMsg, line_num);
355 UNICHAR_ID *test_unichar_ids,
int replacement_ambig_part_size,
356 const char *replacement_string,
int type, AmbigSpec *ambig_spec,
357 UNICHARSET *unicharset) {
359 if (test_ambig_part_size == 1 && replacement_ambig_part_size == 1 &&
360 unicharset->to_lower(test_unichar_ids[0]) ==
361 unicharset->to_lower(unicharset->unichar_to_id(replacement_string))) {
365 ambig_spec->wrong_ngram_size =
380 ambig_spec->correct_ngram_id = unicharset->unichar_to_id(replacement_string);
381 if (replacement_ambig_part_size > 1) {
382 unicharset->set_isngram(ambig_spec->correct_ngram_id,
true);
386 for (
i = 0;
i < test_ambig_part_size; ++
i) {
388 if (test_ambig_part_size == 1) {
389 unichar_id = ambig_spec->correct_ngram_id;
391 std::string frag_str =
394 unichar_id = unicharset->unichar_to_id(frag_str.c_str());
396 ambig_spec->correct_fragments[
i] = unichar_id;
398 ambig_spec->correct_fragments[
i] = INVALID_UNICHAR_ID;
402 if (table[test_unichar_ids[0]] ==
nullptr) {
403 table[test_unichar_ids[0]] =
new AmbigSpec_LIST();
const char kUniversalAmbigsFile[]
std::vector< AmbigSpec_LIST * > UnicharAmbigsVector
void tprintf(const char *format,...)
void chomp_string(char *str)
const int ksizeofUniversalAmbigsFile
const int kMaxAmbigStringSize
std::vector< UNICHAR_ID > UnicharIdVector
const std::vector< std::string > split(const std::string &s, char c)
static void print(const UNICHAR_ID array[], const UNICHARSET &unicharset)
static int copy(const UNICHAR_ID src[], UNICHAR_ID dst[])
UNICHAR_ID correct_ngram_id
UNICHAR_ID wrong_ngram[MAX_AMBIG_SIZE+1]
static int compare_ambig_specs(const void *spec1, const void *spec2)
UNICHAR_ID correct_fragments[MAX_AMBIG_SIZE+1]
void LoadUniversal(const UNICHARSET &encoder_set, UNICHARSET *unicharset)
void InitUnicharAmbigs(const UNICHARSET &unicharset, bool use_ambigs_for_adaption)
void LoadUnicharAmbigs(const UNICHARSET &encoder_set, TFile *ambigs_file, int debug_level, bool use_ambigs_for_adaption, UNICHARSET *unicharset)
char * FGets(char *buffer, int buffer_size)
std::string to_string() const
bool encode_string(const char *str, bool give_up_on_failure, std::vector< UNICHAR_ID > *encoding, std::vector< char > *lengths, unsigned *encoded_length) const
bool contains_unichar(const char *const unichar_repr) const
UNICHAR_ID unichar_to_id(const char *const unichar_repr) const
std::string debug_str(UNICHAR_ID id) const
static FILE * Open(const std::string &filename, const std::string &mode)