Namazu-devel-ja(旧)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: テスト: UTF-8 の query 対応



寺西です。

Tadamasa Teranishi wrote:
> 
> 現状の Namazu では、UTF-8 で query が送られてくる場合、
> 文字化けを起こし、検索できません。
...
> まだまだテストが十分できていませんが、叩き台にでもなればと思い、
> iconv を使った上記問題対応差分を公開します。(HEAD 用)

eucJP で「朝」「貼」を渡すと誤認することがわかりましたので、
ややコストの高い方法ではありますが、認識力を上げる修正を施しました。
(たぶん、lv, nkf, iconv の自動認識と同程度の能力になっているかと
思います。)

パッチは TEST_UTF8 が定義されていると、UTF-8 で query が送られて
も認識するようになります。

> # 当面、commit するつもりはありません。誤動作しそうだし。

多くの方にテストしていただくために、
方針を変更し、#ifdef TEST_UTF8 〜 #endif で囲んだものを commit 
することにします。(特に問題がなければ)

テスト用スクリプトや autotools 関係の修正といった準備が
整えば、#ifdef TEST_UTF8 〜 #endif をはずそうかと思います。

テストされる際には TEST_UTF8 を定義してください。
-- 
=====================================================================
寺西 忠勝(TADAMASA TERANISHI)  yw3t-trns@xxxxxxxxxxxxxxx
http://www.asahi-net.or.jp/~yw3t-trns/index.htm
Key fingerprint =  474E 4D93 8E97 11F6 662D  8A42 17F5 52F4 10E7 D14E
Index: nmz/codeconv.c
===================================================================
RCS file: /storage/cvsroot/namazu/nmz/codeconv.c,v
retrieving revision 1.32
diff -u -r1.32 codeconv.c
--- nmz/codeconv.c	2 Sep 2001 08:25:33 -0000	1.32
+++ nmz/codeconv.c	28 Jan 2004 21:33:07 -0000
@@ -48,6 +48,12 @@
 #include <strings.h>
 #endif
 
+/* #define TEST_UTF8 */
+
+#ifdef TEST_UTF8
+#    include <iconv.h>
+#endif /* TEST_UTF8 */
+
 #include "libnamazu.h"
 #include "codeconv.h"
 #include "util.h"
@@ -56,6 +62,9 @@
 
 static uchar kanji2nd;
 
+#ifdef TEST_UTF8
+static int nmz_codeconv_jp(char *buffer, int bufferSize);
+#endif /* TEST_UTF8 */
 
 /*
  *
@@ -490,9 +499,250 @@
 nmz_codeconv_query(char *query)
 {
     if (nmz_is_lang_ja()) {
+#ifdef TEST_UTF8
+        if (nmz_codeconv_jp(query, BUFSIZE)) {
+            zen2han(query);
+            return;
+        }
+#endif /* TEST_UTF8 */
         if (nmz_codeconv_internal(query)) {
             zen2han(query);
         }
     }
 }
 
