[Groonga-commit] groonga/groonga at f9f095f [master] string_substring: support negative from

Back to archive index

Kouhei Sutou null+****@clear*****
Tue Jul 5 20:18:08 JST 2016


Kouhei Sutou	2016-07-05 20:18:08 +0900 (Tue, 05 Jul 2016)

  New Revision: f9f095f3eabdedc4cfe1d6e8391b8e273f9369ce
  https://github.com/groonga/groonga/commit/f9f095f3eabdedc4cfe1d6e8391b8e273f9369ce

  Message:
    string_substring: support negative from

  Added files:
    test/command/suite/select/function/string/string_substring/from_negative.expected
    test/command/suite/select/function/string/string_substring/from_negative.test
  Modified files:
    plugins/functions/string.c

  Modified: plugins/functions/string.c (+116 -14)
===================================================================
--- plugins/functions/string.c    2016-07-05 19:28:19 +0900 (2a17680)
+++ plugins/functions/string.c    2016-07-05 20:18:08 +0900 (9d2b90b)
@@ -85,12 +85,14 @@ func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args,
                       grn_user_data *user_data)
 {
   grn_obj *target;
+  grn_obj *from_raw;
+  grn_obj *length_raw = NULL;
   size_t string_length = 0;
-  uint64_t from = 0;
-  uint64_t length = 0;
+  int64_t from = 0;
+  int64_t length = -1;
   const char *start;
   const char *end;
-  grn_obj *grn_text;
+  grn_obj *substring;
 
   if (n_args < 2) {
     GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
@@ -100,10 +102,9 @@ func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args,
   }
 
   target = args[0];
-  from = GRN_UINT64_VALUE(args[1]);
-
+  from_raw = args[1];
   if (n_args == 3) {
-    length = GRN_UINT64_VALUE(args[2]);
+    length_raw = args[2];
   }
 
   if (!(target->header.type == GRN_BULK &&
@@ -121,11 +122,117 @@ func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args,
     return NULL;
   }
 
+  /* TODO: extract as grn_func_arg_int64() */
+  if (!grn_type_id_is_number_family(ctx, from_raw->header.domain)) {
+    grn_obj inspected;
+
+    GRN_TEXT_INIT(&inspected, 0);
+    grn_inspect(ctx, &inspected, from_raw);
+    GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
+                     "string_substring(): from must be a number: <%.*s>",
+                     (int)GRN_TEXT_LEN(&inspected),
+                     GRN_TEXT_VALUE(&inspected));
+    GRN_OBJ_FIN(ctx, &inspected);
+    return NULL;
+  }
+  if (from_raw->header.domain == GRN_DB_INT32) {
+    from = GRN_INT32_VALUE(from_raw);
+  } else if (from_raw->header.domain == GRN_DB_INT64) {
+    from = GRN_INT64_VALUE(from_raw);
+  } else {
+    grn_obj buffer;
+    grn_rc rc;
+
+    GRN_INT64_INIT(&buffer, 0);
+    rc = grn_obj_cast(ctx, from_raw, &buffer, GRN_FALSE);
+    if (rc == GRN_SUCCESS) {
+      from = GRN_INT64_VALUE(&buffer);
+    }
+    GRN_OBJ_FIN(ctx, &buffer);
+
+    if (rc != GRN_SUCCESS) {
+      grn_obj inspected;
+
+      GRN_TEXT_INIT(&inspected, 0);
+      grn_inspect(ctx, &inspected, from_raw);
+      GRN_PLUGIN_ERROR(ctx, rc,
+                       "string_substring(): "
+                       "failed to cast from value to number: <%.*s>",
+                       (int)GRN_TEXT_LEN(&inspected),
+                       GRN_TEXT_VALUE(&inspected));
+      GRN_OBJ_FIN(ctx, &inspected);
+      return NULL;
+    }
+  }
+
+  if (length_raw) {
+    /* TODO: extract as grn_func_arg_int64() */
+    if (!grn_type_id_is_number_family(ctx, length_raw->header.domain)) {
+      grn_obj inspected;
+
+      GRN_TEXT_INIT(&inspected, 0);
+      grn_inspect(ctx, &inspected, length_raw);
+      GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
+                       "string_substring(): length must be a number: <%.*s>",
+                       (int)GRN_TEXT_LEN(&inspected),
+                       GRN_TEXT_VALUE(&inspected));
+      GRN_OBJ_FIN(ctx, &inspected);
+      return NULL;
+    }
+    if (length_raw->header.domain == GRN_DB_INT32) {
+      length = GRN_INT32_VALUE(length_raw);
+    } else if (length_raw->header.domain == GRN_DB_INT64) {
+      length = GRN_INT64_VALUE(length_raw);
+    } else {
+      grn_obj buffer;
+      grn_rc rc;
+
+      GRN_INT64_INIT(&buffer, 0);
+      rc = grn_obj_cast(ctx, length_raw, &buffer, GRN_FALSE);
+      if (rc == GRN_SUCCESS) {
+        length = GRN_INT64_VALUE(&buffer);
+      }
+      GRN_OBJ_FIN(ctx, &buffer);
+
+      if (rc != GRN_SUCCESS) {
+        grn_obj inspected;
+
+        GRN_TEXT_INIT(&inspected, 0);
+        grn_inspect(ctx, &inspected, length_raw);
+        GRN_PLUGIN_ERROR(ctx, rc,
+                         "string_substring(): "
+                         "failed to cast length value to number: <%.*s>",
+                         (int)GRN_TEXT_LEN(&inspected),
+                         GRN_TEXT_VALUE(&inspected));
+        GRN_OBJ_FIN(ctx, &inspected);
+        return NULL;
+      }
+    }
+  }
+
+  substring = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, 0);
+  if (!substring) {
+    return NULL;
+  }
+
+  GRN_BULK_REWIND(substring);
+
+  if (GRN_TEXT_LEN(target) == 0) {
+    return substring;
+  }
+  if (length == 0) {
+    return substring;
+  }
+
+  while (from < 0) {
+    from += GRN_TEXT_LEN(target);
+  }
+
   {
     const char *p;
     unsigned int cl = 0;
     start = GRN_TEXT_VALUE(target);
-    end = GRN_BULK_CURR(target);
+    end = start + GRN_TEXT_LEN(target);
     for (p = start; p < end && (cl = grn_charlen(ctx, p, end)); p += cl) {
       if (string_length == from) {
         start = p;
@@ -138,14 +245,9 @@ func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args,
     }
   }
 
-  grn_text = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, 0);
-  if (!grn_text) {
-    return NULL;
-  }
-
-  GRN_TEXT_SET(ctx, grn_text, start, end - start);
+  GRN_TEXT_SET(ctx, substring, start, end - start);
 
