Namazu-devel-ja(旧)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: テスト: UTF-8 の query 対応
- From: Tadamasa Teranishi <yw3t-trns@xxxxxxxxxxxxxxx>
- Date: Thu, 29 Jan 2004 06:57:14 +0900
- X-ml-name: namazu-devel-ja
- X-mail-count: 03612
- References: <400FE43C.98DB7A5@asahi-net.or.jp>
寺西です。
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 */