summaryrefslogtreecommitdiff
path: root/mkworddic/writewords.c
diff options
context:
space:
mode:
Diffstat (limited to 'mkworddic/writewords.c')
-rw-r--r--mkworddic/writewords.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/mkworddic/writewords.c b/mkworddic/writewords.c
new file mode 100644
index 0000000..7f248a7
--- /dev/null
+++ b/mkworddic/writewords.c
@@ -0,0 +1,244 @@
+/*
+ * 読みから単語の情報を取得するデータ構造をファイル中に
+ * 出力するためのコード
+ *
+ * データ構造を変更しやすくするためにmkdic.cから分離(2005/7/8)
+ *
+ * output_word_dict()が呼び出される
+ *
+ * Copyright (C) 2000-2006 TABATA Yusuke
+ */
+/*
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <anthy/anthy.h>
+#include <anthy/word_dic.h>
+#include "mkdic.h"
+
+extern FILE *page_out, *page_index_out;
+extern FILE *yomi_entry_index_out, *yomi_entry_out;
+
+static int
+write_word(struct word_entry *we, int encoding)
+{
+ int count;
+ if (encoding == ANTHY_UTF8_ENCODING) {
+ count = fprintf(yomi_entry_out, "%s", we->word_utf8);
+ } else {
+ char *s = anthy_conv_utf8_to_euc(we->word_utf8);
+ count = fprintf(yomi_entry_out, "%s", s);
+ free(s);
+ }
+ return count;
+}
+
+static int
+write_freq(FILE *fp, struct word_entry *we)
+{
+ int count = 0;
+ int freq = we->freq / 100;
+ if (freq != 1) {
+ count += fprintf(fp, "*%d", freq);
+ }
+ return count;
+}
+
+static int
+compare_word_entry(struct word_entry *prev_we,
+ struct word_entry *we)
+{
+ if (strcmp(prev_we->wt_name, we->wt_name) ||
+ (prev_we->freq / 100) != (we->freq / 100) ||
+ prev_we->feature != we->feature) {
+ return 1;
+ }
+ return 0;
+}
+
+/** 一つの読みに対する単語の内容を出力する
+ * 返り値は出力したバイト数
+ */
+static int
+output_word_entry_for_a_yomi(struct yomi_entry *ye, int encoding)
+{
+ int i;
+ int count = 0;
+
+ if (!ye) {
+ return 0;
+ }
+ if (encoding == ANTHY_UTF8_ENCODING) {
+ count ++;
+ fputc('u', yomi_entry_out);
+ }
+ /* 各単語を出力する */
+ for (i = 0; i < ye->nr_entries; i++) {
+ struct word_entry *we = &ye->entries[i];
+ struct word_entry *prev_we = NULL;
+ if (i != 0) {
+ prev_we = &ye->entries[i-1];
+ }
+ /**/
+ if (!we->raw_freq) {
+ continue;
+ }
+ if (i > 0) {
+ /* 二つ目以降は空白から始まる */
+ count += fprintf(yomi_entry_out, " ");
+ }
+ /* 品詞と頻度を出力する */
+ if (i == 0 ||
+ compare_word_entry(prev_we, we)) {
+ count += fprintf(yomi_entry_out, "%s", we->wt_name);
+ if (we->feature != 0) {
+ count += fprintf(yomi_entry_out, ",");
+ }
+ count += write_freq(yomi_entry_out, we);
+ count += fprintf(yomi_entry_out, " ");
+ }
+ /* 単語を出力する場所がこの単語のid */
+ we->offset = count + ye->offset;
+ /* 単語を出力する */
+ count += write_word(we, encoding);
+ }
+
+ fputc(0, yomi_entry_out);
+ return count + 1;
+}
+
+/* 2つの文字列の共通部分の長さを求める */
+static int
+common_len(xstr *s1, xstr *s2)
+{
+ int m,i;
+ if (!s1 || !s2) {
+ return 0;
+ }
+ if (s1->len < s2->len) {
+ m = s1->len;
+ }else{
+ m = s2->len;
+ }
+ for (i = 0; i < m; i++) {
+ if (s1->str[i] != s2->str[i]) {
+ return i;
+ }
+ }
+ return m;
+}
+
+/*
+ * 2つの文字列の差分を出力する
+ * AAA ABBB という2つの文字列を見た場合には
+ * ABBBはAAAのうしろ2文字を消してBBBを付けたものとして
+ * \0x2BBBと出力される。
+ */
+static int
+output_diff(xstr *p, xstr *c, int encoding)
+{
+ int i, m, len = 1;
+ m = common_len(p, c);
+ if (p && p->len > m) {
+ fprintf(page_out, "%c", p->len - m + 1);
+ } else {
+ fprintf(page_out, "%c", 1);
+ }
+ for (i = m; i < c-> len; i++) {
+ char buf[8];
+ len += anthy_sputxchar(buf, c->str[i], encoding);
+ fputs(buf, page_out);
+ }
+ return len;
+}
+
+static void
+begin_new_page(int i)
+{
+ fputc(0, page_out);
+ write_nl(page_index_out, i);
+}
+
+static void
+output_entry_index(int i)
+{
+ write_nl(yomi_entry_index_out, i);
+}
+
+/* 読みの文字列からファイル中の位置(offset)を求めるためのテーブルを作る
+ * page_out, page_index_out, yomi_entry_index_outに出力
+ */
+static void
+generate_yomi_to_offset_map(struct yomi_entry_list *yl)
+{
+ int i;
+ struct yomi_entry *ye = NULL;
+ xstr *prev = NULL;
+ int page_index = 0;
+ /* 読みから位置(offset)を計算するデータ構造を構成する */
+
+ /* まず、最初の読みに対するエントリのインデックスを書き出す */
+ write_nl(page_index_out, page_index);
+ /**/
+ for (i = 0; i < yl->nr_valid_entries; i++) {
+ ye = yl->ye_array[i];
+ /* 新しいページの開始 */
+ if ((i % WORDS_PER_PAGE) == 0 && (i != 0)) {
+ page_index ++;
+ prev = NULL;
+ begin_new_page(page_index);
+ }
+
+ /* 読みに対応する情報を出力する */
+ page_index += output_diff(prev, ye->index_xstr, yl->index_encoding);
+
+ output_entry_index(ye->offset);
+ /***/
+ prev = ye->index_xstr;
+ }
+}
+
+/** 単語辞書を出力する
+ * また、このときに辞書中のオフセットも計算する */
+void
+output_word_dict(struct yomi_entry_list *yl)
+{
+ int entry_index = 0;
+ int i;
+ struct yomi_entry *ye = NULL;
+
+ /* 各読みに対するループ */
+ for (i = 0; i < yl->nr_valid_entries; i++) {
+ /* 単語を出力して、ファイル中の位置(offset)を計算する */
+ ye = yl->ye_array[i];
+ ye->offset = entry_index;
+ entry_index += output_word_entry_for_a_yomi(ye, yl->body_encoding);
+ }
+ /* 読みの文字列からファイル中の位置(offset)を求めるためのテーブルを作る */
+ generate_yomi_to_offset_map(yl);
+
+ /* 最後の読みを終了 */
+ entry_index += output_word_entry_for_a_yomi(ye, yl->body_encoding);
+ write_nl(yomi_entry_index_out, entry_index);
+ write_nl(page_index_out, 0);
+
+ /**/
+ printf("Total %d indexes, %d words, (%d pages).\n",
+ yl->nr_valid_entries,
+ yl->nr_words,
+ yl->nr_valid_entries / WORDS_PER_PAGE + 1);
+}