diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 53 | ||||
| -rw-r--r-- | src/class.c | 14 | ||||
| -rw-r--r-- | src/string.c | 75 |
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); } |