-  return grn_text;
+  return substring;
 }
 
 grn_rc

  Added: test/command/suite/select/function/string/string_substring/from_negative.expected (+38 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/function/string/string_substring/from_negative.expected    2016-07-05 20:18:08 +0900 (cc1bf59)
@@ -0,0 +1,38 @@
+plugin_register functions/string
+[[0,0.0,0.0],true]
+table_create Memos TABLE_HASH_KEY ShortText
+[[0,0.0,0.0],true]
+load --table Memos
+[
+{"_key": "Groonga"}
+]
+[[0,0.0,0.0],1]
+select Memos   --output_columns '_key, string_substring(_key, -3)'
+[
+  [
+    0,
+    0.0,
+    0.0
+  ],
+  [
+    [
+      [
+        1
+      ],
+      [
+        [
+          "_key",
+          "ShortText"
+        ],
+        [
+          "string_substring",
+          null
+        ]
+      ],
+      [
+        "Groonga",
+        "nga"
+      ]
+    ]
+  ]
+]

  Added: test/command/suite/select/function/string/string_substring/from_negative.test (+11 -0) 100644
===================================================================
--- /dev/null
+++ test/command/suite/select/function/string/string_substring/from_negative.test    2016-07-05 20:18:08 +0900 (5dbba48)
@@ -0,0 +1,11 @@
+plugin_register functions/string
+
+table_create Memos TABLE_HASH_KEY ShortText
+
+load --table Memos
+[
+{"_key": "Groonga"}
+]
+
+select Memos \
+  --output_columns '_key, string_substring(_key, -3)'
-------------- next part --------------
HTML����������������������������...
Télécharger 



More information about the Groonga-commit mailing list
Back to archive index