[Groonga-commit] groonga/groonga [master] query_expand() defined in proc.c

Back to archive index

null+****@clear***** null+****@clear*****
2011年 9月 9日 (金) 14:18:08 JST


Daijiro MORI	2011-09-09 05:18:08 +0000 (Fri, 09 Sep 2011)

  New Revision: ff4d5dea6120217cf3186f74bf18a5924c5f404b

  Log:
    query_expand() defined in proc.c

  Modified files:
    lib/proc.c

  Modified: lib/proc.c (+125 -0)
===================================================================
--- lib/proc.c    2011-09-08 09:21:10 +0000 (df56479)
+++ lib/proc.c    2011-09-09 05:18:08 +0000 (14864b1)
@@ -38,6 +38,131 @@ const char *grn_document_root = NULL;
 
 #define VAR GRN_PROC_GET_VAR_BY_OFFSET
 
+/**** query expander ****/
+
+static grn_rc
+query_subst(grn_ctx *ctx, grn_obj *table, grn_obj *column,
+            const char *key, size_t key_size, grn_obj *dest)
+{
+  grn_id id;
+  grn_rc rc = GRN_END_OF_DATA;
+  if ((id = grn_table_get(ctx, table, (const void *)key, (unsigned) key_size))) {
+    grn_obj_get_value(ctx, column, id, dest);
+    rc = GRN_SUCCESS;
+  }
+  return rc;
+}
+
+static grn_rc
+query_expand(grn_ctx *ctx, grn_obj *table, grn_obj *column, grn_expr_flags flags,
+             const char *str, const char *str_end, grn_obj *dest)
+{
+  grn_obj buf;
+  unsigned int len;
+  const char *start, *cur = str;
+  GRN_TEXT_INIT(&buf, 0);
+  for (;;) {
+    while (cur < str_end && grn_isspace(cur, ctx->encoding)) {
+      if (!(len = grn_charlen(ctx, cur, str_end))) { goto exit; }
+      GRN_TEXT_PUT(ctx, dest, cur, len);
+      cur += len;
+    }
+    if (str_end <= cur) { break; }
+    switch (*cur) {
+    case '\0' :
+      goto exit;
+      break;
+    case GRN_QUERY_AND :
+    case GRN_QUERY_ADJ_INC :
+    case GRN_QUERY_ADJ_DEC :
+    case GRN_QUERY_ADJ_NEG :
+    case GRN_QUERY_BUT :
+    case GRN_QUERY_PARENL :
+    case GRN_QUERY_PARENR :
+    case GRN_QUERY_PREFIX :
+      GRN_TEXT_PUTC(ctx, dest, *cur);
+      cur++;
+      break;
+    case GRN_QUERY_QUOTEL :
+      GRN_BULK_REWIND(&buf);
+      for (start = cur++; cur < str_end; cur += len) {
+        if (!(len = grn_charlen(ctx, cur, str_end))) {
+          goto exit;
+        } else if (len == 1) {
+          if (*cur == GRN_QUERY_QUOTER) {
+            cur++;
+            break;
+          } else if (cur + 1 < str_end && *cur == GRN_QUERY_ESCAPE) {
+            cur++;
+            len = grn_charlen(ctx, cur, str_end);
+          }
+        }
+        GRN_TEXT_PUT(ctx, &buf, cur, len);
+      }
+      if (query_subst(ctx, table, column, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf), dest)) {
+        GRN_TEXT_PUT(ctx, dest, start, cur - start);
+      }
+      break;
+    case 'O' :
+      if (cur + 2 < str_end && cur[1] == 'R' && grn_isspace(cur + 2, ctx->encoding)) {
+        GRN_TEXT_PUT(ctx, dest, cur, 2);
+        cur += 2;
+        break;
+      }
+      /* fallthru */
+    default :
+      for (start = cur; cur < str_end; cur += len) {
+        if (!(len = grn_charlen(ctx, cur, str_end))) {
+          goto exit;
+        } else if (grn_isspace(cur, ctx->encoding)) {
+          break;
+        } else if (len == 1) {
+          if (*cur == GRN_QUERY_PARENL ||
+              *cur == GRN_QUERY_PARENR ||
+              *cur == GRN_QUERY_PREFIX) {
+            break;
+          } else if (flags & GRN_EXPR_ALLOW_COLUMN && *cur == GRN_QUERY_COLUMN) {
+            if (cur + 1 < str_end) {
+              switch (cur[1]) {
+              case '!' :
+              case '@' :
+              case '^' :
+              case '$' :
+                cur += 2;
+                break;
+              case '=' :
+                cur += (flags & GRN_EXPR_ALLOW_UPDATE) ? 2 : 1;
+                break;
+              case '<' :
+              case '>' :
+                cur += (cur + 2 < str_end && cur[2] == '=') ? 3 : 2;
+                break;
+              default :
+                cur += 1;
+                break;
+              }
+            } else {
+              cur += 1;
+            }
+            GRN_TEXT_PUT(ctx, dest, start, cur - start);
+            start = cur;
+            break;
+          }
+        }
+      }
+      if (start < cur) {
+        if (query_subst(ctx, table, column, start, cur - start, dest)) {
+          GRN_TEXT_PUT(ctx, dest, start, cur - start);
+        }
+      }
+      break;
+    }
+  }
+exit :
+  GRN_OBJ_FIN(ctx, &buf);
+  return GRN_SUCCESS;
+}
+
 /**** procs ****/
 
 #define DEFAULT_LIMIT           10




Groonga-commit メーリングリストの案内
Back to archive index