summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c53
-rw-r--r--src/class.c14
-rw-r--r--src/string.c75
3 files changed, 127 insertions, 15 deletions
diff --git a/src/array.c b/src/array.c
index 06c23dcd3..70e2fcab7 100644
--- a/src/array.c
+++ b/src/array.c
@@ -9,6 +9,8 @@
#include <mruby/class.h>
#include <mruby/string.h>
#include <mruby/range.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
#include "value_array.h"
#define ARY_DEFAULT_LEN 4
@@ -1257,6 +1259,55 @@ mrb_ary_svalue(mrb_state *mrb, mrb_value ary)
}
}
+static mrb_code each_iseq[] = {
+ OP_ENTER, 0x0, 0x00, 0x1, /* OP_ENTER 0:0:0:0:0:0:1 */
+ OP_JMPIF, 0x1, 0x0, 19, /* OP_JMPIF R1 19 */
+ OP_LOADSELF, 0x3, /* OP_LOADSELF R3 */
+ OP_LOADSYM, 0x4, 0x0, /* OP_LOADSYM R4 :each*/
+ OP_SEND, 0x3, 0x1, 0x1, /* OP_SEND R3 :to_enum 1 */
+ OP_RETURN, 0x3, /* OP_RETURN R3 */
+ OP_LOADI_0, 0x2, /* OP_LOADI_0 R2 */
+ OP_JMP, 0x0, 43, /* OP_JMP 49 */
+ OP_MOVE, 0x3, 0x1, /* OP_MOVE R3 R1 */
+ OP_LOADSELF, 0x4, /* OP_LOADSELF R4 */
+ OP_MOVE, 0x5, 0x2, /* OP_MOVE R5 R2 */
+ OP_SEND, 0x4, 0x2, 0x1, /* OP_SEND R4 :[] 1 */
+ OP_SEND, 0x3, 0x3, 0x1, /* OP_SEND R3 :call 1 */
+ OP_ADDI, 0x2, 1, /* OP_ADDI R3 1 */
+ OP_MOVE, 0x3, 0x2, /* OP_MOVE R3 R2 */
+ OP_LOADSELF, 0x4, /* OP_LOADSELF R4 */
+ OP_SEND, 0x4, 0x4, 0x0, /* OP_SEND R4 :length 0 */
+ OP_LT, 0x3, /* OP_LT R3 */
+ OP_JMPIF, 0x3, 0x0, 24, /* OP_JMPIF R3 24 */
+ OP_RETURN, 0x0 /* OP_RETURN R3 */
+};
+
+static void
+init_ary_each(mrb_state *mrb, struct RClass *ary)
+{
+ struct RProc *p;
+ mrb_method_t m;
+ mrb_irep *each_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
+ static const mrb_irep mrb_irep_zero = { 0 };
+
+ *each_irep = mrb_irep_zero;
+ each_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*5);
+ each_irep->syms[0] = mrb_intern_lit(mrb, "each");
+ each_irep->syms[1] = mrb_intern_lit(mrb, "to_enum");
+ each_irep->syms[2] = mrb_intern_lit(mrb, "[]");
+ each_irep->syms[3] = mrb_intern_lit(mrb, "call");
+ each_irep->syms[4] = mrb_intern_lit(mrb, "length");
+ each_irep->slen = 5;
+ each_irep->flags = MRB_ISEQ_NO_FREE;
+ each_irep->iseq = each_iseq;
+ each_irep->ilen = sizeof(each_iseq);
+ each_irep->nregs = 7;
+ each_irep->nlocals = 3;
+ p = mrb_proc_new(mrb, each_irep);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, ary, mrb_intern_lit(mrb, "each"), m);
+}
+
void
mrb_init_array(mrb_state *mrb)
{
@@ -1297,4 +1348,6 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
mrb_define_method(mrb, a, "__svalue", mrb_ary_svalue, MRB_ARGS_NONE());
+
+ init_ary_each(mrb, a);
}
diff --git a/src/class.c b/src/class.c
index e4fda18fc..7e37973f6 100644
--- a/src/class.c
+++ b/src/class.c
@@ -674,7 +674,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
if (i < argc) {
- *p = mrb_to_str(mrb, ARGV[arg_i++]);
+ *p = ARGV[arg_i++];
+ mrb_to_str(mrb, *p);
i++;
}
}
@@ -735,7 +736,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
if (i < argc) {
- ss = mrb_to_str(mrb, ARGV[arg_i++]);
+ ss = ARGV[arg_i++];
+ mrb_to_str(mrb, ss);
*ps = RSTRING_PTR(ss);
*pl = RSTRING_LEN(ss);
i++;
@@ -757,7 +759,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
if (i < argc) {
- ss = mrb_to_str(mrb, ARGV[arg_i++]);
+ ss = ARGV[arg_i++];
+ mrb_to_str(mrb, ss);
*ps = RSTRING_CSTR(mrb, ss);
i++;
}
@@ -1537,7 +1540,10 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv)
}
new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
mid = mrb_intern_lit(mrb, "initialize");
- if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) {
+ if (mrb_func_basic_p(mrb, new_class, mid, mrb_class_initialize)) {
+ mrb_class_initialize(mrb, new_class);
+ }
+ else {
mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
}
mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
diff --git a/src/string.c b/src/string.c
index 34ab2a51a..ab53c2e69 100644
--- a/src/string.c
+++ b/src/string.c
@@ -337,19 +337,69 @@ chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
/* map byte offset to character index */
static mrb_int
-bytes2chars(char *p, mrb_int bi)
+bytes2chars(char *p, mrb_int len, mrb_int bi)
{
- mrb_int i, b, n;
+ const char *e = p + (size_t)len;
+ const char *pivot = p + bi;
+ mrb_int i;
- for (b=i=0; b<bi; i++) {
- n = utf8len_codepage[(unsigned char)*p];
- b += n;
- p += n;
+ for (i = 0; p < pivot; i ++) {
+ p += utf8len(p, e);
}
- if (b != bi) return -1;
+ if (p != pivot) return -1;
return i;
}
+static const char *
+char_adjust(const char *beg, const char *end, const char *ptr)
+{
+ if ((ptr > beg || ptr < end) && (*ptr & 0xc0) == 0x80) {
+ const int utf8_adjust_max = 3;
+ const char *p;
+
+ if (ptr - beg > utf8_adjust_max) {
+ beg = ptr - utf8_adjust_max;
+ }
+
+ p = ptr;
+ while (p > beg) {
+ p --;
+ if ((*p & 0xc0) != 0x80) {
+ int clen = utf8len(p, end);
+ if (clen > ptr - p) return p;
+ break;
+ }
+ }
+ }
+
+ return ptr;
+}
+
+static const char *
+char_backtrack(const char *ptr, const char *end)
+{
+ if (ptr < end) {
+ const int utf8_bytelen_max = 4;
+ const char *p;
+
+ if (end - ptr > utf8_bytelen_max) {
+ ptr = end - utf8_bytelen_max;
+ }
+
+ p = end;
+ while (p > ptr) {
+ p --;
+ if ((*p & 0xc0) != 0x80) {
+ int clen = utf8len_codepage[(unsigned char)*p];
+ if (clen == end - p) { return p; }
+ break;
+ }
+ }
+ }
+
+ return end - 1;
+}
+
static mrb_int
str_index_str_by_char_search(mrb_state *mrb, const char *p, const char *pend, const char *s, const mrb_int slen, mrb_int off)
{
@@ -412,7 +462,9 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
#else
#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
#define chars2bytes(p, off, ci) (ci)
-#define bytes2chars(p, bi) (bi)
+#define bytes2chars(p, end, bi) (bi)
+#define char_adjust(beg, end, ptr) (ptr)
+#define char_backtrack(ptr, end) ((end) - 1)
#define BYTES_ALIGN_CHECK(pos)
#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
#endif
@@ -615,7 +667,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
static mrb_int
str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
{
- char *s, *sbeg, *t;
+ const char *s, *sbeg, *t;
struct RString *ps = mrb_str_ptr(str);
mrb_int len = RSTRING_LEN(sub);
@@ -628,11 +680,12 @@ str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
s = RSTR_PTR(ps) + pos;
t = RSTRING_PTR(sub);
if (len) {
+ s = char_adjust(sbeg, sbeg + RSTR_LEN(ps), s);
while (sbeg <= s) {
if (memcmp(s, t, len) == 0) {
return (mrb_int)(s - RSTR_PTR(ps));
}
- s--;
+ s = char_backtrack(sbeg, s);
}
return -1;
}
@@ -1995,7 +2048,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str)
case MRB_TT_STRING:
pos = str_rindex(mrb, str, sub, pos);
if (pos >= 0) {
- pos = bytes2chars(RSTRING_PTR(str), pos);
+ pos = bytes2chars(RSTRING_PTR(str), RSTRING_LEN(str), pos);
BYTES_ALIGN_CHECK(pos);
return mrb_fixnum_value(pos);
}