namazu-dev(ring)


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

internal/suffix match



古川です。

日本語の中間一致、後方一致を正規表現検索として扱うときに、NMZ.w を日本
語の先頭まで seek しておいたほうが、速くなるはず、と思います。

具体的には、'*' の後の文字の最上位ビットが立っていたら、NMZ.w を、「先
頭の文字の最上位ビットが立っている行」まで seek します。(新形式では、
NMZ.wi があるので、それが可能になっています)


ただ、ちょっと迷うところがありまして…

(1) seek 位置をいつ計算するか。

下のコードでは、検索時に計算しています。これを、あらかじめ mknmz で計算
しておいて、ファイルに記録しておけば、もう少し速くなるかもしれません。
ただ、どのファイルに記録するか…(または、これだけのために新しくファイル
を作るか?)


(2) 世界進出との兼ね合い

この話は、ASCII と EUC-JP が、必ず別の単語に分かれることが前堤になって
います。Latin などでは、ASCII と共に一つの単語を構成することがあるので、
適用できません。何らかの方法で、seek する/しないを切り換える必要があり
そうです。そういった意味では、(1) は mknmz で行なうようにして、ついでに
日本語かどうか判断するようにしたほうがいいかも。


というわけで、直ちに commit はせず、patch を付けておくことにします。

-- 

                                        ヤマハ(株)ピアノプレーヤ設計課
                                                              古川 令
                                             furukawa@xxxxxxxxxxxxxxxx


--- re.c.orig	Mon Sep 13 13:32:21 1999
+++ re.c	Fri Sep 17 02:32:24 1999
@@ -142,11 +142,11 @@
     return 0;
 }
 
-HLIST regex_grep(uchar *orig_expr, FILE *fp, uchar *field, int field_mode)
+HLIST regex_grep(uchar *orig_expr, FILE *fp, uchar *field, int field_mode, int i)
 {
     unsigned char buf[BUFSIZE], expr[BUFSIZE];
     REGEX *rp;
-    int i, n, size = 0, max, uri_mode = 0;
+    int n, size = 0, max, uri_mode = 0;
     HLIST val, tmp;
     val.n = 0;
 
@@ -180,7 +180,7 @@
 
     re_compile_pattern(expr, strlen(expr), rp);
 
-    for (i = n = 0; fgets(buf, BUFSIZE, fp); i++) {
+    for (n = 0; fgets(buf, BUFSIZE, fp); i++) {
         if (*(lastc(buf)) != '\n') {  /* too long */
             i--;
             continue;
--- re.h.orig	Mon Sep 13 13:32:21 1999
+++ re.h	Fri Sep 17 02:30:52 1999
@@ -6,6 +6,6 @@
 #define MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(n))
 
 int replace_uri(uchar*);
-HLIST regex_grep(uchar*, FILE*, uchar*, int);
+HLIST regex_grep(uchar*, FILE*, uchar*, int, int);
 
 #endif /* _RE_H */
--- search.c.orig	Thu Sep 16 23:49:48 1999
+++ search.c	Fri Sep 17 02:54:22 1999
@@ -68,7 +68,7 @@
 HLIST cmp_phrase_hash(int, HLIST, FILE *, FILE *);
 int open_phrase_index_files(FILE**, FILE**);
 HLIST do_phrase_search(uchar*, HLIST);
-void do_regex_preprocessing(uchar*);
+int do_regex_preprocessing(uchar*);
 HLIST do_regex_search(uchar*, HLIST);
 void get_expr(uchar*, uchar*);
 HLIST do_field_search(uchar*, HLIST);
@@ -444,26 +444,27 @@
 }
 
 #define iseuc(c)  ((c) >= 0xa1 && (c) <= 0xfe)
-void do_regex_preprocessing(uchar *expr)
+int do_regex_preprocessing(uchar *expr)
 {
-    if (*expr == '*' && *(lastc(expr)) != '*') {
+    if (*expr == '*') {
+        int ret = (0x80 & *strcpy(expr, expr + 1));
+        if (*(lastc(expr)) == '*') {
+            /* if internal match such as '*foo*', enforce it into regex */
+            *(lastc(expr)) = '\0';
+        } else {
         /* if suffix match such as '*bar', enforce it into regex */
-        strcpy(expr, expr + 1);
         strcat(expr, "$");
+        }
+        return ret;
     } else if (*expr != '*' && *(lastc(expr)) == '*') {
         /* if prefix match such as 'bar*', enforce it into regex */
         *(lastc(expr)) = '.';
         strcat(expr, "*");
-    } else if (*expr == '*' && *(lastc(expr)) == '*') {
-        /* if internal match such as '*foo*', enforce it into regex */
-        strcpy(expr, expr + 1);
-        *(lastc(expr)) = '\0';
     } else if (*expr == '/' && *(lastc(expr)) == '/') {
         /* genuine regex */
         /* remove the both of '/' chars at begging and end of string */
         strcpy(expr, expr + 1); 
         *(lastc(expr))= '\0';
-        return;
     } else {
         uchar buf[BUFSIZE * 2], *bufp, *exprp;
 
@@ -488,15 +489,17 @@
         *bufp = '\0';
         strcpy(expr, buf);
     }
+    return 0;
 }
 
 HLIST do_regex_search(uchar *orig_expr, HLIST val)
 {
+    int offset;
     FILE *fp;
     uchar expr[BUFSIZE * 2]; /* because of escaping meta characters */
 
     strcpy(expr, orig_expr);
-    do_regex_preprocessing(expr);
+    offset = do_regex_preprocessing(expr);
 
     fp = fopen(NMZ.w, "rb");
     if (fp == NULL) {
@@ -504,7 +507,26 @@
         val.n = ERR_REGEX_SEARCH_FAILED;  /* cannot open regex index */
         return val;
     }
-    val = regex_grep(expr, fp, "", 0);
+    if (offset) {
+        FILE *fwi = fopen(NMZ.wi, "rb");
+        offset = 0;
+        if (fwi) {
+            int l, x;
+            lrget(0, &l, &offset);
+            while (l < offset) {
+                x = (l + offset) / 2;
+                fseek(fp, getidxptr(fwi, x), 0L);
+                if (fgetc(fp) & 0x80){
+                    offset = x;
+                } else {
+                    l = x + 1;
+                }
+            }
+            fseek(fp, getidxptr(fwi, offset), 0);
+            fclose(fwi);
+        }
+    }
+    val = regex_grep(expr, fp, "", 0, offset);
     fclose(fp);
     return val;
 
@@ -535,7 +557,7 @@
         val.n = -4;  /* cannot open field index */
         return val;
     }
-    val = regex_grep(expr, fp, field_name, 1); /* last argument must be 1 */
+    val = regex_grep(expr, fp, field_name, 1, 0); /* 4th argument must be 1 */
     fclose(fp);
     return val;
 }