diff options
Diffstat (limited to 'mrbgems/mruby-string-ext/src')
| -rw-r--r-- | mrbgems/mruby-string-ext/src/string.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 9b317386e..460c8509e 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -252,7 +252,7 @@ enum tr_pattern_type { struct tr_pattern { uint8_t type; // 1:in-order, 2:range mrb_bool flag_reverse : 1; - mrb_bool flag_on_stack : 1; + mrb_bool flag_on_heap : 1; uint16_t n; union { uint16_t start_pos; @@ -261,14 +261,14 @@ struct tr_pattern { struct tr_pattern *next; }; -#define STATIC_TR_PATTERN { TR_UNINITIALIZED, FALSE, TRUE, 0, {}, NULL } +#define STATIC_TR_PATTERN { 0 } static inline void tr_free_pattern(mrb_state *mrb, struct tr_pattern *pat) { while (pat) { struct tr_pattern *p = pat->next; - if (!pat->flag_on_stack) { + if (pat->flag_on_heap) { mrb_free(mrb, pat); } pat = p; @@ -279,7 +279,7 @@ static struct tr_pattern* tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_pattern, mrb_bool flag_reverse_enable) { const char *pattern = RSTRING_PTR(v_pattern); - int pattern_length = RSTRING_LEN(v_pattern); + mrb_int pattern_length = RSTRING_LEN(v_pattern); mrb_bool flag_reverse = FALSE; struct tr_pattern *pat1; int i = 0; @@ -304,7 +304,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte } pat1->type = TR_RANGE; pat1->flag_reverse = flag_reverse; - pat1->flag_on_stack = ret_uninit; + pat1->flag_on_heap = !ret_uninit; pat1->n = pattern[i+2] - pattern[i] + 1; pat1->next = NULL; pat1->val.ch[0] = pattern[i]; @@ -328,7 +328,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte } pat1->type = TR_IN_ORDER; pat1->flag_reverse = flag_reverse; - pat1->flag_on_stack = ret_uninit; + pat1->flag_on_heap = !ret_uninit; pat1->n = len; pat1->next = NULL; pat1->val.start_pos = start_pos; @@ -368,7 +368,7 @@ tr_find_character(const struct tr_pattern *pat, const char *pat_str, int ch) ret = n_sum + ch - pat->val.ch[0]; } else { - mrb_assert(FALSE); // should not reach + mrb_assert(pat->type == TR_UNINITIALIZED); } n_sum += pat->n; pat = pat->next; @@ -384,13 +384,29 @@ static inline mrb_int tr_get_character(const struct tr_pattern *pat, const char *pat_str, mrb_int n_th) { mrb_int n_sum = 0; + while (pat != NULL) { if (n_th < (n_sum + pat->n)) { mrb_int i = (n_th - n_sum); - return (pat->type == TR_IN_ORDER) ? pat_str[pat->val.start_pos + i] :pat->val.ch[0] + i; + + switch (pat->type) { + case TR_IN_ORDER: + return pat_str[pat->val.start_pos + i]; + case TR_RANGE: + return pat->val.ch[0]+i; + case TR_UNINITIALIZED: + return -1; + } } if (pat->next == NULL) { - return (pat->type == TR_IN_ORDER) ? pat_str[pat->val.start_pos + pat->n - 1] : pat->val.ch[1]; + switch (pat->type) { + case TR_IN_ORDER: + return pat_str[pat->val.start_pos + pat->n - 1]; + case TR_RANGE: + return pat->val.ch[1]; + case TR_UNINITIALIZED: + return -1; + } } n_sum += pat->n; pat = pat->next; @@ -430,15 +446,16 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee else { mrb_int c = tr_get_character(rep, RSTRING_PTR(p2), n); - if (squeeze && c == lastch) { + if (c < 0 || (squeeze && c == lastch)) { j--; continue; } - if (c < 0 || c > 0x80) { + if (c > 0x80) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%S) out of range", mrb_fixnum_value((mrb_int)c)); } - lastch = s[i] = c; + lastch = c; + s[i] = (char)c; } } } |
