]> granicus.if.org Git - onig/commitdiff
add onig_builtin_cmp()
authorK.Kosako <kosako@sofnec.co.jp>
Tue, 6 Mar 2018 05:05:20 +0000 (14:05 +0900)
committerK.Kosako <kosako@sofnec.co.jp>
Tue, 6 Mar 2018 05:05:20 +0000 (14:05 +0900)
src/oniguruma.h
src/regexec.c

index 38e9caad474bf32996183e4a8e25fe3d7fe5ed18..1e94d3ab57770c497c9c470cd208ed8d9302f140 100644 (file)
@@ -1015,6 +1015,8 @@ ONIG_EXTERN
 int onig_builtin_total_count P_((OnigCalloutArgs* args, void* user_data));
 ONIG_EXTERN
 int onig_builtin_max P_((OnigCalloutArgs* args, void* user_data));
+ONIG_EXTERN
+int onig_builtin_cmp P_((OnigCalloutArgs* args, void* user_data));
 
 ONIG_EXTERN
 int onig_setup_builtin_monitors_by_ascii_encoded_name P_((void));
index cdad343766d330d5a1a46b8b9ab926c159787461..155685ea495a32e9a4eeb01c13681087530e6854 100644 (file)
@@ -5381,6 +5381,131 @@ onig_builtin_max(OnigCalloutArgs* args, void* user_data ARG_UNUSED)
   return ONIG_CALLOUT_SUCCESS;
 }
 
+enum OP_CMP {
+  OP_EQ,
+  OP_NE,
+  OP_LT,
+  OP_GT,
+  OP_LE,
+  OP_GE
+};
+
+extern int
+onig_builtin_cmp(OnigCalloutArgs* args, void* user_data ARG_UNUSED)
+{
+  int r;
+  int num;
+  int slot;
+  long lv;
+  long rv;
+  OnigType  type;
+  OnigValue val;
+  regex_t* reg;
+  enum OP_CMP op;
+
+  reg = args->regex;
+
+  r = onig_get_arg_by_callout_args(args, 0, &type, &val);
+  if (r != ONIG_NORMAL) return r;
+
+  if (type == ONIG_TYPE_TAG) {
+    r = onig_get_callout_data_by_callout_num(reg, args->msa->mp, val.tag,
+                                             0, &type, &val);
+    if (r < ONIG_NORMAL) return r;
+    else if (r > ONIG_NORMAL)
+      lv = 0L;
+    else
+      lv = val.l;
+  }
+  else { /* ONIG_TYPE_LONG */
+    lv = val.l;
+  }
+
+  r = onig_get_arg_by_callout_args(args, 2, &type, &val);
+  if (r != ONIG_NORMAL) return r;
+
+  if (type == ONIG_TYPE_TAG) {
+    r = onig_get_callout_data_by_callout_num(reg, args->msa->mp, val.tag,
+                                             0, &type, &val);
+    if (r < ONIG_NORMAL) return r;
+    else if (r > ONIG_NORMAL)
+      rv = 0L;
+    else
+      rv = val.l;
+  }
+  else { /* ONIG_TYPE_LONG */
+    rv = val.l;
+  }
+
+  num = onig_get_callout_num_by_callout_args(args);
+  slot = 0;
+  r = onig_get_callout_data_by_callout_num(reg, args->msa->mp, num, slot,
+                                           &type, &val);
+  if (r < ONIG_NORMAL)
+    return r;
+  else if (r > ONIG_NORMAL) {
+    /* type == void: initial state */
+    OnigCodePoint c1, c2;
+    UChar* p;
+
+    r = onig_get_arg_by_callout_args(args, 1, &type, &val);
+    if (r != ONIG_NORMAL) return r;
+
+    p = val.s.start;
+    c1 = ONIGENC_MBC_TO_CODE(reg->enc, p, val.s.end);
+    p += ONIGENC_MBC_ENC_LEN(reg->enc, p);
+    if (p < val.s.end) {
+      c2 = ONIGENC_MBC_TO_CODE(reg->enc, p, val.s.end);
+      p += ONIGENC_MBC_ENC_LEN(reg->enc, p);
+      if (p != val.s.end)  return ONIGERR_INVALID_CALLOUT_ARG;
+    }
+    else
+      c2 = 0;
+
+    switch (c1) {
+    case '=':
+      if (c2 != '=') return ONIGERR_INVALID_CALLOUT_ARG;
+      op = OP_EQ;
+      break;
+    case '!':
+      if (c2 != '=') return ONIGERR_INVALID_CALLOUT_ARG;
+      op = OP_NE;
+      break;
+    case '<':
+      if (c2 == '=') op = OP_LE;
+      else if (c2 == 0) op = OP_LT;
+      else  return ONIGERR_INVALID_CALLOUT_ARG;
+      break;
+    case '>':
+      if (c2 == '=') op = OP_GE;
+      else if (c2 == 0) op = OP_GT;
+      else  return ONIGERR_INVALID_CALLOUT_ARG;
+      break;
+    default:
+      return ONIGERR_INVALID_CALLOUT_ARG;
+      break;
+    }
+    val.l = (long )op;
+    r = onig_set_callout_data_by_callout_num(reg, args->msa->mp, num, slot,
+                                             ONIG_TYPE_LONG, &val);
+    if (r != ONIG_NORMAL) return r;
+  }
+  else {
+    op = (enum OP_CMP )val.l;
+  }
+
+  switch (op) {
+  case OP_EQ: r = (lv == rv); break;
+  case OP_NE: r = (lv != rv); break;
+  case OP_LT: r = (lv <  rv); break;
+  case OP_GT: r = (lv >  rv); break;
+  case OP_LE: r = (lv <= rv); break;
+  case OP_GE: r = (lv >= rv); break;
+  }
+
+  return r == 0 ? ONIG_CALLOUT_FAIL : ONIG_CALLOUT_SUCCESS;
+}
+
 
 #include <stdio.h>