+#ifdef TEST_UTF8
+
+enum code_type {
+    ERROR = -1,
+    TYPE_UNKNOWN = 0,
+    TYPE_JIS,
+    TYPE_UTF8,
+    TYPE_EUCJP,
+    TYPE_SJIS
+};
+
+static int 
+nmz_codeconv_jp(char *buffer, int bufferSize)
+{
+    int i, j;
+    char *bufferJIS;
+    char *bufferUTF8;
+    char *bufferSJIS;
+
+    typedef struct {
+        enum code_type type;
+        int length, bytes;
+    } CODE_DATA;
+
+    CODE_DATA data[3], _data[3];
+    enum code_type resultType = TYPE_UNKNOWN;
+    int count;
+
+
+    if ((bufferJIS = calloc(sizeof(char), bufferSize)) == NULL) {
+	nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
+        return 0;
+    }
+
+    /******************************************/
+    /* ISO-2022-JP                            */
+    /******************************************/
+    {
+        strncpy(bufferJIS, buffer, bufferSize);
+        if (nmz_from_to(bufferJIS, bufferSize, "ISO-2022-JP", "EUC-JP")) {
+            strncpy(buffer, bufferJIS, bufferSize);
+            free(bufferJIS);
+            return 1;
+        }
+    }
+
+    bufferUTF8 = bufferJIS;
+    if ((bufferSJIS = calloc(sizeof(char), bufferSize)) == NULL) {
+        free(bufferUTF8);
+	nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
+        return 0;
+    }
+    bufferUTF8[bufferSize - 1] = '\0';
+
+    /******************************************/
+    /* init                                   */
+    /******************************************/
+    for(i = 0; i < 3; i++) {
+       data[i].length = 0;
+       data[i].bytes = 0;
+    }
+    data[0].type = TYPE_UTF8;
+    data[1].type = TYPE_EUCJP;
+    data[2].type = TYPE_SJIS;
+
+    /******************************************/
+    /* UTF-8                                  */
+    /******************************************/
+    strncpy(bufferUTF8, buffer, bufferSize);
+    if (nmz_from_to(bufferUTF8, bufferSize, "UTF-8", "EUC-JP")) {
+        data[0].length = nmz_lengthEUCJP(bufferUTF8, strlen(bufferUTF8));
+        if (data[0].length != 0) {
+            data[0].bytes = strlen(bufferUTF8);
+        }
+    }
+
+    /******************************************/
+    /* EUC-JP                                 */
+    /******************************************/
+    data[1].length = nmz_lengthEUCJP(buffer, strlen(buffer));
+    if (data[1].length) {
+        data[1].bytes = strlen(buffer);
+    }
+
+    /******************************************/
+    /* SHIFT-JIS                              */
+    /******************************************/
+    strncpy(bufferSJIS, buffer, bufferSize);
+    if (nmz_from_to(bufferSJIS, bufferSize, "SHIFT-JIS", "EUC-JP")) {
+        data[2].length = nmz_lengthEUCJP(bufferSJIS, strlen(bufferSJIS));
+        if (data[2].length != 0) {
+            data[2].bytes = strlen(bufferSJIS);
+        }
+    }
+
+    /******************************************/
+
+    for(i = 0 ; i < 3 - 1; i++) {
+        for(j = i + 1 ; j < 3; j++) {
+            if (data[i].length > data[j].length) {
+                /* swap */
+                CODE_DATA temp;
+
+                temp = data[i];
+                data[i] = data[j];
+                data[j] = temp;
+            }
+        }
+    }
+
+    count = 0;
+    for(i = 0; i < 3; i++) {
+        if (data[i].length == 0) {
+            continue;
+        }
+        _data[count++] = data[i];
+    }
+
+    if (count == 0) {
+        free(bufferUTF8);
+        free(bufferSJIS);
+        return 0;
+    }
+
+    if (count >= 2) {
+        if (_data[0].length == _data[1].length) {
+            if (data[0].bytes > data[1].bytes) {
+                _data[0] = _data[1];
+            }
+        }
+    }
+
+    resultType = _data[0].type;
+
+    /******************************************/
+
+    if (resultType == TYPE_UTF8) {
+        strncpy(buffer, bufferUTF8, bufferSize);
+    } else if (resultType == TYPE_SJIS) {
+        strncpy(buffer, bufferSJIS, bufferSize);
+    }
+
+    free(bufferUTF8);
+    free(bufferSJIS);
+
+    return 1;
+}
+
+char *
+nmz_from_to(char *buffer, int bufferSize,
+    const char *fromCode, const char *toCode)
+{
+    iconv_t cd;
+    size_t sz_from, sz_to;
+    char *toBuffer = NULL;
+    char *from, *to;
+    size_t status;
+
+    sz_from = strlen(buffer) + 1;
+    sz_to = bufferSize;
+
+    toBuffer = (char *)calloc(sizeof(char), sz_to);
+    if (!toBuffer) {
+	nmz_set_dyingmsg(nmz_msg("%s", strerror(errno)));
+        return NULL;
+    }
+
+    from = buffer;
+    to = toBuffer;
+
+    cd = iconv_open(toCode, fromCode);
+
+    status = iconv(cd, &from, &sz_from, &to, &sz_to);
+
+    iconv_close(cd);
+
+    if (status == -1) {
+        if (toBuffer) {
+            free(toBuffer);
+        }
+        return NULL;
+    }
+
+    strncpy(buffer, toBuffer, bufferSize - 1);
+    buffer[bufferSize - 1] = '\0';
+
+    free(toBuffer);
+
+    return buffer;
+}
+
+int 
+nmz_lengthEUCJP(const char *str, int length)
+{
+   int i, mode = 0;
+   unsigned char ch;
+   int count = 0;
+
+   for(i = 0; i < length; i++) {
+       ch = (unsigned char)str[i];
+       if (mode == 0) {
+           count++;
+           if (ch == 0x8e || (ch >= 0xa1 && ch <= 0xfe)) {
+               mode = 1;
+           } else if (ch == 0x8f) {
+               mode = 2;
+           } else if (ch >= 0x80) {
+               return 0;
+           }
+       } else if (mode == 1) {              /* 2bytes char */
+           if (ch >= 0xa1 && ch <= 0xfe) {
+               mode = 0;
+           } else {
+               return 0;
+           }
+       } else if (mode == 2 || mode == 3) { /* 3bytes char */
+           if (ch >= 0xa1 && ch <= 0xfe) {
+               mode++;
+               if (mode == 4) {
+                   mode = 0;
+               }
+           } else {
+               return 0;
+           }
+       }
+   }
+
+   if (mode != 0) {
+       return 0;
+   }
+
+   return count;
+}
+
+#endif /* TEST_UTF8 */
Index: nmz/codeconv.h
===================================================================
RCS file: /storage/cvsroot/namazu/nmz/codeconv.h,v
retrieving revision 1.9
diff -u -r1.9 codeconv.h
--- nmz/codeconv.h	16 Feb 2000 13:14:11 -0000	1.9
+++ nmz/codeconv.h	28 Jan 2004 21:33:07 -0000
@@ -5,4 +5,9 @@
 extern char *nmz_codeconv_external(const char *);
 extern void nmz_codeconv_query ( char *query );
 
+#ifdef TEST_UTF8
+extern char *nmz_from_to(char *buffer, int bufferSize, const char *fromCode, const char *toCode);
+extern int nmz_lengthEUCJP(const char *str, int length);
+#endif /* TEST_UTF8 */
+
 #endif /* _CODECONV_H */